diff --git a/apps/1kv-backend/templates/kusama-otv-backend.yaml b/apps/1kv-backend/templates/kusama-otv-backend.yaml
index 45fd3fdbe..0f7cb4b67 100644
--- a/apps/1kv-backend/templates/kusama-otv-backend.yaml
+++ b/apps/1kv-backend/templates/kusama-otv-backend.yaml
@@ -17,7 +17,7 @@ spec:
source:
repoURL: https://w3f.github.io/helm-charts/
chart: otv-backend
- targetRevision: v3.1.2
+ targetRevision: v3.1.3
plugin:
env:
- name: HELM_VALUES
diff --git a/apps/1kv-backend/templates/polkadot-otv-backend.yaml b/apps/1kv-backend/templates/polkadot-otv-backend.yaml
index ea9948c59..d05ecf3e5 100644
--- a/apps/1kv-backend/templates/polkadot-otv-backend.yaml
+++ b/apps/1kv-backend/templates/polkadot-otv-backend.yaml
@@ -17,7 +17,7 @@ spec:
source:
repoURL: https://w3f.github.io/helm-charts/
chart: otv-backend
- targetRevision: v3.1.2
+ targetRevision: v3.1.3
plugin:
env:
- name: HELM_VALUES
diff --git a/charts/otv-backend/Chart.yaml b/charts/otv-backend/Chart.yaml
index ab0998573..1e78958d7 100644
--- a/charts/otv-backend/Chart.yaml
+++ b/charts/otv-backend/Chart.yaml
@@ -1,5 +1,5 @@
description: 1K Validators Backend
name: otv-backend
-version: v3.1.2
-appVersion: v3.1.2
+version: v3.1.3
+appVersion: v3.1.3
apiVersion: v2
diff --git a/package.json b/package.json
index ca5008c39..81e5edade 100644
--- a/package.json
+++ b/package.json
@@ -79,8 +79,8 @@
"typedoc-plugin-markdown": "^3.17.1"
},
"dependencies": {
- "@polkadot/api": "^10.11.2",
- "@polkadot/rpc-provider": "^10.11.2",
+ "@polkadot/api": "^10.12.1",
+ "@polkadot/rpc-provider": "^10.12.1",
"@types/ws": "^8.5.10",
"axios": "^1.6.7",
"chalk": "4.1.2",
diff --git a/packages/common/package.json b/packages/common/package.json
index a49a15382..5e20af2f2 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -1,6 +1,6 @@
{
"name": "@1kv/common",
- "version": "3.1.2",
+ "version": "3.1.3",
"description": "Services for running the Thousand Validator Program.",
"main": "build/index.js",
"types": "build/index.d.ts",
diff --git a/packages/common/src/chaindata/queries/Era.ts b/packages/common/src/chaindata/queries/Era.ts
index c4572db48..fd6f4ef1c 100644
--- a/packages/common/src/chaindata/queries/Era.ts
+++ b/packages/common/src/chaindata/queries/Era.ts
@@ -203,16 +203,17 @@ export const findEraBlockHash = async (
if (!blockHash) {
return ["", "Block hash is null"];
}
- const testEra =
- await chaindata?.api?.query.staking.activeEra.at(blockHash);
- if (testEra && testEra.isNone) {
- logger.info(`Test era is none`);
+ const apiAt = await chaindata?.api?.at(blockHash);
+ if (!apiAt) {
+ return ["", "API at block hash is null"];
+ }
+
+ const testEra = await apiAt.query.staking.currentEra();
+ if (testEra && testEra.isEmpty) {
+ logger.info(`Test era is empty: ${JSON.stringify(testEra)}`);
return ["", "Test era is none"];
}
- const testIndex =
- testEra && testEra?.unwrap && testEra?.unwrap().index?.toNumber()
- ? testEra?.unwrap().index.toNumber()
- : 0;
+ const testIndex = testEra.unwrap().toNumber();
if (era == testIndex) {
return [blockHash.toString(), null];
}
diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts
index 060e83827..8603c27d0 100644
--- a/packages/common/src/constants.ts
+++ b/packages/common/src/constants.ts
@@ -1,6 +1,8 @@
/// One week in milliseconds.
import WS from "ws";
+export const TWO_DAYS_IN_MS = 2 * 24 * 60 * 60 * 1000;
+
export const FIVE_MINUTES = 5 * 60 * 1000;
export const WEEK = 7 * 24 * 60 * 60 * 1000;
@@ -45,6 +47,9 @@ export const CHAINDATA_SLEEP = 300;
export const API_PROVIDER_TIMEOUT = 10000;
+// The number of eras a nominator should wait until making a next nomination
+export const NOMINATOR_SHOULD_NOMINATE_ERAS_THRESHOLD = 1;
+
/// List of Kusama endpoints we can switch between.
export const KusamaEndpoints = [
"wss://kusama-rpc-tn.dwellir.com",
@@ -100,8 +105,8 @@ export const TIME_DELAY_BLOCKS = 10850;
// The number of blocks after a time delay proxy call was announced that we want to cancel the tx. Should be 36 hours
export const CANCEL_THRESHOLD = 21700;
-// Monitor Cron job for checking if clients have upgraded. This runs ever 15 minutes by default
-export const MONITOR_CRON = "0 */15 * * * *";
+// Monitor Cron job for checking if clients have upgraded. This runs ever 3 minutes by default
+export const MONITOR_CRON = "0 */3 * * * *";
// Clear Offline Time Cron Job. This runs once every sunday by default
// export const CLEAR_OFFLINE_CRON = "0 0 0 * * 0";
diff --git a/packages/common/src/constraints/ScoreCandidates.ts b/packages/common/src/constraints/ScoreCandidates.ts
index 7cf9a2f69..e9216f1d0 100644
--- a/packages/common/src/constraints/ScoreCandidates.ts
+++ b/packages/common/src/constraints/ScoreCandidates.ts
@@ -210,7 +210,9 @@ export const scoreCandidate = async (
const nominatorStakeScore =
scaledNominatorStake * constraints.WEIGHT_CONFIG.NOMINATIONS_WEIGHT;
- const isAlternativeClient = candidate?.implementation != "Parity Polkadot";
+ const isAlternativeClient = candidate?.implementation
+ ? candidate?.implementation != "Parity Polkadot"
+ : false;
const clientScore = isAlternativeClient
? constraints.WEIGHT_CONFIG.CLIENT_WEIGHT
: 0;
diff --git a/packages/common/src/constraints/ValidityChecks.ts b/packages/common/src/constraints/ValidityChecks.ts
index 95444bb5f..85a507973 100644
--- a/packages/common/src/constraints/ValidityChecks.ts
+++ b/packages/common/src/constraints/ValidityChecks.ts
@@ -89,7 +89,7 @@ export const checkLatestClientVersion = async (
): Promise => {
try {
const skipClientUpgrade = config.constraints?.skipClientUpgrade || false;
- if (skipClientUpgrade!) {
+ if (!skipClientUpgrade) {
if (candidate?.implementation == "Kagome Node") {
await setLatestClientReleaseValidity(candidate.stash, true);
return true;
@@ -120,18 +120,19 @@ export const checkLatestClientVersion = async (
return true;
}
} else {
+ await setLatestClientReleaseValidity(candidate.stash, false);
return false;
}
} else {
await setLatestClientReleaseValidity(candidate.stash, true);
return true;
}
- return true;
} catch (e) {
logger.error(
`Error checking latest client version: ${e}`,
constraintsLabel,
);
+ await setLatestClientReleaseValidity(candidate.stash, false);
return false;
}
};
diff --git a/packages/common/src/db/models.ts b/packages/common/src/db/models.ts
index c1c384e68..73550cd9d 100644
--- a/packages/common/src/db/models.ts
+++ b/packages/common/src/db/models.ts
@@ -463,6 +463,12 @@ export const CandidateSchema = new Schema({
export const CandidateModel = mongoose.model("Candidate", CandidateSchema);
+export interface Era {
+ lastNominatedEraIndex: string;
+ nextNomination: number;
+ when: number;
+}
+
export const EraSchema = new Schema({
// The last era a nomination took place
lastNominatedEraIndex: { type: String, default: "0" },
@@ -726,6 +732,7 @@ export interface ValidatorScore {
nominatorStake: number;
// The randomness factor used to buffer the total
randomness: number;
+ client: number;
}
export const ValidatorScoreSchema = new Schema({
@@ -763,6 +770,7 @@ export const ValidatorScoreSchema = new Schema({
country: Number,
provider: Number,
nominatorStake: Number,
+ client: Number,
// The randomness factor used to buffer the total
randomness: Number,
});
diff --git a/packages/common/src/db/queries/Candidate.ts b/packages/common/src/db/queries/Candidate.ts
index d780b0bb8..358554bf0 100644
--- a/packages/common/src/db/queries/Candidate.ts
+++ b/packages/common/src/db/queries/Candidate.ts
@@ -334,7 +334,7 @@ export const getIdentityName = async (
.lean()
.select({ name: 1 });
- return identity?.name;
+ return identity?.name || null;
}
};
@@ -516,6 +516,7 @@ export const updateCandidateOnlineTelemetryDetails = async (
telemetryId: { $literal: telemetryNodeDetails.telemetryId },
onlineSince: { $literal: Date.now() },
offlineSince: { $literal: 0 },
+ version: telemetryNodeDetails.version,
implementation: {
$literal: telemetryNodeDetails.nodeImplementation,
},
diff --git a/packages/common/src/db/queries/Era.ts b/packages/common/src/db/queries/Era.ts
index 9c4a61d91..fe455e94b 100644
--- a/packages/common/src/db/queries/Era.ts
+++ b/packages/common/src/db/queries/Era.ts
@@ -1,33 +1,39 @@
-import { EraModel } from "../models";
+import { Era, EraModel } from "../models";
+import logger from "../../logger";
export const setLastNominatedEraIndex = async (
index: number,
): Promise => {
- const data = await EraModel.findOne({}).lean();
- if (!data) {
- const eraIndex = new EraModel({
- lastNominatedEraIndex: index.toString(),
- when: Date.now(),
- });
- await eraIndex.save();
- return true;
- }
-
- await EraModel.findOneAndUpdate(
- { lastNominatedEraIndex: /.*/ },
- {
- $set: {
+ try {
+ const data = await EraModel.findOne({}).lean();
+ if (!data) {
+ const eraIndex = new EraModel({
lastNominatedEraIndex: index.toString(),
when: Date.now(),
- nextNomination: Date.now() + 86400000,
+ });
+ await eraIndex.save();
+ return true;
+ }
+
+ await EraModel.findOneAndUpdate(
+ { lastNominatedEraIndex: /.*/ },
+ {
+ $set: {
+ lastNominatedEraIndex: index.toString(),
+ when: Date.now(),
+ nextNomination: Date.now() + 86400000,
+ },
},
- },
- ).exec();
- return true;
+ ).exec();
+ return true;
+ } catch (e) {
+ logger.error(
+ `Error setting last nominated era index: ${JSON.stringify(e)}`,
+ );
+ return false;
+ }
};
-export const getLastNominatedEraIndex = async (): Promise => {
- return EraModel.findOne({ lastNominatedEraIndex: /[0-9]+/ })
- .lean()
- .exec();
+export const getLastNominatedEraIndex = async (): Promise => {
+ return EraModel.findOne({ lastNominatedEraIndex: /[0-9]+/ }).lean();
};
diff --git a/packages/common/src/db/queries/Location.ts b/packages/common/src/db/queries/Location.ts
index f3ecd9cc9..fff69cb72 100644
--- a/packages/common/src/db/queries/Location.ts
+++ b/packages/common/src/db/queries/Location.ts
@@ -9,6 +9,7 @@ import { logger } from "../../index";
import { getLatestSession } from "./Session";
import { HardwareSpec } from "../../types";
import { dbLabel } from "../index";
+import { TWO_DAYS_IN_MS } from "../../constants";
export const getAllLocations = async (): Promise => {
return LocationModel.find({}).lean();
@@ -131,6 +132,22 @@ export const cleanBlankLocations = async (): Promise => {
}).exec();
};
+// Remove all location data older than two days
+export const cleanOldLocations = async (): Promise => {
+ const twoDaysAgo = Date.now() - TWO_DAYS_IN_MS;
+
+ try {
+ await LocationModel.deleteMany({ updated: { $lt: twoDaysAgo } }).exec();
+ return true;
+ } catch (error) {
+ logger.info(
+ `Error cleaning old locations: ${JSON.stringify(error)}`,
+ dbLabel,
+ );
+ return false;
+ }
+};
+
// Sets a location from heartbeats
export const iitExists = async (): Promise => {
diff --git a/packages/common/src/db/queries/NominatorStake.ts b/packages/common/src/db/queries/NominatorStake.ts
index 75676776e..5ced1250f 100644
--- a/packages/common/src/db/queries/NominatorStake.ts
+++ b/packages/common/src/db/queries/NominatorStake.ts
@@ -1,4 +1,7 @@
import { NominatorStake, NominatorStakeModel } from "../models";
+import { TWO_DAYS_IN_MS } from "../../constants";
+import { logger } from "../../index";
+import { dbLabel } from "../index";
export const setNominatorStake = async (
validator: string,
@@ -84,3 +87,20 @@ export const getNominatorStake = async (
.sort("-era")
.limit(limit ? limit : 100);
};
+
+export const cleanOldNominatorStakes = async (): Promise => {
+ const twoDaysAgo = Date.now() - TWO_DAYS_IN_MS;
+
+ try {
+ await NominatorStakeModel.deleteMany({
+ updated: { $lt: twoDaysAgo },
+ }).exec();
+ return true;
+ } catch (error) {
+ logger.info(
+ `Error cleaning old nominator stakes: ${JSON.stringify(error)}`,
+ dbLabel,
+ );
+ return false;
+ }
+};
diff --git a/packages/common/src/db/queries/ValidatorScore.ts b/packages/common/src/db/queries/ValidatorScore.ts
index b0cdbeeed..9a45e5a6c 100644
--- a/packages/common/src/db/queries/ValidatorScore.ts
+++ b/packages/common/src/db/queries/ValidatorScore.ts
@@ -1,4 +1,5 @@
import { ValidatorScore, ValidatorScoreModel } from "../models";
+import { TWO_DAYS_IN_MS } from "../../constants";
export const setValidatorScore = async (
address: string,
@@ -25,6 +26,7 @@ export const setValidatorScore = async (
nominatorStake,
randomness,
updated,
+ client,
} = score;
const data = await ValidatorScoreModel.findOne({
@@ -54,6 +56,7 @@ export const setValidatorScore = async (
provider,
nominatorStake,
randomness,
+ client,
});
await score.save();
return true;
@@ -82,6 +85,7 @@ export const setValidatorScore = async (
country,
provider,
nominatorStake,
+ client,
randomness,
},
).exec();
@@ -107,7 +111,7 @@ export const getValidatorScore = async (
export const getLatestValidatorScore = async (
address: string,
-): Promise => {
+): Promise => {
return ValidatorScoreModel.findOne({ address: address }, { _id: 0, __v: 0 })
.sort({ session: -1 })
.limit(1)
@@ -115,10 +119,7 @@ export const getLatestValidatorScore = async (
};
export const deleteOldValidatorScores = async (): Promise => {
- const FIVE_MINUTES = 300000;
- const ONE_WEEK = 604800016.56;
- const ONE_MONTH = 2629800000;
- const timeWindow = Date.now() - ONE_WEEK;
+ const timeWindow = Date.now() - TWO_DAYS_IN_MS;
const scoreToDelete = await ValidatorScoreModel.find({
updated: { $lt: timeWindow },
}).exec();
diff --git a/packages/common/src/db/queries/Validators.ts b/packages/common/src/db/queries/Validators.ts
index c09522bc0..856488963 100644
--- a/packages/common/src/db/queries/Validators.ts
+++ b/packages/common/src/db/queries/Validators.ts
@@ -5,7 +5,7 @@ import {
ValidatorSet,
ValidatorSetModel,
} from "../models";
-import { allCandidates } from "./Candidate";
+import { allCandidates, getIdentityAddresses } from "./Candidate";
import { NextKeys } from "../../chaindata/queries/ValidatorPref";
export const setValidatorSet = async (
@@ -44,10 +44,7 @@ export const getLatestValidatorSet = async (): Promise => {
};
export const getAllValidatorSets = async (): Promise => {
- return ValidatorSetModel.find({})
- .sort({ era: -1 })
- .lean()
- .exec();
+ return ValidatorSetModel.find({}).sort({ era: -1 }).lean();
};
export const validatorSetExistsForEra = async (
@@ -170,3 +167,36 @@ export const hasBeefyDummy = async (address: string): Promise => {
const validator = await getValidator(address);
return validator?.keys?.beefy?.slice(0, 10) == "0x62656566";
};
+
+// TODO: add tests
+// Returns the number of eras a validator stash has been active
+export const getValidatorActiveEras = async (
+ stash: string,
+): Promise => {
+ let count = 0;
+ const validatorSets = await getAllValidatorSets();
+ for (const era of validatorSets) {
+ if (era.validators.includes(stash)) {
+ count++;
+ }
+ }
+ return count;
+};
+
+// TODO: add tests
+// return the number of eras
+export const getIdentityValidatorActiveEras = async (
+ address: string,
+): Promise => {
+ const identityAddresses = await getIdentityAddresses(address);
+ let count = 0;
+ const validatorSets = await getAllValidatorSets();
+ for (const era of validatorSets) {
+ if (
+ era.validators.some((validator) => identityAddresses.includes(validator))
+ ) {
+ count++;
+ }
+ }
+ return count;
+};
diff --git a/packages/common/src/nominator/NominatorChainInfo.ts b/packages/common/src/nominator/NominatorChainInfo.ts
new file mode 100644
index 000000000..26f1e8e14
--- /dev/null
+++ b/packages/common/src/nominator/NominatorChainInfo.ts
@@ -0,0 +1,126 @@
+import Nominator from "./nominator";
+import { queries } from "../index";
+import { NOMINATOR_SHOULD_NOMINATE_ERAS_THRESHOLD } from "../constants";
+import { NominatorState } from "../types";
+
+// Query on-chain info for a nominator
+export const getNominatorChainInfo = async (nominator: Nominator) => {
+ const stash = await nominator.stash();
+ const isBonded = await nominator.chaindata.isBonded(stash);
+ const [bonded, err] = await nominator.chaindata.getDenomBondedAmount(stash);
+ const currentBlock = (await nominator.chaindata.getLatestBlock()) || 0;
+
+ const currentEra = (await nominator.chaindata.getCurrentEra()) || 0;
+ const lastNominationEra =
+ (await nominator.chaindata.getNominatorLastNominationEra(stash)) || 0;
+ nominator.lastEraNomination = lastNominationEra;
+ const currentTargets =
+ (await nominator.chaindata.getNominatorCurrentTargets(stash)) || [];
+ const currentNamedTargets = await Promise.all(
+ currentTargets.map(async (target) => {
+ const kyc = await queries.isKYC(target);
+ let name = await queries.getIdentityName(target);
+ if (!name) {
+ name =
+ (await nominator.chaindata.getFormattedIdentity(target))?.name || "";
+ }
+
+ const scoreResult = await queries.getLatestValidatorScore(target);
+ const score = scoreResult && scoreResult.total ? scoreResult.total : 0;
+
+ return {
+ stash: target,
+ name: name || "",
+ kyc: kyc || false,
+ score: score,
+ };
+ }),
+ );
+
+ const proxyAnnouncements = await queries.getAccountDelayedTx(
+ nominator.bondedAddress,
+ );
+
+ const namedProxyTargets = await Promise.all(
+ (proxyAnnouncements || []).map(async (announcement) => {
+ const namedTargets = await Promise.all(
+ announcement.targets.map(async (target) => {
+ const kyc = await queries.isKYC(target);
+ let name = await queries.getIdentityName(target);
+
+ if (!name) {
+ const formattedIdentity =
+ await nominator.chaindata.getFormattedIdentity(target);
+ name = formattedIdentity?.name || "";
+ }
+
+ const scoreResult = await queries.getLatestValidatorScore(target);
+ const score =
+ scoreResult && scoreResult.total ? scoreResult.total : 0;
+
+ return {
+ stash: target,
+ name: name || "",
+ kyc: kyc || false,
+ score: score,
+ };
+ }),
+ );
+ const executionMsTime =
+ (nominator.proxyDelay + currentBlock - announcement.number) * 6 * 1000;
+ return {
+ ...announcement,
+ targets: namedTargets,
+ executionTime: executionMsTime,
+ };
+ }),
+ );
+
+ const shouldNominate =
+ bonded > 50 &&
+ isBonded &&
+ currentEra - lastNominationEra >=
+ NOMINATOR_SHOULD_NOMINATE_ERAS_THRESHOLD &&
+ proxyAnnouncements.length == 0;
+
+ let status;
+
+ if (namedProxyTargets.length > 0) {
+ `Pending Proxy Execution at #${namedProxyTargets[0].number}`;
+ } else if (shouldNominate) {
+ status = "Awaiting New Nomination";
+ } else if (lastNominationEra == 0) {
+ status = "Not Nominating Anyone";
+ } else {
+ status = `Nominating, last nomination era: ${lastNominationEra} current era: ${currentEra}`;
+ }
+
+ let state;
+ if (shouldNominate) {
+ state = NominatorState.ReadyToNominate;
+ } else if (namedProxyTargets.length > 0) {
+ state = NominatorState.AwaitingProxyExecution;
+ } else if (lastNominationEra == 0) {
+ state = NominatorState.NotNominating;
+ } else if (namedProxyTargets.length == 0 && lastNominationEra > 0) {
+ state = NominatorState.Nominated;
+ }
+
+ const stale =
+ isBonded &&
+ currentEra - lastNominationEra > 8 &&
+ proxyAnnouncements.length == 0 &&
+ bonded > 50;
+
+ return {
+ state: state,
+ status: status,
+ isBonded: isBonded,
+ bondedAmount: Number(bonded),
+ lastNominationEra: lastNominationEra,
+ currentTargets: currentNamedTargets,
+ proxyAnnouncements: namedProxyTargets,
+ shouldNominate: shouldNominate,
+ stale: stale,
+ };
+};
diff --git a/packages/common/src/nominator/NominatorTx.ts b/packages/common/src/nominator/NominatorTx.ts
index e45361f67..7a1273c5a 100644
--- a/packages/common/src/nominator/NominatorTx.ts
+++ b/packages/common/src/nominator/NominatorTx.ts
@@ -2,9 +2,10 @@ import logger from "../logger";
import { blake2AsHex } from "@polkadot/util-crypto";
import { DelayedTx } from "../db";
import { ChainData, queries } from "../index";
-import Nominator, { nominatorLabel } from "./nominator";
import { ApiPromise } from "@polkadot/api";
import MatrixBot from "../matrix";
+import Nominator, { nominatorLabel } from "./nominator";
+import { NominatorState } from "../types";
// Sends a Proxy Delay Nominate Tx for a given nominator
// TODO: unit tests
@@ -20,7 +21,8 @@ export const sendProxyDelayTx = async (
`{Nominator::nominate::proxy} starting tx for ${nominator.address} with proxy delay ${nominator.proxyDelay} blocks`,
nominatorLabel,
);
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
+ state: NominatorState.Nominating,
status: `[noninate] starting proxy delay tx`,
updated: Date.now(),
stale: false,
@@ -34,7 +36,7 @@ export const sendProxyDelayTx = async (
`{Nominator::nominate} there was an error getting the current block`,
nominatorLabel,
);
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
status: `[noninate] err: no current block`,
updated: Date.now(),
stale: false,
@@ -55,7 +57,8 @@ export const sendProxyDelayTx = async (
callHash,
};
await queries.addDelayedTx(delayedTx);
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
+ state: NominatorState.Nominating,
status: `[noninate] tx: ${JSON.stringify(delayedTx)}`,
updated: Date.now(),
stale: false,
@@ -64,7 +67,8 @@ export const sendProxyDelayTx = async (
const allProxyTxs = await queries.getAllDelayedTxs();
const didSend = await nominator.signAndSendTx(tx);
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
+ state: NominatorState.AwaitingProxyExecution,
status: `Announced Proxy Tx: ${didSend}`,
nextTargets: targets,
updated: Date.now(),
@@ -79,7 +83,7 @@ export const sendProxyDelayTx = async (
nominatorLabel,
);
logger.error(JSON.stringify(e), nominatorLabel);
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
status: `Proxy Delay Error: ${JSON.stringify(e)}`,
updated: Date.now(),
});
@@ -144,16 +148,20 @@ export const sendProxyTx = async (
targets.map(async (val) => {
const name = await queries.getIdentityName(val);
const kyc = await queries.isKYC(val);
+ const scoreResult = await queries.getLatestValidatorScore(val);
+ const score = scoreResult && scoreResult.total ? scoreResult.total : 0;
return {
address: val,
- name: name,
- kyc: kyc,
+ name: name || "",
+ kyc: kyc || false,
+ score: score,
};
}),
);
- const currentEra = await chaindata.getCurrentEra();
+ const currentEra = (await chaindata.getCurrentEra()) || 0;
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
+ state: NominatorState.AwaitingProxyExecution,
status: "Submitted Proxy Tx",
currentTargets: namedTargets,
updated: Date.now(),
@@ -172,7 +180,7 @@ export const sendProxyTx = async (
nominatorLabel,
);
logger.error(JSON.stringify(e), nominatorLabel);
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
status: `Proxy Error: ${JSON.stringify(e)}`,
updated: Date.now(),
});
diff --git a/packages/common/src/nominator/__mocks__/nominator.ts b/packages/common/src/nominator/__mocks__/nominator.ts
index a226b9e99..ed8e876b4 100644
--- a/packages/common/src/nominator/__mocks__/nominator.ts
+++ b/packages/common/src/nominator/__mocks__/nominator.ts
@@ -100,6 +100,10 @@ class NominatorMock {
async sendStakingTx(tx: any, targets: string[]): Promise {
return true;
}
+
+ async updateNominatorStatus(): Promise {
+ return true;
+ }
}
export default NominatorMock;
diff --git a/packages/common/src/nominator/nominator.ts b/packages/common/src/nominator/nominator.ts
index e8fe7d9fb..9197440ac 100644
--- a/packages/common/src/nominator/nominator.ts
+++ b/packages/common/src/nominator/nominator.ts
@@ -7,38 +7,11 @@ import { ChainData, Constants, queries, Types } from "../index";
import logger from "../logger";
import EventEmitter from "eventemitter3";
import { sendProxyDelayTx, sendProxyTx } from "./NominatorTx";
+import { getNominatorChainInfo } from "./NominatorChainInfo";
+import { NominatorState, NominatorStatus } from "../types";
export const nominatorLabel = { label: "Nominator" };
-export interface NominatorStatus {
- status?: string;
- isBonded?: boolean;
- bondedAddress?: string;
- bondedAmount?: number;
- stashAddress?: string;
- proxyAddress?: string;
- isProxy?: boolean;
- proxyDelay?: number;
- isNominating?: boolean;
- lastNominationEra?: number;
- lastNominationTime?: number;
- currentTargets?:
- | string[]
- | {
- stash?: string;
- name?: string;
- kyc?: boolean;
- score?: string | number;
- }[];
- nextTargets?: string[];
- proxyTxs?: any[];
- updated: number;
- rewardDestination?: string;
- stale?: boolean;
- dryRun?: boolean;
- shouldNominate?: boolean;
-}
-
export default class Nominator extends EventEmitter {
public currentlyNominating: Types.Stash[] = [];
@@ -57,12 +30,7 @@ export default class Nominator extends EventEmitter {
// The amount of blocks for a time delay proxy
private _proxyDelay: number;
- private _canNominate: { canNominate: boolean; reason: string } = {
- canNominate: false,
- reason: "",
- };
-
- public lastEraNomination: number;
+ public lastEraNomination = 0;
public _shouldNominate = false;
@@ -99,15 +67,6 @@ export default class Nominator extends EventEmitter {
this._proxyDelay =
cfg.proxyDelay == 0 ? cfg.proxyDelay : Constants.TIME_DELAY_BLOCKS;
- logger.info(
- `{nominator::proxyDelay} config proxy delay: ${cfg.proxyDelay}`,
- nominatorLabel,
- );
- logger.info(
- `{nominator::proxy} nominator proxy delay: ${this._proxyDelay}`,
- nominatorLabel,
- );
-
const keyring = new Keyring({
type: "sr25519",
});
@@ -120,9 +79,9 @@ export default class Nominator extends EventEmitter {
: this.signer.address;
logger.info(
- `(Nominator::constructor) Nominator signer spawned: ${this.address} | ${
+ `(Nominator::constructor) Nominator spawned: ${this.address} | ${
this._isProxy ? "Proxy" : "Controller"
- }`,
+ } ${this._proxyDelay ? `| Delay: ${this._proxyDelay}` : ""} bonded address: ${this._bondedAddress}`,
nominatorLabel,
);
}
@@ -131,143 +90,80 @@ export default class Nominator extends EventEmitter {
return this._status;
};
- public updateNominatorStatus = (newStatus: NominatorStatus) => {
- this._status = { ...this._status, ...newStatus };
- };
+ public async updateNominatorStatus(newStatus: NominatorStatus) {
+ // Always update on-chain data for status
+ const nominatorInfo = await getNominatorChainInfo(this);
+ const {
+ isBonded,
+ bondedAmount,
+ lastNominationEra,
+ proxyAnnouncements,
+ stale,
+ } = nominatorInfo;
+
+ this._status = {
+ ...this._status,
+ ...newStatus,
+ isBonded,
+ bondedAmount,
+ lastNominationEra,
+ proxyTxs: proxyAnnouncements,
+ stale,
+ };
+ }
public async shouldNominate(): Promise {
const stash = await this.stash();
const isBonded = await this.chaindata.isBonded(stash);
const [bonded, err] = await this.chaindata.getDenomBondedAmount(stash);
const proxyTxs = await queries.getAccountDelayedTx(this.bondedAddress);
+ const lastNominationEra =
+ (await this.chaindata.getNominatorLastNominationEra(stash)) || 0;
+ this.lastEraNomination = lastNominationEra;
const currentEra = (await this.chaindata.getCurrentEra()) || 0;
this._shouldNominate =
isBonded &&
bonded > 50 &&
- currentEra - this.lastEraNomination >= 1 &&
+ currentEra - lastNominationEra >= 1 &&
proxyTxs.length == 0;
return this._shouldNominate;
}
- public async init(): Promise {
+ public async init(): Promise {
try {
- const stash = await this.stash();
- const isBonded = await this.chaindata.isBonded(stash);
- const [bonded, err] = await this.chaindata.getDenomBondedAmount(stash);
- const currentBlock = await this.chaindata.getLatestBlock();
-
- const currentEra = (await this.chaindata.getCurrentEra()) || 0;
- const lastNominationEra =
- (await this.chaindata.getNominatorLastNominationEra(stash)) || 0;
- this.lastEraNomination = lastNominationEra;
- const currentTargets =
- (await this.chaindata.getNominatorCurrentTargets(stash)) || [];
- const currentNamedTargets = await Promise.all(
- currentTargets.map(async (target) => {
- const kyc = await queries.isKYC(target);
- let name = await queries.getIdentityName(target);
- if (!name) {
- name = (await this.chaindata.getFormattedIdentity(target))?.name;
- }
-
- const scoreResult = await queries.getLatestValidatorScore(target);
- const score =
- scoreResult && scoreResult.total ? scoreResult.total : 0;
-
- return {
- stash: target,
- name: name,
- kyc: kyc,
- score: score,
- };
- }),
- );
-
- const proxyAnnouncements = await queries.getAccountDelayedTx(
- this.bondedAddress,
- );
-
- const namedProxyTargets = await Promise.all(
- (proxyAnnouncements || []).map(async (announcement) => {
- const namedTargets = await Promise.all(
- announcement.targets.map(async (target) => {
- const kyc = await queries.isKYC(target);
- let name = await queries.getIdentityName(target);
-
- if (!name) {
- const formattedIdentity =
- await this.chaindata.getFormattedIdentity(target);
- name = formattedIdentity?.name;
- }
-
- const scoreResult = await queries.getLatestValidatorScore(target);
- const score =
- scoreResult && scoreResult.total ? scoreResult.total : 0;
-
- return {
- stash: target,
- name: name,
- kyc: kyc,
- score: score,
- };
- }),
- );
- const executionMsTime =
- (this._proxyDelay + currentBlock - announcement.number) * 6 * 1000;
- return {
- ...announcement,
- targets: namedTargets,
- executionTime: executionMsTime,
- };
- }),
- );
-
- this._shouldNominate =
- bonded > 50 &&
- isBonded &&
- currentEra - lastNominationEra >= 1 &&
- proxyAnnouncements.length == 0;
-
- const rewardDestination = await this.payee();
-
- let nominationStatus;
- if (proxyAnnouncements.length > 0) {
- nominationStatus = "Announced Proxy Tx";
- } else if (this._shouldNominate) {
- nominationStatus = "Initialized";
- } else {
- nominationStatus = "Existing Recent Nomination";
- }
-
- const stale =
- isBonded &&
- currentEra - lastNominationEra > 8 &&
- proxyAnnouncements.length == 0 &&
- bonded > 50;
+ const nominatorInfo = await getNominatorChainInfo(this);
+ const {
+ state,
+ status: nominatorStatus,
+ isBonded,
+ bondedAmount,
+ currentTargets,
+ lastNominationEra,
+ proxyAnnouncements,
+ stale,
+ } = nominatorInfo;
const status: NominatorStatus = {
- status: nominationStatus,
+ state: state,
+ status: nominatorStatus,
bondedAddress: this.bondedAddress,
stashAddress: await this.stash(),
- bondedAmount: Number(bonded),
+ bondedAmount: bondedAmount,
isBonded: isBonded,
isProxy: this._isProxy,
proxyDelay: this._proxyDelay,
proxyAddress: this.signer.address,
- rewardDestination: rewardDestination,
+ rewardDestination: await this.payee(),
lastNominationEra: lastNominationEra,
- currentTargets: currentNamedTargets,
- proxyTxs: namedProxyTargets,
+ currentTargets: currentTargets,
+ proxyTxs: proxyAnnouncements,
stale: stale,
dryRun: this._dryRun,
updated: Date.now(),
shouldNominate: this._shouldNominate,
};
- this.updateNominatorStatus(status);
- this._canNominate = {
- canNominate: isBonded,
- reason: isBonded ? "Bonded" : "Not bonded",
- };
+ await this.updateNominatorStatus(status);
+
return status;
} catch (e) {
logger.error(`Error getting status for ${this.bondedAddress}: ${e}`);
@@ -362,7 +258,8 @@ export default class Nominator extends EventEmitter {
try {
if (this._dryRun) {
logger.info(`DRY RUN ENABLED, SKIPPING TX`, nominatorLabel);
- this.updateNominatorStatus({
+ await this.updateNominatorStatus({
+ state: NominatorState.Nominating,
status: `[signAndSend] DRY RUN TX`,
updated: Date.now(),
stale: false,
@@ -371,7 +268,8 @@ export default class Nominator extends EventEmitter {
} else {
logger.info(`Sending tx: ${tx.method.toString()}`, nominatorLabel);
await tx.signAndSend(this.signer);
- this.updateNominatorStatus({
+ await this.updateNominatorStatus({
+ state: NominatorState.Nominated,
status: `[signAndSend] signed and sent tx`,
updated: Date.now(),
stale: false,
@@ -382,7 +280,7 @@ export default class Nominator extends EventEmitter {
} catch (e) {
logger.error(`Error sending tx: `, nominatorLabel);
logger.error(JSON.stringify(e), nominatorLabel);
- this.updateNominatorStatus({
+ await this.updateNominatorStatus({
status: `[signAndSend] Error signing and sending tx: ${JSON.stringify(e)}`,
updated: Date.now(),
stale: false,
@@ -402,14 +300,15 @@ export default class Nominator extends EventEmitter {
return false;
}
- const currentEra = await this.chaindata.getCurrentEra();
+ const currentEra = (await this.chaindata.getCurrentEra()) || 0;
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `[nominate] start`,
updated: Date.now(),
stale: false,
};
- this.updateNominatorStatus(nominatorStatus);
+ await this.updateNominatorStatus(nominatorStatus);
let isBonded;
try {
const stash = await this.stash();
@@ -421,7 +320,8 @@ export default class Nominator extends EventEmitter {
}
logger.info(`nominator is bonded: ${isBonded}`, nominatorLabel);
- this.updateNominatorStatus({
+ await this.updateNominatorStatus({
+ state: NominatorState.Nominating,
status: `[nominate] bonded; ${isBonded}`,
updated: Date.now(),
stale: false,
@@ -438,7 +338,8 @@ export default class Nominator extends EventEmitter {
);
// Start an announcement for a delayed proxy tx
if (this._isProxy && this._proxyDelay > 0) {
- this.updateNominatorStatus({
+ await this.updateNominatorStatus({
+ state: NominatorState.Nominating,
status: `[nominate] proxy ${this._isProxy}; delay ${this._proxyDelay}`,
updated: Date.now(),
stale: false,
@@ -519,36 +420,37 @@ export default class Nominator extends EventEmitter {
// If Dry Run is enabled in the config, nominations will be stubbed but not executed
if (this._dryRun) {
logger.info(`DRY RUN ENABLED, SKIPPING TX`, nominatorLabel);
- const currentEra = await this.chaindata.getCurrentEra();
+ const currentEra = (await this.chaindata.getCurrentEra()) || 0;
const namedTargets = await Promise.all(
targets.map(async (target) => {
- const kyc = await queries.isKYC(target);
- let name = await queries.getIdentityName(target);
+ const kyc = (await queries.isKYC(target)) || false;
+ let name = (await queries.getIdentityName(target)) || "";
// Fetch name using chaindata.getFormattedIdentity only if the name wasn't found initially
if (!name) {
const formattedIdentity =
await this.chaindata.getFormattedIdentity(target);
- name = formattedIdentity?.name;
+ name = formattedIdentity?.name || "";
}
return {
stash: target,
- name, // shorthand for name: name
- kyc, // shorthand for kyc: kyc
+ name: name || "",
+ kyc: kyc || false,
score: 0,
};
}),
);
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `Dry Run: Nominated ${targets.length} validators`,
updated: Date.now(),
stale: false,
currentTargets: namedTargets,
lastNominationEra: currentEra,
};
- this.updateNominatorStatus(nominatorStatus);
+ await this.updateNominatorStatus(nominatorStatus);
// `dryRun` return as blockhash is checked elsewhere to finish the hook of writing db entries
return [false, "dryRun"];
}
@@ -683,37 +585,39 @@ export default class Nominator extends EventEmitter {
break;
}
});
- const currentEra = await this.chaindata.getCurrentEra();
+ const currentEra = (await this.chaindata.getCurrentEra()) || 0;
const namedTargets = await Promise.all(
targets.map(async (target) => {
const kyc = await queries.isKYC(target);
let name = await queries.getIdentityName(target);
if (!name) {
- name = (await this.chaindata.getFormattedIdentity(target))?.name;
+ name =
+ (await this.chaindata.getFormattedIdentity(target))?.name || "";
}
const score = await queries.getLatestValidatorScore(target);
return {
stash: target,
- name: name,
- kyc: kyc,
- score: score && score[0] && score[0].total ? score[0].total : 0,
+ name: name || "",
+ kyc: kyc || false,
+ score: score && score && score?.total ? score?.total : 0,
};
}),
);
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominated,
status: `Nominated ${targets.length} validators: ${didSend} ${finalizedBlockHash}`,
updated: Date.now(),
stale: false,
currentTargets: namedTargets,
lastNominationEra: currentEra,
};
- this.updateNominatorStatus(nominatorStatus);
+ await this.updateNominatorStatus(nominatorStatus);
return [didSend, finalizedBlockHash || null]; // Change to return undefined
} catch (e) {
logger.error(`Error sending tx: ${JSON.stringify(e)}`, nominatorLabel);
- return [false, e];
+ return [false, JSON.stringify(e)];
}
};
}
diff --git a/packages/common/src/scorekeeper/Nominating.ts b/packages/common/src/scorekeeper/Nominating.ts
index eab542e52..4e793ef87 100644
--- a/packages/common/src/scorekeeper/Nominating.ts
+++ b/packages/common/src/scorekeeper/Nominating.ts
@@ -10,7 +10,8 @@ import { ChainData, queries, Util } from "../index";
import ApiHandler from "../ApiHandler/ApiHandler";
import MatrixBot from "../matrix";
import { ConfigSchema } from "../config";
-import Nominator, { NominatorStatus } from "../nominator/nominator";
+import Nominator from "../nominator/nominator";
+import { NominatorState, NominatorStatus } from "../types";
// Takes in a list of valid Candidates, and will nominate them based on the nominator groups
export const doNominations = async (
@@ -31,20 +32,6 @@ export const doNominations = async (
return null;
}
- for (const nom of nominatorGroups) {
- const nominatorStatus: NominatorStatus = {
- status: `Doing Nominations.....`,
- updated: Date.now(),
- stale: false,
- };
- nom.updateNominatorStatus(nominatorStatus);
- }
-
- const allTargets = candidates.map((c) => {
- return { stash: c.stash };
- });
- let counter = 0;
-
const currentEra = await chaindata.getCurrentEra();
if (!currentEra) {
logger.error(
@@ -54,22 +41,32 @@ export const doNominations = async (
return null;
}
+ // The list of all valid Validators to nominate
+ const allTargets = candidates.map((c) => {
+ return { stash: c.stash };
+ });
+
+ // A counter to keep track of the number of nominations
+ let counter = 0;
+
for (const nominator of nominatorGroups) {
- const nomStash = await nominator.stash();
- const nominatorLastNominated =
- await chaindata.getNominatorLastNominationEra(nomStash);
- if (nominatorLastNominated + 4 > currentEra) {
+ const stash = await nominator.stash();
+ const shouldNominate = await nominator.shouldNominate();
+ if (!shouldNominate) {
logger.info(
- `Nominator ${nomStash} has already nominated this era: ${nominatorLastNominated}`,
+ `Nominator ${stash} has already nominated in era: ${nominator.lastEraNomination} (current era: ${currentEra}) - Skipping`,
);
continue;
}
+
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `Nominating...`,
updated: Date.now(),
stale: false,
};
- nominator.updateNominatorStatus(nominatorStatus);
+ await nominator.updateNominatorStatus(nominatorStatus);
+
// The number of nominations to do per nominator account
// This is either hard coded, or set to "auto", meaning it will find a dynamic amount of validators
// to nominate based on the lowest staked validator in the validator set
@@ -78,7 +75,6 @@ export const doNominations = async (
if (!api || !denom) return null;
const autoNom = await autoNumNominations(api, nominator);
const { nominationNum } = autoNom;
- const stash = await nominator.stash();
logger.info(
`Nominator ${stash} ${nominator.isProxy ? "Proxy" : "Non-Proxy"} with delay ${nominator.proxyDelay} blocks nominate ${nominationNum} validators`,
diff --git a/packages/common/src/scorekeeper/NumNominations.ts b/packages/common/src/scorekeeper/NumNominations.ts
index 25df39f0c..53eaa3d2c 100644
--- a/packages/common/src/scorekeeper/NumNominations.ts
+++ b/packages/common/src/scorekeeper/NumNominations.ts
@@ -5,9 +5,10 @@
*/
import { ApiPromise } from "@polkadot/api";
import { scorekeeperLabel } from "./scorekeeper";
-import Nominator, { NominatorStatus } from "../nominator/nominator";
+import Nominator from "../nominator/nominator";
import { Constants } from "../index";
import logger from "../logger";
+import { NominatorState, NominatorStatus } from "../types";
/**
* Automatically determines the number of validators a nominator can nominate based on their available balance
@@ -36,11 +37,12 @@ export const autoNumNominations = async (
nominator: Nominator,
): Promise => {
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `Calculating how many validators to nominate...`,
updated: Date.now(),
stale: false,
};
- nominator.updateNominatorStatus(nominatorStatus);
+ await nominator.updateNominatorStatus(nominatorStatus);
const denom = (await nominator?.chaindata?.getDenom()) || 0;
diff --git a/packages/common/src/scorekeeper/Round.ts b/packages/common/src/scorekeeper/Round.ts
index 1191caf5a..8507c87e5 100644
--- a/packages/common/src/scorekeeper/Round.ts
+++ b/packages/common/src/scorekeeper/Round.ts
@@ -11,9 +11,10 @@ import { OTV } from "../constraints/constraints";
import { ConfigSchema } from "../config";
import MatrixBot from "../matrix";
import ApiHandler from "../ApiHandler/ApiHandler";
-import Nominator, { NominatorStatus } from "../nominator/nominator";
+import Nominator from "../nominator/nominator";
import { jobStatusEmitter } from "../Events";
import { JobNames } from "./jobs/JobConfigs";
+import { NominatorState, NominatorStatus } from "../types";
/// Handles the beginning of a new round.
// - Gets the current era
@@ -34,16 +35,6 @@ export const startRound = async (
if (nominating) return [];
nominating = true;
- const shouldNominatePromises = nominatorGroups.map(async (nom) => {
- return {
- nominator: nom,
- shouldNominate: await nom.shouldNominate(),
- };
- });
- const resolvedNominators = await Promise.all(shouldNominatePromises);
- const filteredNominators = resolvedNominators
- .filter((nom) => nom.shouldNominate)
- .map((nom) => nom.nominator);
const now = new Date().getTime();
// The nominations sent now won't be active until the next era.
@@ -58,13 +49,14 @@ export const startRound = async (
`New round is starting! Era ${newEra} will begin new nominations.`,
);
- for (const nom of filteredNominators) {
+ for (const nom of nominatorGroups) {
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `Round Started`,
updated: Date.now(),
stale: false,
};
- nom.updateNominatorStatus(nominatorStatus);
+ await nom.updateNominatorStatus(nominatorStatus);
}
const proxyTxs = await queries.getAllDelayedTxs();
@@ -97,23 +89,25 @@ export const startRound = async (
`[${index}/${allCandidates.length}] checked ${candidate.name} ${isValid ? "Valid" : "Invalid"} [${index}/${allCandidates.length}]`,
scorekeeperLabel,
);
- for (const nom of filteredNominators) {
+ for (const nom of nominatorGroups) {
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `[${index}/${allCandidates.length}] ${candidate.name} ${isValid ? "✅ " : "❌"}`,
updated: Date.now(),
stale: false,
};
- nom.updateNominatorStatus(nominatorStatus);
+ await nom.updateNominatorStatus(nominatorStatus);
}
}
- for (const nom of filteredNominators) {
+ for (const nom of nominatorGroups) {
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominating,
status: `Scoring Candidates...`,
updated: Date.now(),
stale: false,
};
- nom.updateNominatorStatus(nominatorStatus);
+ await nom.updateNominatorStatus(nominatorStatus);
}
// Score all candidates
@@ -126,7 +120,7 @@ export const startRound = async (
const scoredCandidate = {
name: candidate.name,
stash: candidate.stash,
- total: score.total,
+ total: score?.total || 0,
};
return scoredCandidate;
}),
@@ -143,7 +137,7 @@ export const startRound = async (
// TODO unit test that assets this value
const numValidatorsNominated = await doNominations(
sortedCandidates,
- filteredNominators,
+ nominatorGroups,
chaindata,
handler,
bot,
@@ -157,29 +151,21 @@ export const startRound = async (
scorekeeperLabel,
);
await queries.setLastNominatedEraIndex(newEra);
- for (const nom of filteredNominators) {
+ for (const nom of nominatorGroups) {
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominated,
status: `Nominated!`,
updated: Date.now(),
stale: false,
lastNominationEra: newEra,
};
- nom.updateNominatorStatus(nominatorStatus);
+ await nom.updateNominatorStatus(nominatorStatus);
}
} else {
logger.info(
`${numValidatorsNominated} nominated this round, lastNominatedEra not set...`,
scorekeeperLabel,
);
- for (const nom of filteredNominators) {
- const nominatorStatus: NominatorStatus = {
- status: `${numValidatorsNominated} nominated, era not set!`,
- updated: Date.now(),
- stale: false,
- lastNominationEra: newEra,
- };
- nom.updateNominatorStatus(nominatorStatus);
- }
}
nominating = false;
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/CancelJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/CancelJob.ts
index b901114a2..69b145873 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/CancelJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/CancelJob.ts
@@ -20,7 +20,7 @@ export const cancelJob = async (
const latestBlock = await chaindata.getLatestBlock();
if (!latestBlock) {
logger.error(`latest block is null`, cronLabel);
- return;
+ return false;
}
const threshold = latestBlock - 1.2 * config?.proxy?.timeDelayBlocks;
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/ConstraintsJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/ConstraintsJob.ts
index ed81ec78b..520d5c5be 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/ConstraintsJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/ConstraintsJob.ts
@@ -162,7 +162,7 @@ export const scoreJob = async (
name: JobNames.Score,
progress,
updated: Date.now(),
- iteration: `[${score.toFixed(1)}] ${candidate.name}`,
+ iteration: `[${score?.toFixed(1)}] ${candidate.name}`,
});
logger.info(
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/EraPointsJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/EraPointsJob.ts
index abafe06bc..fffa5305a 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/EraPointsJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/EraPointsJob.ts
@@ -16,18 +16,39 @@ export class EraPointsJob extends Job {
export const individualEraPointsJob = async (
chaindata: ChainData,
eraIndex: number,
-) => {
- const erapoints = await queries.getTotalEraPoints(eraIndex);
+): Promise => {
+ try {
+ const erapoints = await queries.getTotalEraPoints(eraIndex);
- // If Era Points for the era exist, and are what the total should be, skip
- if (!!erapoints && erapoints.totalEraPoints >= 0 && erapoints.median) {
- return;
- } else {
- const data = await chaindata.getTotalEraPoints(eraIndex);
- if (data) {
- const { era, total, validators } = data;
- await queries.setTotalEraPoints(era, total, validators);
+ // If Era Points for the era exist, and are what the total should be, skip
+ if (!!erapoints && erapoints.totalEraPoints >= 0 && erapoints.median) {
+ return false;
+ } else {
+ const data = await chaindata.getTotalEraPoints(eraIndex);
+ if (
+ data &&
+ data.era &&
+ data.total &&
+ data.validators &&
+ data.validators.length > 0
+ ) {
+ const { era, total, validators } = data;
+ await queries.setTotalEraPoints(era, total, validators);
+ } else {
+ logger.error(
+ `Error getting total era points for era: ${JSON.stringify(data)} is null`,
+ erapointsLabel,
+ );
+ return false;
+ }
}
+ return true;
+ } catch (e) {
+ logger.error(
+ `Error running individual era points job: ${JSON.stringify(e)}`,
+ erapointsLabel,
+ );
+ return false;
}
};
export const eraPointsJob = async (
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/EraStatsJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/EraStatsJob.ts
index 7ab67ff49..d26aac695 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/EraStatsJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/EraStatsJob.ts
@@ -17,6 +17,9 @@ export const eraStatsJob = async (
): Promise => {
try {
const { chaindata } = metadata;
+
+ await setValidatorRanks();
+
const currentSession = await chaindata.getSession();
const currentEra = await chaindata.getCurrentEra();
const validators = await chaindata.currentValidators();
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/ExecutionJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/ExecutionJob.ts
index b8cd0d429..c6cb1bd3f 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/ExecutionJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/ExecutionJob.ts
@@ -4,7 +4,7 @@ import { Constants, queries, Util } from "../../../index";
import { cronLabel } from "../cron/StartCronJobs";
import { jobStatusEmitter } from "../../../Events";
import { JobNames } from "../JobConfigs";
-import { NominatorStatus } from "../../../nominator/nominator";
+import { NominatorState, NominatorStatus } from "../../../types";
export class ExecutionJob extends Job {
constructor(jobConfig: JobConfig, jobRunnerMetadata: JobRunnerMetadata) {
@@ -28,19 +28,19 @@ export const executionJob = async (
const latestBlock = await chaindata.getLatestBlock();
if (!latestBlock) {
logger.error(`latest block is null`, cronLabel);
- return;
+ return false;
}
const api = handler.getApi();
if (!api) {
logger.error(`api is null`, cronLabel);
- return;
+ return false;
}
const era = await chaindata.getCurrentEra();
if (!era) {
logger.error(`current era is null`, cronLabel);
- return;
+ return false;
}
const allDelayed = await queries.getAllDelayedTxs();
@@ -93,7 +93,7 @@ export const executionJob = async (
updated: Date.now(),
stale: false,
};
- nominator.updateNominatorStatus(nominatorStatus);
+ await nominator.updateNominatorStatus(nominatorStatus);
if (bot) {
await bot.sendMessage(
`@room ${target} has invalid commission: ${commission}`,
@@ -117,7 +117,7 @@ export const executionJob = async (
updated: Date.now(),
stale: false,
};
- nominator.updateNominatorStatus(nominatorStatus);
+ await nominator.updateNominatorStatus(nominatorStatus);
await nominator.cancelTx(announcement);
}
}
@@ -128,7 +128,8 @@ export const executionJob = async (
(validCommission && dataNum + Number(timeDelayBlocks) <= latestBlock);
if (shouldExecute) {
- nominator.updateNominatorStatus({
+ await nominator.updateNominatorStatus({
+ state: NominatorState.Nominating,
status: `Starting Delayed Execution for ${callHash} - ${dataNum}`,
updated: Date.now(),
stale: false,
@@ -139,11 +140,12 @@ export const executionJob = async (
);
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.NotNominating,
status: `${isDryRun ? "DRY RUN: " : ""} Executing Valid Proxy Tx: ${data.callHash}`,
updated: Date.now(),
stale: false,
};
- nominator.updateNominatorStatus(nominatorStatus);
+ await nominator.updateNominatorStatus(nominatorStatus);
// time to execute
@@ -168,11 +170,12 @@ export const executionJob = async (
// `dryRun` is a special value for the returned block hash that is used to test the execution job without actually sending the transaction
if (didSend || finalizedBlockHash == "dryRun") {
const nominatorStatus: NominatorStatus = {
+ state: NominatorState.Nominated,
status: `Executed Proxy Tx: ${finalizedBlockHash == "dryRun" ? "" : didSend} ${finalizedBlockHash}`,
updated: Date.now(),
stale: false,
};
- nominator.updateNominatorStatus(nominatorStatus);
+ await nominator.updateNominatorStatus(nominatorStatus);
nominator.lastEraNomination = era;
// Create a Nomination Object
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/LocationStatsJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/LocationStatsJob.ts
index 39cfb0761..1b10450a3 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/LocationStatsJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/LocationStatsJob.ts
@@ -16,6 +16,7 @@ export const locationStatsJob = async (metadata: JobRunnerMetadata) => {
try {
const { chaindata } = metadata;
await queries.cleanBlankLocations();
+ await queries.cleanOldLocations();
jobStatusEmitter.emit("jobProgress", {
name: JobNames.LocationStats,
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/MainScorekeeperJob.ts b/packages/common/src/scorekeeper/jobs/specificJobs/MainScorekeeperJob.ts
index fbb19c956..67be1a52d 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/MainScorekeeperJob.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/MainScorekeeperJob.ts
@@ -4,6 +4,7 @@ import { queries } from "../../../index";
import { startRound } from "../../Round";
import { jobStatusEmitter } from "../../../Events";
import { JobNames } from "../JobConfigs";
+import { NOMINATOR_SHOULD_NOMINATE_ERAS_THRESHOLD } from "../../../constants";
export class MainScorekeeperJob extends Job {
constructor(jobConfig: JobConfig, jobRunnerMetadata: JobRunnerMetadata) {
@@ -41,7 +42,8 @@ export const mainScorekeeperJob = async (
return;
}
- const { lastNominatedEraIndex } = await queries.getLastNominatedEraIndex();
+ const lastNominatedEra = await queries.getLastNominatedEraIndex();
+ const lastNominatedEraIndex = lastNominatedEra?.lastNominatedEraIndex || 0;
const eraBuffer = config.global.networkPrefix == 0 ? 1 : 4;
const isNominationRound =
Number(lastNominatedEraIndex) <= activeEra - eraBuffer;
@@ -55,8 +57,10 @@ export const mainScorekeeperJob = async (
const stash = await nom.stash();
if (!stash || stash === "0x") return false;
const lastNominatedEra =
- await chaindata.getNominatorLastNominationEra(stash);
- return lastNominatedEra <= activeEra - 1;
+ (await chaindata.getNominatorLastNominationEra(stash)) || 0;
+ return (
+ activeEra - lastNominatedEra >= NOMINATOR_SHOULD_NOMINATE_ERAS_THRESHOLD
+ );
}),
);
diff --git a/packages/common/src/scorekeeper/jobs/specificJobs/StaleNomination.ts b/packages/common/src/scorekeeper/jobs/specificJobs/StaleNomination.ts
index 444ecfb57..85f2651a5 100644
--- a/packages/common/src/scorekeeper/jobs/specificJobs/StaleNomination.ts
+++ b/packages/common/src/scorekeeper/jobs/specificJobs/StaleNomination.ts
@@ -38,7 +38,7 @@ export const staleNominationJob = async (
if (!stash || stash === "0x") continue;
const lastNominatedEra =
- await chaindata.getNominatorLastNominationEra(stash);
+ (await chaindata.getNominatorLastNominationEra(stash)) || 0;
if (lastNominatedEra < Number(currentEra) - threshold) {
const message = `Nominator ${stash} has a stale nomination. Last nomination was in era ${nom.getStatus()?.lastNominationEra} (it is now era ${currentEra})`;
diff --git a/packages/common/src/scorekeeper/scorekeeper.ts b/packages/common/src/scorekeeper/scorekeeper.ts
index c9e23c1a0..05ca7a017 100644
--- a/packages/common/src/scorekeeper/scorekeeper.ts
+++ b/packages/common/src/scorekeeper/scorekeeper.ts
@@ -9,7 +9,7 @@ import {
Util,
} from "../index";
-import Nominator, { NominatorStatus } from "../nominator/nominator";
+import Nominator from "../nominator/nominator";
import {
registerAPIHandler,
registerEventEmitterHandler,
@@ -17,6 +17,7 @@ import {
import { Job, JobRunnerMetadata, JobStatus } from "./jobs/JobsClass";
import { JobsRunnerFactory } from "./jobs/JobsRunnerFactory";
import { startRound } from "./Round";
+import { NominatorStatus } from "../types";
// import { monitorJob } from "./jobs";
export type NominatorGroup = Config.NominatorConfig[];
@@ -240,7 +241,7 @@ export default class ScoreKeeper {
scorekeeperLabel,
);
- const currentEra = await this.chaindata.getCurrentEra();
+ const currentEra = (await this.chaindata.getCurrentEra()) || 0;
this.currentEra = currentEra;
// await setAllIdentities(this.chaindata, scorekeeperLabel);
diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts
index 7936559dd..6095a0aee 100644
--- a/packages/common/src/types.ts
+++ b/packages/common/src/types.ts
@@ -111,3 +111,42 @@ export interface TelemetryWsPayload extends Array {
6: any; // location
7: any; // startupTime
}
+
+export enum NominatorState {
+ Nominated = "Nominated",
+ ReadyToNominate = "Ready to Nominate",
+ Nominating = "Nominating",
+ AwaitingProxyExecution = "Awaiting Proxy Execution",
+ NotNominating = "Not Nominating",
+ Stale = "Stale",
+}
+
+export interface NominatorStatus {
+ state?: NominatorState;
+ status?: string;
+ isBonded?: boolean;
+ bondedAddress?: string;
+ bondedAmount?: number;
+ stashAddress?: string;
+ proxyAddress?: string;
+ isProxy?: boolean;
+ proxyDelay?: number;
+ isNominating?: boolean;
+ lastNominationEra?: number;
+ lastNominationTime?: number;
+ currentTargets?:
+ | string[]
+ | {
+ stash?: string;
+ name?: string;
+ kyc?: boolean;
+ score?: string | number;
+ }[];
+ nextTargets?: string[];
+ proxyTxs?: any[];
+ updated: number;
+ rewardDestination?: string;
+ stale?: boolean;
+ dryRun?: boolean;
+ shouldNominate?: boolean;
+}
diff --git a/packages/common/src/utils/Validators.ts b/packages/common/src/utils/Validators.ts
index 7811d16a6..b296e6b59 100644
--- a/packages/common/src/utils/Validators.ts
+++ b/packages/common/src/utils/Validators.ts
@@ -1,51 +1,13 @@
-import {
- allCandidates,
- getAllValidatorSets,
- getIdentityAddresses,
- setRank,
-} from "../db";
+import { allCandidates, setRank } from "../db/queries";
+import { queries } from "../index";
+// Sets all validators ranks
export const setValidatorRanks = async () => {
- const rankMap: Map = new Map();
const candidates = await allCandidates();
- const candidateAddresses = candidates.map((candidate) => candidate.stash);
- const validatorSets = await getAllValidatorSets();
- if (validatorSets) {
- for (const era of validatorSets) {
- const validators = era.validators || [];
-
- for (const validator of validators) {
- const candidateExists = candidateAddresses.includes(validator);
- if (candidateExists) {
- if (rankMap.has(validator)) {
- const val = rankMap.get(validator) || 0;
- rankMap.set(validator, val + 1);
- } else {
- rankMap.set(validator, 1);
- }
- }
- }
- }
- await processRankMap(rankMap);
+ for (const candidate of candidates) {
+ const identityRank = await queries.getIdentityValidatorActiveEras(
+ candidate.stash,
+ );
+ await setRank(candidate.stash, identityRank);
}
};
-
-export const processRankMap = async (
- rankMap: Map,
-): Promise => {
- return await Promise.all(
- Array.from(rankMap.entries()).map(async ([validator, rank]) => {
- const rankList: { address: string; rank: number }[] = [];
- const identityAddresses: string[] = await getIdentityAddresses(validator);
- for (const identityAddress of identityAddresses) {
- rankList.push({ address: identityAddress, rank: rank });
- }
- const sortedRankList = rankList.sort((a, b) => b.rank - a.rank);
- const maxRank: number = Math.max(
- ...sortedRankList.map((entry) => entry.rank),
- );
-
- await setRank(validator, maxRank);
- }),
- );
-};
diff --git a/packages/common/test/db/queries/EraStats.unit.test.ts b/packages/common/test/db/queries/EraStats.unit.test.ts
index 72b8d62cd..c0ba80d47 100644
--- a/packages/common/test/db/queries/EraStats.unit.test.ts
+++ b/packages/common/test/db/queries/EraStats.unit.test.ts
@@ -10,13 +10,15 @@ describe("setEraStats", () => {
const totalNodes = 10;
const valid = 8;
const active = 6;
- await setEraStats(era, totalNodes, valid, active);
+ const kyc = 3;
+ await setEraStats(era, totalNodes, valid, active, kyc);
const eraStats = await EraStatsModel.findOne({ era }).lean();
expect(eraStats).toBeDefined();
expect(eraStats?.totalNodes).toBe(totalNodes);
expect(eraStats?.valid).toBe(valid);
expect(eraStats?.active).toBe(active);
+ expect(eraStats?.kyc).toBe(kyc);
});
it("should update existing era stats with different values", async () => {
@@ -24,6 +26,7 @@ describe("setEraStats", () => {
const initialTotalNodes = 5;
const initialValid = 4;
const initialActive = 3;
+ const kyc = 2;
await new EraStatsModel({
era,
totalNodes: initialTotalNodes,
@@ -34,13 +37,14 @@ describe("setEraStats", () => {
const updatedTotalNodes = 12;
const updatedValid = 10;
const updatedActive = 8;
- await setEraStats(era, updatedTotalNodes, updatedValid, updatedActive);
+ await setEraStats(era, updatedTotalNodes, updatedValid, updatedActive, kyc);
const eraStats = await EraStatsModel.findOne({ era }).lean();
expect(eraStats).toBeDefined();
expect(eraStats?.totalNodes).toBe(updatedTotalNodes);
expect(eraStats?.valid).toBe(updatedValid);
expect(eraStats?.active).toBe(updatedActive);
+ expect(eraStats?.kyc).toBe(kyc);
});
it("should not update existing era stats if values are the same", async () => {
@@ -48,10 +52,11 @@ describe("setEraStats", () => {
const totalNodes = 20;
const valid = 15;
const active = 10;
- await new EraStatsModel({ era, totalNodes, valid, active }).save();
+ const kyc = 5;
+ await new EraStatsModel({ era, totalNodes, valid, active, kyc }).save();
// Call setEraStats with the same values
- await setEraStats(era, totalNodes, valid, active);
+ await setEraStats(era, totalNodes, valid, active, kyc);
const eraStats = await EraStatsModel.findOne({ era }).lean();
expect(eraStats).toBeDefined();
@@ -59,6 +64,7 @@ describe("setEraStats", () => {
expect(eraStats?.totalNodes).toBe(totalNodes);
expect(eraStats?.valid).toBe(valid);
expect(eraStats?.active).toBe(active);
+ expect(eraStats?.kyc).toBe(kyc);
});
});
@@ -70,6 +76,7 @@ describe("getLatestEraStats", () => {
totalNodes: era * 2,
valid: era * 1.5,
active: era,
+ kyc: 1,
}));
await EraStatsModel.create(eraStatsData);
diff --git a/packages/common/test/scorekeeper/NumNominations.int.test.ts b/packages/common/test/scorekeeper/NumNominations.int.test.ts
index c43c7ff56..1a58ba2e7 100644
--- a/packages/common/test/scorekeeper/NumNominations.int.test.ts
+++ b/packages/common/test/scorekeeper/NumNominations.int.test.ts
@@ -2,6 +2,8 @@ import { ApiPromise, WsProvider } from "@polkadot/api";
import { autoNumNominations } from "../../src/scorekeeper/NumNominations";
import { KusamaEndpoints } from "../../src/constants";
+import Nominator from "../../src/nominator/nominator";
+import ApiHandler from "../../src/ApiHandler/ApiHandler";
describe("autoNumNominations Integration Test", () => {
it("queries the real API and retrieves data", async () => {
@@ -10,11 +12,18 @@ describe("autoNumNominations Integration Test", () => {
});
await api.isReadyOrError;
- const nom = {
- stash: () => "EX9uchmfeSqKTM7cMMg8DkH49XV8i4R7a7rqCn8btpZBHDP",
+ const handler = new ApiHandler(KusamaEndpoints);
+
+ const nominatorConfig = {
+ isProxy: false,
+ seed: "0x" + "00".repeat(32),
+ proxyDelay: 10800,
+ proxyFor: "EX9uchmfeSqKTM7cMMg8DkH49XV8i4R7a7rqCn8btpZBHDP",
};
- const result = await autoNumNominations(api, nom as any);
+ const nominator = new Nominator(handler, nominatorConfig, 2, null);
+
+ const result = await autoNumNominations(api, nominator);
expect(result).toBeDefined();
diff --git a/packages/common/test/utils/Validators.unit.test.ts b/packages/common/test/utils/Validators.unit.test.ts
new file mode 100644
index 000000000..9cb61e41b
--- /dev/null
+++ b/packages/common/test/utils/Validators.unit.test.ts
@@ -0,0 +1,101 @@
+// import { setValidatorRanks } from "../../src/utils";
+import { addKusamaCandidates } from "../testUtils/candidate";
+import { Identity } from "../../src/types";
+import {
+ addCandidate,
+ getCandidate,
+ getIdentityValidatorActiveEras,
+ getValidatorActiveEras,
+ setCandidateIdentity,
+ setValidatorSet,
+} from "../../src/db/queries";
+import { initTestServerBeforeAll } from "../testUtils/dbUtils";
+import { ValidatorSetModel } from "../../src/db";
+import { setValidatorRanks } from "../../src/utils/Validators";
+
+initTestServerBeforeAll();
+describe("setValidatorRanks", () => {
+ it("should set ranks for all candidates", async () => {
+ await addKusamaCandidates();
+
+ await addCandidate(
+ 2398,
+ "Blockshard2",
+ "HkJjBkX8fPBFJvTtAbUDKWZSsMrNFuMc7TrT8BqVS5YhZXg",
+ "",
+ false,
+ "matrixhandle",
+ false,
+ );
+
+ const identity1: Identity = {
+ address: "Cp4U5UYg2FaVUpyEtQgfBm9aqge6EEPkJxEFVZFYy7L1AZF",
+ name: "Blockshard",
+ display: "Blockshard",
+ subIdentities: [
+ {
+ name: "Blockshard2",
+ address: "HkJjBkX8fPBFJvTtAbUDKWZSsMrNFuMc7TrT8BqVS5YhZXg",
+ },
+ ],
+ };
+ const identity2: Identity = {
+ address: "D9rwRxuG8xm8TZf5tgkbPxhhTJK5frCJU9wvp59VRjcMkUf",
+ name: "🎠 Forbole GP01 🇭🇰",
+ display: "🎠 Forbole GP01 🇭🇰",
+ };
+ const identity3: Identity = {
+ address: "J4hAvZoHCviZSoPHoSwLida8cEkZR1NXJcGrcfx9saHTk7D",
+ name: "Anonstake",
+ display: "Anonstake",
+ };
+ const identity4: Identity = {
+ address: "EPhtbjecJ9P2SQEGEJ4XmFS4xN7JioBFarSrbqjhj8BuJ2v",
+ name: "Indigo One",
+ display: "Indigo One",
+ };
+ const identity5: Identity = {
+ address: "HhcrzHdB5iBx823XNfBUukjj4TUGzS9oXS8brwLm4ovMuVp",
+ name: "KIRA Staking",
+ display: "KIRA Staking",
+ };
+ await setCandidateIdentity(identity1?.address, identity1);
+
+ await setValidatorSet(1, 1, [identity1?.address, identity2?.address]);
+ await setValidatorSet(5, 2, [identity1?.address, identity2?.address]);
+ await setValidatorSet(8, 3, [
+ identity1?.address,
+ identity3?.address,
+ identity5?.address,
+ "HkJjBkX8fPBFJvTtAbUDKWZSsMrNFuMc7TrT8BqVS5YhZXg",
+ ]);
+ await setValidatorSet(16, 4, [
+ identity1?.address,
+ identity3?.address,
+ identity4?.address,
+ "HkJjBkX8fPBFJvTtAbUDKWZSsMrNFuMc7TrT8BqVS5YhZXg",
+ identity5?.address,
+ ]);
+ await setValidatorSet(100, 5, [identity1?.address, identity4?.address]);
+
+ const validatorSets = await ValidatorSetModel.find({}).exec();
+ expect(validatorSets.length).toBe(5);
+
+ const numEras = await getValidatorActiveEras(identity1?.address);
+ expect(numEras).toBe(5);
+
+ const subNumEras = await getIdentityValidatorActiveEras(
+ "HkJjBkX8fPBFJvTtAbUDKWZSsMrNFuMc7TrT8BqVS5YhZXg",
+ );
+ expect(subNumEras).toBe(5);
+
+ await setValidatorRanks();
+ const candidate = await getCandidate(identity1?.address);
+ expect(candidate?.rank).toBe(5);
+
+ const secondNode = await getCandidate(
+ "HkJjBkX8fPBFJvTtAbUDKWZSsMrNFuMc7TrT8BqVS5YhZXg",
+ );
+ expect(secondNode?.rank).toBe(5);
+ }, 10000);
+});
diff --git a/packages/core/package.json b/packages/core/package.json
index a20cfd76d..ed17917ff 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@1kv/core",
- "version": "3.1.2",
+ "version": "3.1.3",
"description": "Services for running the Thousand Validator Program.",
"main": "index.js",
"scripts": {
@@ -40,7 +40,7 @@
"@1kv/worker": "workspace:^",
"@koa/router": "^12.0.1",
"@octokit/rest": "^20.0.2",
- "@polkadot/api": "^10.11.2",
+ "@polkadot/api": "^10.12.1",
"@polkadot/keyring": "^12.6.2",
"@types/cron": "^2.4.0",
"@types/jest": "^29.5.12",
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 94d0ba36e..0fe42ffc1 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -120,6 +120,8 @@ export const clean = async (scorekeeper) => {
try {
// Clean locations with None
await queries.cleanBlankLocations();
+ await queries.cleanOldLocations();
+ await queries.cleanOldNominatorStakes();
// Delete all on-chain identities so they get fetched new on startup.
await queries.deleteAllIdentities();
diff --git a/packages/gateway/package.json b/packages/gateway/package.json
index 922afb509..ebb5e15e2 100644
--- a/packages/gateway/package.json
+++ b/packages/gateway/package.json
@@ -1,6 +1,6 @@
{
"name": "@1kv/gateway",
- "version": "3.1.2",
+ "version": "3.1.3",
"description": "Services for running the Thousand Validator Program.",
"main": "build/index.js",
"types": "build/index.d.ts",
diff --git a/packages/gateway/src/controllers/Validators.ts b/packages/gateway/src/controllers/Validators.ts
index caeae6a3a..7323a09c9 100644
--- a/packages/gateway/src/controllers/Validators.ts
+++ b/packages/gateway/src/controllers/Validators.ts
@@ -55,4 +55,17 @@ export default class ValidatorController {
}
response(context, 200, await ValidatorService.getBeefyDummy());
}
+
+ public static async getValidatorsNumActiveEras(context: any): Promise {
+ requestEmitter.emit("requestReceived");
+ if (await context.cashed()) {
+ logger.info(`getValidatorsNumActiveEras is cached`, gatewayLabel);
+ return;
+ }
+ response(
+ context,
+ 200,
+ await ValidatorService.getValidatorsNumActiveEras(context.params.address),
+ );
+ }
}
diff --git a/packages/gateway/src/routes/index.ts b/packages/gateway/src/routes/index.ts
index 01189c3ae..9f1a1492a 100644
--- a/packages/gateway/src/routes/index.ts
+++ b/packages/gateway/src/routes/index.ts
@@ -52,6 +52,7 @@ const API = {
CurrentValidatorSet: "/validators/current",
Validators: "/validators",
Validator: "/validator/:address",
+ ValidatorsNumActiveEras: "/validators/activeeras/:address",
ValidatorsBeefyStats: "/validators/beefy",
ValidatorsBeefyDummy: "/validators/beefy/dummy",
RewardsValidator: "/rewards/validator/:address",
@@ -97,6 +98,7 @@ router.get(API.ScoreMetadata, Score.getLatestScoreMetadata);
router.get(API.SessionScoreMetadata, Score.getSessionScoreMetadata);
router.get(API.CurrentValidatorSet, Validator.getLatestValidatorSet);
+router.get(API.ValidatorsNumActiveEras, Validator.getValidatorsNumActiveEras);
router.get(
API.LocationsCurrentValidatorSet,
@@ -129,20 +131,4 @@ router.get(API.BlockIndex, Block.getBlockIndex);
router.get(API.StatsTotalReqeusts, Stats.getTotalRequests);
router.get(API.StatsEndpointCounts, Stats.getEndpointCounts);
-// router.get("/stats/totalRequests", (ctx) => {
-// ctx.body = { totalRequests: requestEmitter.listenerCount("requestReceived") };
-// });
-//
-// // Endpoint to retrieve the count of requests per endpoint
-// router.get("/stats/endpointCounts", (ctx) => {
-// const endpointCounts = {};
-//
-// // Iterate over all registered endpoints
-// requestEmitter.eventNames().forEach((endpoint) => {
-// endpointCounts[endpoint] = requestEmitter.listenerCount(endpoint);
-// });
-//
-// ctx.body = { endpointCounts };
-// });
-
export default router;
diff --git a/packages/gateway/src/services/Candidate.ts b/packages/gateway/src/services/Candidate.ts
index 8ca169701..1da5ba7fc 100644
--- a/packages/gateway/src/services/Candidate.ts
+++ b/packages/gateway/src/services/Candidate.ts
@@ -3,11 +3,15 @@ import { logger, queries } from "@1kv/common";
const label = { label: "Gateway" };
export const getCandidateData = async (candidate: any): Promise => {
- const metadata = await queries.getChainMetadata();
+ const [metadata, score, nominations, location] = await Promise.all([
+ queries.getChainMetadata(),
+ queries.getLatestValidatorScore(candidate.stash),
+ queries.getLatestNominatorStake(candidate.stash),
+ queries.getCandidateLocation(candidate.name),
+ ]);
+
const denom = Math.pow(10, metadata.decimals);
- const score = await queries.getLatestValidatorScore(candidate.stash);
- const nominations = await queries.getLatestNominatorStake(candidate.stash);
- const location = await queries.getCandidateLocation(candidate.name);
+
return {
slotId: candidate.slotId,
kyc: candidate.kyc,
diff --git a/packages/gateway/src/services/Validator.ts b/packages/gateway/src/services/Validator.ts
index 8e0f08692..ebf8bd029 100644
--- a/packages/gateway/src/services/Validator.ts
+++ b/packages/gateway/src/services/Validator.ts
@@ -24,3 +24,17 @@ export const getBeefyDummy = async (): Promise => {
const validators = await queries.getValidatorsBeefyDummy();
return validators;
};
+
+export const getValidatorsNumActiveEras = async (
+ stash: string,
+): Promise => {
+ const eras = await queries.getValidatorActiveEras(stash);
+ return eras;
+};
+
+export const getIdentityValidatorNumActiveEras = async (
+ stash: string,
+): Promise => {
+ const eras = await queries.getIdentityValidatorActiveEras(stash);
+ return eras;
+};
diff --git a/packages/gateway/src/swagger.yml b/packages/gateway/src/swagger.yml
index a7d5d882b..e9993719a 100644
--- a/packages/gateway/src/swagger.yml
+++ b/packages/gateway/src/swagger.yml
@@ -32,6 +32,8 @@ tags:
description: Querying score data
paths:
+
+
/candidate/{candidateStash}:
get:
tags:
@@ -58,6 +60,33 @@ paths:
description: Successful response with a list of candidates
+ /candidates/rank:
+ get:
+ tags:
+ - Candidates
+ summary: Retrieve a list of candidates ordered by rank
+ responses:
+ 200:
+ description: Successful response with a list of candidates
+
+ /candidates/valid:
+ get:
+ tags:
+ - Candidates
+ summary: Retrieve a list of candidates that are valid
+ responses:
+ 200:
+ description: Successful response with a list of candidates
+
+ /candidates/invalid:
+ get:
+ tags:
+ - Candidates
+ summary: Retrieve a list of candidates that are invalid
+ responses:
+ 200:
+ description: Successful response with a list of candidates
+
/rewards/validator/{stash}:
get:
tags:
@@ -148,12 +177,7 @@ paths:
responses:
200:
description: Rewards.
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/Reward'
+
/rewards/nominator/{address}/total:
get:
@@ -171,13 +195,19 @@ paths:
responses:
'200':
description: "Total rewards for the specified nominator."
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/RewardTotal'
'404':
description: "Validator not found."
+
+ /healthcheck:
+ get:
+ summary: "health check of the backend"
+ description: "Health check of the backend"
+ responses:
+ '200':
+ description: "health check of the backend"
+
+
/nominators:
get:
summary: "Get All Nominators"
@@ -207,6 +237,31 @@ paths:
'404':
description: "Nominator not found."
+ /nominator/{address}/{last}:
+ get:
+ summary: "Get Nominator by Address"
+ tags:
+ - Nominator
+ description: "Retrieve details of a specific nominator by address."
+ parameters:
+ - in: path
+ name: address
+ required: true
+ schema:
+ type: string
+ description: "The unique address of the nominator."
+ - in: path
+ name: last
+ required: true
+ schema:
+ type: string
+ description: "Number of eras to retrieve."
+ responses:
+ '200':
+ description: "Successful response with nominator details."
+ '404':
+ description: "Nominator not found."
+
/nominations:
get:
summary: "Get All Nominations"
@@ -385,12 +440,12 @@ paths:
'404':
description: "Data not found."
- /delegations/{address}:
+
+
+ /erapoints/{address}:
get:
- summary: "Delegation Data"
- tags:
- - Candidates
- description: "Retrieve details of a specific validator's delegations'"
+ summary: "Era Points"
+ description: "Retrieve details of a specific validator's era points'"
parameters:
- in: path
name: address
@@ -404,100 +459,178 @@ paths:
'404':
description: "Data not found."
- /opengov/votes/address/{address}:
+ /totalerapoints:
get:
- summary: "Open Gov Vote Data"
- tags:
- - Candidates
- description: "Retrieve details of a specific validator's votes"
+ summary: "Total Era Points"
+ description: "Retrieves total era points"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /erastats:
+ get:
+ summary: "Era Stats"
+ description: "Retrieves era stats"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /scoremetadata:
+ get:
+ summary: "Score Metadata"
+ description: "Retrieves score metadata"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /scoremetadata/{session}:
+ get:
+ summary: "Score Metadata"
+ description: "Retrieve details of a score metadata for a session'"
parameters:
- in: path
- name: address
+ name: session
required: true
schema:
type: string
- description: "The unique address of the validator."
+ description: "Session"
+ responses:
+ '200':
+ description: "Successful response."
+ '404':
+ description: "Data not found."
+
+ /release:
+ get:
+ summary: "Latest Release"
+ description: "Retrieves latest tagged release"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /location/currentvalidatorset:
+ get:
+ summary: "location stats of the current validator set"
+ description: "location stats of the current validator set"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /locationstats:
+ get:
+ summary: "location stats"
+ description: "location stats"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /locationstats/valid:
+ get:
+ summary: "location stats of valid nodes"
+ description: "location stats of valid nodes"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /locationstats/{session}:
+ get:
+ summary: "location stats for a session"
+ description: "Retrieve details of location stats for a session'"
+ parameters:
+ - in: path
+ name: session
+ required: true
+ schema:
+ type: string
+ description: "Session"
responses:
'200':
description: "Successful response."
'404':
description: "Data not found."
-#
-#
-#components:
-# schemas:
-# Reward:
-# type: object
-# properties:
-# role:
-# type: string
-# exposurePercentage:
-# type: integer
-# totalStake:
-# type: integer
-# commission:
-# type: integer
-# era:
-# type: integer
-# validator:
-# type: string
-# nominator:
-# type: string
-# rewardAmount:
-# type: string
-# rewardDestination:
-# type: string
-# erasMinStake:
-# type: number
-# format: float
-# validatorStakeEfficiency:
-# type: number
-# format: float
-# blockHash:
-# type: string
-# blockNumber:
-# type: integer
-# timestamp:
-# type: integer
-# date:
-# type: string
-# format: date
-# chf:
-# type: number
-# format: float
-# usd:
-# type: number
-# format: float
-# eur:
-# type: number
-# format: float
-# RewardTotal:
-# type: object
-# properties:
-# validator:
-# type: string
-# example: "ESNMjpEWcenAbCqGEsHVdbbRai79VQYMmV1fNW1kRZogmzx"
-# total:
-# type: number
-# format: float
-# example: 0.879469625343
-# rewardCount:
-# type: integer
-# example: 1
-# RewardStats:
-# type: object
-# properties:
-# total:
-# type: number
-# format: float
-# example: 0.235934990397
-# rewardCount:
-# type: integer
-# example: 1
-# avgEfficiency:
-# type: number
-# format: float
-# example: 84.46114961271203
-# avgStake:
-# type: integer
-# example: 7985
\ No newline at end of file
+
+ /validators/current:
+ get:
+ summary: "Current Validator Set"
+ description: "Current Validator Set"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /validators:
+ get:
+ summary: "Validator Set Keys"
+ description: "Validator Set Keys"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /validators/beefy:
+ get:
+ summary: "Validator Set Beefy Keys"
+ description: "Validator Set Beefy Keys"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /validators/beefy/dummmy:
+ get:
+ summary: "Validator Set Beefy Dummy Keys"
+ description: "Validator Set Beefy Dummy Keys"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /validators/{address}:
+ get:
+ summary: "Validator Set Keys"
+ description: "Validator Set Keys"
+ parameters:
+ - in: path
+ name: address
+ required: true
+ schema:
+ type: string
+ description: "address"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /validators/activeeras/{address}:
+ get:
+ summary: "Number of active eras for an address"
+ description: "Number of active eras for an address"
+ parameters:
+ - in: path
+ name: address
+ required: true
+ schema:
+ type: string
+ description: "address"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /blockindex:
+ get:
+ summary: "The block index of the backend"
+ description: "block index of the backend"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /stats/totalReqeusts:
+ get:
+ summary: "The total number of api requests of the backend"
+ description: "The total number of api requests of the backend"
+ responses:
+ '200':
+ description: "Successful response."
+
+ /stats/endpointCount:
+ get:
+ summary: "The total number of api requests of the backend for an endpoint"
+ description: "The total number of api requests of the backend for an endpoint"
+ responses:
+ '200':
+ description: "Successful response."
\ No newline at end of file
diff --git a/packages/scorekeeper-status-ui/package.json b/packages/scorekeeper-status-ui/package.json
index ba6471168..4d364377d 100644
--- a/packages/scorekeeper-status-ui/package.json
+++ b/packages/scorekeeper-status-ui/package.json
@@ -1,7 +1,7 @@
{
"name": "@1kv/scorekeeper-status-ui",
"private": true,
- "version": "3.1.2",
+ "version": "3.1.3",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/packages/scorekeeper-status-ui/src/App.css b/packages/scorekeeper-status-ui/src/App.css
index ee356628a..5f87bce34 100644
--- a/packages/scorekeeper-status-ui/src/App.css
+++ b/packages/scorekeeper-status-ui/src/App.css
@@ -479,6 +479,7 @@ h1 {
}
.proxyTransactionItem {
+ color: #0f0;
display: flex;
flex-direction: column;
align-items: center;
@@ -536,3 +537,37 @@ h1 {
white-space: nowrap; /* Keep the text on a single line */
max-width: 70%; /* Adjust this value based on your container's width */
}
+
+
+.nominatorStateContainer {
+ width: 80%;
+ box-shadow: 0 0 10px rgba(0, 255, 0, 0.5);
+ background: rgba(0, 255, 0, 0.05);
+ border: 1px solid rgba(0, 255, 0, 0.5);
+ margin: 0 auto;
+ display: flex;
+ flex-direction: column; /* Align children vertically */
+ align-items: center; /* Center children horizontally */
+ gap: 10px;
+ padding: 10px;
+ border-radius: 5px;
+ margin-top: 7%;
+ margin-bottom: 4%;
+}
+
+.nominatorStateContainer hr {
+ width: 100%; /* Match the width of the container */
+ border-color: rgba(0, 255, 0, 0.5); /* Match the border color */
+ box-shadow: 0 0 5px rgba(0, 255, 0, 0.5); /* Softer glow for the line */
+}
+
+.nominatorStateContainer > div, .nominatorStateContainer > p {
+ width: 100%; /* Ensure full width for center alignment */
+ text-align: center; /* Center the text */
+}
+
+.parentContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
diff --git a/packages/scorekeeper-status-ui/src/App.tsx b/packages/scorekeeper-status-ui/src/App.tsx
index 543105b29..8f2e1c56a 100644
--- a/packages/scorekeeper-status-ui/src/App.tsx
+++ b/packages/scorekeeper-status-ui/src/App.tsx
@@ -1,4 +1,5 @@
import React, { useCallback, useEffect, useState } from "react";
+import axios from "axios";
import {
FiActivity,
FiAlertTriangle,
@@ -6,7 +7,6 @@ import {
FiCheckCircle,
FiClock,
FiDollarSign,
- FiInfo,
FiPlay,
FiRefreshCcw,
FiSend,
@@ -16,15 +16,13 @@ import {
FiUserCheck,
FiXCircle,
} from "react-icons/fi";
-
import { BeatLoader } from "react-spinners";
import { motion } from "framer-motion";
import "./App.css";
-import axios from "axios"; // Ensure the path to your CSS file is correct
-import { debounce } from "lodash";
import HealthCheckBar from "./HealthCheckBar";
import { Identicon } from "@polkadot/react-identicon";
import EraStatsBar from "./EraStatsBar";
+import { debounce } from "lodash";
interface Job {
name: string;
@@ -265,6 +263,66 @@ const App = () => {
}
}
+ const getStateColor = (state) => {
+ switch (state) {
+ case "Nominated":
+ return "green";
+ case "Ready to Nominate":
+ return "blue";
+ case "Nominating":
+ return "orange";
+ case "Awaiting Proxy Execution":
+ return "purple";
+ case "Not Nominating":
+ return "red";
+ case "Stale":
+ return "grey";
+ default:
+ return "black";
+ }
+ };
+
+ const renderNominatorStateIcon = (state: string) => {
+ let iconComponent;
+ const iconSize = 24;
+
+ switch (state) {
+ case "Nominated":
+ iconComponent = ;
+ break;
+ case "Nominating":
+ iconComponent = ;
+ break;
+ case "Stale":
+ iconComponent = ;
+ break;
+ case "Not Nominating":
+ iconComponent = ;
+ break;
+ case "Ready to Nominate":
+ case "Awaiting Proxy Execution":
+ iconComponent = ;
+ break;
+ default:
+ iconComponent = <>>;
+ break;
+ }
+
+ return (
+
+ {iconComponent}
+ {state}
+
+ );
+ };
+
return (
@@ -332,7 +390,7 @@ const App = () => {
@@ -346,7 +404,7 @@ const App = () => {
border: `1px solid linear-gradient(to right, rgba(255, 0, 0, 0.1) ${job.progress}%, rgba(255, 255, 0, 0.1) ${job.progress}%, rgba(0, 255, 0, 0.1) ${job.progress}%)`,
}}
>
- {job.progress !== undefined ? job.progress.toFixed(1) : 0}%
+ {job.progress !== undefined ? job.progress?.toFixed(1) : 0}%
{job.iteration && (
@@ -418,12 +476,16 @@ const App = () => {
)}
+
{nominator.status && (
-
-
-
- {nominator.status}
-
+
+
+
+
{renderNominatorStateIcon(nominator.state)}
+ {nominator.state &&
}
+ {nominator.status}
+
+
)}
{nominator.isBonded !== undefined && (
@@ -441,7 +503,7 @@ const App = () => {
Bonded Amount:{" "}
{new Intl.NumberFormat().format(
- nominator.bondedAmount.toFixed(2),
+ nominator.bondedAmount?.toFixed(2),
)}{" "}
{currentEndpoint.includes("kusama") ? "KSM" : "DOT"}
@@ -513,8 +575,8 @@ const App = () => {
theme="polkadot"
/>
{target.name
- ? `[${target.score.toFixed(0)}] ${target.name}`
- : `[${target.score.toFixed(0)}] ${truncateAddress(target.stash)}`}{" "}
+ ? `[${target.score?.toFixed(0)}] ${target.name}`
+ : `[${target.score?.toFixed(0)}] ${truncateAddress(target.stash)}`}{" "}
{target.kyc && (
{
try {
const eraStatsEndpoint = new URL("/erastats", currentEndpoint).href;
const { data } = await axios.get(eraStatsEndpoint);
- // console.log("Era Stats Data:", JSON.stringify(data));
setEraStats(data[0]);
- console.log(`era stats`);
- console.log(JSON.stringify(eraStats));
} catch (error) {
console.error("Error fetching era stats data:", error);
}
@@ -36,6 +33,11 @@ const EraStatsBar = ({ currentEndpoint }) => {
return () => clearInterval(interval);
}, [currentEndpoint]);
+ useEffect(() => {
+ console.log(`era stats`);
+ console.log(JSON.stringify(eraStats));
+ }, [eraStats]);
+
return (
@@ -57,7 +59,7 @@ const EraStatsBar = ({ currentEndpoint }) => {
- KYC: {eraStats?.kyc} ($
+ KYC: {eraStats?.kyc} (
{((eraStats?.kyc / eraStats?.totalNodes) * 100).toFixed(0)}%)
diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json
index 665d28b9f..1bb939fd1 100644
--- a/packages/telemetry/package.json
+++ b/packages/telemetry/package.json
@@ -1,6 +1,6 @@
{
"name": "@1kv/telemetry",
- "version": "3.1.2",
+ "version": "3.1.3",
"description": "Services for running the Thousand Validator Program.",
"main": "build/index.js",
"types": "build/index.d.ts",
diff --git a/packages/worker/package.json b/packages/worker/package.json
index c6cac488c..d3ee1b416 100644
--- a/packages/worker/package.json
+++ b/packages/worker/package.json
@@ -1,6 +1,6 @@
{
"name": "@1kv/worker",
- "version": "3.1.2",
+ "version": "3.1.3",
"description": "Services for running the Thousand Validator Program.",
"main": "build/index.js",
"types": "build/index.d.ts",
@@ -29,7 +29,7 @@
},
"dependencies": {
"@1kv/common": "workspace:^",
- "@polkadot/api": "^10.11.2",
+ "@polkadot/api": "^10.12.1",
"bullmq": "^5.1.5",
"typescript": "^5.3.3"
},
diff --git a/yarn.lock b/yarn.lock
index 0fdea3918..8205f2b5a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9,8 +9,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "1k-validators-be@workspace:."
dependencies:
- "@polkadot/api": ^10.11.2
- "@polkadot/rpc-provider": ^10.11.2
+ "@polkadot/api": ^10.12.1
+ "@polkadot/rpc-provider": ^10.12.1
"@types/coingecko-api": ^1.0.13
"@types/eslint": ^8.44.7
"@types/jest": ^29.5.12
@@ -77,7 +77,7 @@ __metadata:
"@ava/typescript": ^4.1.0
"@koa/router": ^12.0.1
"@octokit/rest": ^20.0.2
- "@polkadot/api": ^10.11.2
+ "@polkadot/api": ^10.12.1
"@polkadot/keyring": ^12.6.2
"@types/cron": ^2.4.0
"@types/jest": ^29.5.12
@@ -196,7 +196,7 @@ __metadata:
dependencies:
"@1kv/common": "workspace:^"
"@ava/typescript": ^4.1.0
- "@polkadot/api": ^10.11.2
+ "@polkadot/api": ^10.12.1
"@typescript-eslint/eslint-plugin": ^5.59.9
"@typescript-eslint/parser": ^5.59.9
ava: ^6.1.1
@@ -1606,7 +1606,7 @@ __metadata:
languageName: node
linkType: hard
-"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.3":
+"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.3.3":
version: 1.3.3
resolution: "@noble/hashes@npm:1.3.3"
checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b
@@ -1808,74 +1808,138 @@ __metadata:
languageName: node
linkType: hard
-"@polkadot/api-augment@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/api-augment@npm:10.11.2"
+"@polkadot-api/client@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/client@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
dependencies:
- "@polkadot/api-base": 10.11.2
- "@polkadot/rpc-augment": 10.11.2
- "@polkadot/types": 10.11.2
- "@polkadot/types-augment": 10.11.2
- "@polkadot/types-codec": 10.11.2
+ "@polkadot-api/metadata-builders": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/substrate-bindings": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/substrate-client": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/utils": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ peerDependencies:
+ rxjs: ">=7.8.0"
+ checksum: 572a5538013131321722924a8ec4c4a3f18dfe76fc4897d77a65b2aa7e3162c5d11adab30111fd8489ab6952b7bd875f544e863b8cc0e54948233c6d736335e5
+ languageName: node
+ linkType: hard
+
+"@polkadot-api/json-rpc-provider-proxy@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/json-rpc-provider-proxy@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
+ checksum: d30789f6171fce9887139b88e832d121489fbe1694aa6919fb1c4a37e6ac39ba1f8e19caa76c0007fd815820f1c1b1de6e12169c6b638c580eb74eb0137b4b34
+ languageName: node
+ linkType: hard
+
+"@polkadot-api/json-rpc-provider@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/json-rpc-provider@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
+ checksum: fb028b1d16e2c39e5130f90e340691afcd1c45f08f39f56e3a46aa5a87f2bdfd2f71ad81f348d7fe78aceae483c50be4eb55e572f5fdf273beab5ac7b253a59c
+ languageName: node
+ linkType: hard
+
+"@polkadot-api/metadata-builders@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/metadata-builders@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
+ dependencies:
+ "@polkadot-api/substrate-bindings": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/utils": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ checksum: 64705f32b9f7d43af759db28161e244f1ea45d5a4214a2a7592b1a4b3922378f1bfe50ad659defe93f23a63da306e50df9602a757656200cf1e50387b1a11842
+ languageName: node
+ linkType: hard
+
+"@polkadot-api/substrate-bindings@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/substrate-bindings@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
+ dependencies:
+ "@noble/hashes": ^1.3.1
+ "@polkadot-api/utils": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@scure/base": ^1.1.1
+ scale-ts: ^1.4.3
+ checksum: c17caa73feaee67edff6e106453f4ef54fe2e14fc921e1fa5e1bd4e8e3f4af8e01802ce3959df072f5997d843c9ad4916b0b52103fdf58c7bf006911be326585
+ languageName: node
+ linkType: hard
+
+"@polkadot-api/substrate-client@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/substrate-client@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
+ checksum: 655272b98490e084b948e2c798e0f7d4ba7d90d33b9f24b4d01dd2a5ef6e7e31bf523dd6de602354a3911e897c55bdc32dc24f3b504ce22f27a8e40063296bb4
+ languageName: node
+ linkType: hard
+
+"@polkadot-api/utils@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0":
+ version: 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ resolution: "@polkadot-api/utils@npm:0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0"
+ checksum: 48ff709170ee7abad50f784f1123532b6b39725ab709da59fc9ddd859568753456b46c9c42d5aa56cad3d9fa0af27e46ed0650697df840f0ef2c023bd3a512f1
+ languageName: node
+ linkType: hard
+
+"@polkadot/api-augment@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/api-augment@npm:10.12.1"
+ dependencies:
+ "@polkadot/api-base": 10.12.1
+ "@polkadot/rpc-augment": 10.12.1
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-augment": 10.12.1
+ "@polkadot/types-codec": 10.12.1
"@polkadot/util": ^12.6.2
tslib: ^2.6.2
- checksum: 04a59f84abdc242ba0111afc9a41cc84ab562c3fb653db545f9d3ceb081afac2bcee392f709d4742079e1d3d1297fd135eac8727565c237349bdb7aa389ba04b
+ checksum: 430f4eba309cc7d4d3508d1bc5d949d6312cb96739a93a257f490ff0261d20a4b61a894afcbb13661f4a5e40060f5080a3c710c619b98a0e39e249cdb668072e
languageName: node
linkType: hard
-"@polkadot/api-base@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/api-base@npm:10.11.2"
+"@polkadot/api-base@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/api-base@npm:10.12.1"
dependencies:
- "@polkadot/rpc-core": 10.11.2
- "@polkadot/types": 10.11.2
+ "@polkadot/rpc-core": 10.12.1
+ "@polkadot/types": 10.12.1
"@polkadot/util": ^12.6.2
rxjs: ^7.8.1
tslib: ^2.6.2
- checksum: 88f3aa2c61ebf0ac75451236767d3e873b1823a4e3bef96433e765899f9f030cdf5d059da0d1ec3e97effc6287974e48b8f60966f019ed8f62e19b35170a9721
+ checksum: 9eb9ccdfae93e5bd333bb669dde00e2ed1242142d689f49ae56b501fbfcd5981018eec31e3d7539bc345ebaf856d0c57cc971a2e62f6f1f914ffe68b9eee4544
languageName: node
linkType: hard
-"@polkadot/api-derive@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/api-derive@npm:10.11.2"
+"@polkadot/api-derive@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/api-derive@npm:10.12.1"
dependencies:
- "@polkadot/api": 10.11.2
- "@polkadot/api-augment": 10.11.2
- "@polkadot/api-base": 10.11.2
- "@polkadot/rpc-core": 10.11.2
- "@polkadot/types": 10.11.2
- "@polkadot/types-codec": 10.11.2
+ "@polkadot/api": 10.12.1
+ "@polkadot/api-augment": 10.12.1
+ "@polkadot/api-base": 10.12.1
+ "@polkadot/rpc-core": 10.12.1
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-codec": 10.12.1
"@polkadot/util": ^12.6.2
"@polkadot/util-crypto": ^12.6.2
rxjs: ^7.8.1
tslib: ^2.6.2
- checksum: e89bcae6ac730fce72bb75f9b491400d561b0c61eb6f390d01e7c7060dd8fe24f893d7278f12e57200e485632f4a19f61af9b3dd5354bdfc07281bc9d2e85cb2
+ checksum: fdd725f8b28b4f213e2b61ab6e99cddff26add60cd9a605ebf59b210c9f1a8b79879c169d13e9a0ff712cec9fd64281a235c704c08a3877b33b349a7b13c00c4
languageName: node
linkType: hard
-"@polkadot/api@npm:10.11.2, @polkadot/api@npm:^10.11.2":
- version: 10.11.2
- resolution: "@polkadot/api@npm:10.11.2"
+"@polkadot/api@npm:10.12.1, @polkadot/api@npm:^10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/api@npm:10.12.1"
dependencies:
- "@polkadot/api-augment": 10.11.2
- "@polkadot/api-base": 10.11.2
- "@polkadot/api-derive": 10.11.2
+ "@polkadot/api-augment": 10.12.1
+ "@polkadot/api-base": 10.12.1
+ "@polkadot/api-derive": 10.12.1
"@polkadot/keyring": ^12.6.2
- "@polkadot/rpc-augment": 10.11.2
- "@polkadot/rpc-core": 10.11.2
- "@polkadot/rpc-provider": 10.11.2
- "@polkadot/types": 10.11.2
- "@polkadot/types-augment": 10.11.2
- "@polkadot/types-codec": 10.11.2
- "@polkadot/types-create": 10.11.2
- "@polkadot/types-known": 10.11.2
+ "@polkadot/rpc-augment": 10.12.1
+ "@polkadot/rpc-core": 10.12.1
+ "@polkadot/rpc-provider": 10.12.1
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-augment": 10.12.1
+ "@polkadot/types-codec": 10.12.1
+ "@polkadot/types-create": 10.12.1
+ "@polkadot/types-known": 10.12.1
"@polkadot/util": ^12.6.2
"@polkadot/util-crypto": ^12.6.2
eventemitter3: ^5.0.1
rxjs: ^7.8.1
tslib: ^2.6.2
- checksum: 4bb1c3ab28e7a96ea2c7a10f192ed679aff3c49e713164e69f163df7503686cb9fea7a20ab59b2dd6b85ed51e9c84df3efb346902dfd91b2f2e39aec0bdb351f
+ checksum: 25ef0b7ae5fbc740a9a0e4fd2536475ec473edfe29f94a97b5ea776c7d02b6a95a937564e7a171a459d678784818053a7444dff8302fafc594241f8db29ab440
languageName: node
linkType: hard
@@ -1929,128 +1993,128 @@ __metadata:
languageName: node
linkType: hard
-"@polkadot/rpc-augment@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/rpc-augment@npm:10.11.2"
+"@polkadot/rpc-augment@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/rpc-augment@npm:10.12.1"
dependencies:
- "@polkadot/rpc-core": 10.11.2
- "@polkadot/types": 10.11.2
- "@polkadot/types-codec": 10.11.2
+ "@polkadot/rpc-core": 10.12.1
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-codec": 10.12.1
"@polkadot/util": ^12.6.2
tslib: ^2.6.2
- checksum: 06daf8630fd2e73bb5d6692300e6e9d0b4ed9b4b0814174c5103e73ad59c79036657543ddf34a4da273e16e8dde6482dcc7c422850b3f21fb54a665565881d48
+ checksum: 845ea139f6526de67de1afb7e0f4542e29b63af3efdc98934676031eb174b84e49a17a212f06441c400cd234453414f78fff2b8b0c0c5cd54d2364cf2fbb6010
languageName: node
linkType: hard
-"@polkadot/rpc-core@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/rpc-core@npm:10.11.2"
+"@polkadot/rpc-core@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/rpc-core@npm:10.12.1"
dependencies:
- "@polkadot/rpc-augment": 10.11.2
- "@polkadot/rpc-provider": 10.11.2
- "@polkadot/types": 10.11.2
+ "@polkadot/rpc-augment": 10.12.1
+ "@polkadot/rpc-provider": 10.12.1
+ "@polkadot/types": 10.12.1
"@polkadot/util": ^12.6.2
rxjs: ^7.8.1
tslib: ^2.6.2
- checksum: f1511fbebee55ea993d1cb113c2a163efd7fd4ae03829c91c8400ed1ba6fbd7d6e1aeebcbf9f9997b0c386fdeb7db62eab25ac3ce7ed0a7cea9691ff28488973
+ checksum: d9f12597110e237fbb0f8f1c4c86cc8fcc598eddfd4ace0de00928fae446f3ddd8208183b462984738c149048cd51c9556c76d12568b27b77cc6ede4177db700
languageName: node
linkType: hard
-"@polkadot/rpc-provider@npm:10.11.2, @polkadot/rpc-provider@npm:^10.11.2":
- version: 10.11.2
- resolution: "@polkadot/rpc-provider@npm:10.11.2"
+"@polkadot/rpc-provider@npm:10.12.1, @polkadot/rpc-provider@npm:^10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/rpc-provider@npm:10.12.1"
dependencies:
"@polkadot/keyring": ^12.6.2
- "@polkadot/types": 10.11.2
- "@polkadot/types-support": 10.11.2
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-support": 10.12.1
"@polkadot/util": ^12.6.2
"@polkadot/util-crypto": ^12.6.2
"@polkadot/x-fetch": ^12.6.2
"@polkadot/x-global": ^12.6.2
"@polkadot/x-ws": ^12.6.2
- "@substrate/connect": 0.7.35
+ "@substrate/connect": 0.8.7
eventemitter3: ^5.0.1
mock-socket: ^9.3.1
- nock: ^13.4.0
+ nock: ^13.5.0
tslib: ^2.6.2
dependenciesMeta:
"@substrate/connect":
optional: true
- checksum: a266ea4bf1fa4b2f3aaad005a04906bc2ffb6440b96b21789c41aad975311fe9a73f46e57a88c327130d69af06ad39d4e8826d70c5635966e55e2644a77ffa9a
+ checksum: 29246fa825be3f4f2eb34d63a1ef17ecda1b2e6423cfcb6c119ecbfdf15c18230d085fc111ff4739c07748cc3923a4829ec5deefaebb54b8b6a1252b80d5da39
languageName: node
linkType: hard
-"@polkadot/types-augment@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/types-augment@npm:10.11.2"
+"@polkadot/types-augment@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/types-augment@npm:10.12.1"
dependencies:
- "@polkadot/types": 10.11.2
- "@polkadot/types-codec": 10.11.2
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-codec": 10.12.1
"@polkadot/util": ^12.6.2
tslib: ^2.6.2
- checksum: 74d6efbac15dd20ce1f4c47adccdc1bf9cabed577c53ae964cf14ab943346c0fb4d0965e93b1276055f42f136d51de4bf10115ef79942bf12f8b309344e57fa4
+ checksum: eec5f93331174a587dd804fe4f00b5409b7f775af3d8b8db3289d804d165a1a840311d44e54beaacf0b1ae323ac51905725aad32f9e48ff68a84a3afec03e726
languageName: node
linkType: hard
-"@polkadot/types-codec@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/types-codec@npm:10.11.2"
+"@polkadot/types-codec@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/types-codec@npm:10.12.1"
dependencies:
"@polkadot/util": ^12.6.2
"@polkadot/x-bigint": ^12.6.2
tslib: ^2.6.2
- checksum: 154b3c89120b8095c82b55e89e0c0233b9f4e628017dfbbf0a9ca8383e6085bf93a3f91cd21264acdc9e996180e28d734c5f669a70524a3aa1399d0f5b8202d6
+ checksum: 800f4172d0504d860e97f6894a8f43bde5ae20abe9f7b0a3a0e85cb8cfbeb80ce77fb381bda49d1defe30f4756939649b607dc4c3660e40c335e1b21651f28e5
languageName: node
linkType: hard
-"@polkadot/types-create@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/types-create@npm:10.11.2"
+"@polkadot/types-create@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/types-create@npm:10.12.1"
dependencies:
- "@polkadot/types-codec": 10.11.2
+ "@polkadot/types-codec": 10.12.1
"@polkadot/util": ^12.6.2
tslib: ^2.6.2
- checksum: 4fb124dbd3f42baaf99de68e6b26c4ce3d314ec92ba2c8a88eee72b9c3404bbe84d234e66048edbe26afb155338cdc81bf62a65c9e4dbdfe9c32e694de6f97b2
+ checksum: ff051f75c5e692f89de4e7686311a66e7b889a398efefcd373a67a18796c06a80266eed55726a97850b1e4e430ca13004895394a8e368acbe5e030e55c20269f
languageName: node
linkType: hard
-"@polkadot/types-known@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/types-known@npm:10.11.2"
+"@polkadot/types-known@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/types-known@npm:10.12.1"
dependencies:
"@polkadot/networks": ^12.6.2
- "@polkadot/types": 10.11.2
- "@polkadot/types-codec": 10.11.2
- "@polkadot/types-create": 10.11.2
+ "@polkadot/types": 10.12.1
+ "@polkadot/types-codec": 10.12.1
+ "@polkadot/types-create": 10.12.1
"@polkadot/util": ^12.6.2
tslib: ^2.6.2
- checksum: 198c92576fa85060bf571a56dcca3041ff749950645109d357ef77a619472096136a2fec2eaf3174742db9d20a181486c29bc23c4224c9968fc60a17b161408c
+ checksum: dbd4b4ac107908606d24fc5ec1a5be9cc1a972d1345b45908b310dae7fe09fc9f4f49c03edbec4694ed8b2de4c771f98ec228aa155a968b13e82513f33db9eeb
languageName: node
linkType: hard
-"@polkadot/types-support@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/types-support@npm:10.11.2"
+"@polkadot/types-support@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/types-support@npm:10.12.1"
dependencies:
"@polkadot/util": ^12.6.2
tslib: ^2.6.2
- checksum: 6283a5581876c7fba850add6612cd9285a876f506298581392a7db1f0f92357857da86aac031eef515e8d0ca725ec89259bef676b662616242cc5f5efc2527bc
+ checksum: a6eb886fb0e1c56f7c22e96a9255d6dac53fd4e30248c96950867a58854b542943b9143a69052b3b73a596ec2b2665b8857ed98267acf0e55fbeebb1670ca125
languageName: node
linkType: hard
-"@polkadot/types@npm:10.11.2":
- version: 10.11.2
- resolution: "@polkadot/types@npm:10.11.2"
+"@polkadot/types@npm:10.12.1":
+ version: 10.12.1
+ resolution: "@polkadot/types@npm:10.12.1"
dependencies:
"@polkadot/keyring": ^12.6.2
- "@polkadot/types-augment": 10.11.2
- "@polkadot/types-codec": 10.11.2
- "@polkadot/types-create": 10.11.2
+ "@polkadot/types-augment": 10.12.1
+ "@polkadot/types-codec": 10.12.1
+ "@polkadot/types-create": 10.12.1
"@polkadot/util": ^12.6.2
"@polkadot/util-crypto": ^12.6.2
rxjs: ^7.8.1
tslib: ^2.6.2
- checksum: 6e4873329bc8754d6ebdf1e4b20b1ced1edbda554a837c6d47dbc6f3abf8001e74884631bba3695cbd08b07e96ae784191a586d286d3bdfc5a985a0785595049
+ checksum: 6184f50bef018b1fa11e3caaf851dc6fc7510c3dc56f81cfbde1b401f30ddd8ac73083770af41f3c8b3aa76beb4784d9ddb772460ab77c933628385090ab290c
languageName: node
linkType: hard
@@ -2373,7 +2437,7 @@ __metadata:
languageName: node
linkType: hard
-"@scure/base@npm:^1.1.5":
+"@scure/base@npm:^1.1.1, @scure/base@npm:^1.1.5":
version: 1.1.5
resolution: "@scure/base@npm:1.1.5"
checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519
@@ -2412,20 +2476,46 @@ __metadata:
languageName: node
linkType: hard
-"@substrate/connect-extension-protocol@npm:^1.0.1":
- version: 1.0.1
- resolution: "@substrate/connect-extension-protocol@npm:1.0.1"
- checksum: 116dee587e81e832e14c25038bd849438c9493c6089aa6c1bf1760780d463880d44d362ed983d57ac3695368ac46f3c9df3dbaed92f36de89626c9735cecd1e4
+"@substrate/connect-extension-protocol@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@substrate/connect-extension-protocol@npm:2.0.0"
+ checksum: a7c6ff3fefc0784f28b1d253514c1d2951684fe3d06392dfd70299fa2184fbe040d2bd6e0f113e30a1920920b649d43668aa4565847778ab3334c7e445e880cf
+ languageName: node
+ linkType: hard
+
+"@substrate/connect-known-chains@npm:^1.0.7":
+ version: 1.0.9
+ resolution: "@substrate/connect-known-chains@npm:1.0.9"
+ checksum: 58a25df8dd8e7836e7ff932c3834e6cee67b820c0ee4832eb08d3ef25e6523c9560edd6ddecc96cb816fcbbb1ed01a3e0df50d1cf58a4bf9cc820180f21269e8
languageName: node
linkType: hard
-"@substrate/connect@npm:0.7.35":
- version: 0.7.35
- resolution: "@substrate/connect@npm:0.7.35"
+"@substrate/connect@npm:0.8.7":
+ version: 0.8.7
+ resolution: "@substrate/connect@npm:0.8.7"
dependencies:
- "@substrate/connect-extension-protocol": ^1.0.1
- smoldot: 2.0.7
- checksum: 4f0cfb2b9521c5300cbcc0245e87b72484738e6cc8103ddf91e3516f627de546d0a152839824ac2716b8ea2f327f3eee0f74a9a07886ed4a091e3b7c1e989441
+ "@substrate/connect-extension-protocol": ^2.0.0
+ "@substrate/connect-known-chains": ^1.0.7
+ "@substrate/light-client-extension-helpers": ^0.0.3
+ smoldot: 2.0.21
+ checksum: 8390d03f463690b63193363024c4c9edafebebe1722acd95d07a8177630d85039d7115cf1c502d1d8254adbea97e5b3cf49ec36841cebefeb0408201e39e8fc5
+ languageName: node
+ linkType: hard
+
+"@substrate/light-client-extension-helpers@npm:^0.0.3":
+ version: 0.0.3
+ resolution: "@substrate/light-client-extension-helpers@npm:0.0.3"
+ dependencies:
+ "@polkadot-api/client": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/json-rpc-provider": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/json-rpc-provider-proxy": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@polkadot-api/substrate-client": 0.0.1-12c4b0432a814086c3c1a3b8052b31c72c2c9ad3.1.0
+ "@substrate/connect-extension-protocol": ^2.0.0
+ "@substrate/connect-known-chains": ^1.0.7
+ rxjs: ^7.8.1
+ peerDependencies:
+ smoldot: 2.x
+ checksum: a2e4a1df8f76c10c7ef3193cd4c7633beaea59e840afa71b74a5d90bdd8b335f1ec7b847b3c30e84be6e59bd25a8240549860d3016e3851a14aced45eac339a7
languageName: node
linkType: hard
@@ -9115,14 +9205,14 @@ __metadata:
languageName: node
linkType: hard
-"nock@npm:^13.4.0":
- version: 13.5.3
- resolution: "nock@npm:13.5.3"
+"nock@npm:^13.5.0":
+ version: 13.5.4
+ resolution: "nock@npm:13.5.4"
dependencies:
debug: ^4.1.0
json-stringify-safe: ^5.0.1
propagate: ^2.0.0
- checksum: f119e71d8e56a456a29bfa00a1d959387210fe8ada69443a7102fa9329a9c5fb2e0db149c4a00d304b11681127efd03fc0e6bc142a4ff609b1e153f70aa8712d
+ checksum: d31f924e34c87ae985edfb7b5a56e8a4dcfc3a072334ceb6d686326581f93090b3e23492663a64ce61b8df4f365b113231d926bc300bcfe9e5eb309c3e4b8628
languageName: node
linkType: hard
@@ -10464,6 +10554,13 @@ __metadata:
languageName: node
linkType: hard
+"scale-ts@npm:^1.4.3":
+ version: 1.6.0
+ resolution: "scale-ts@npm:1.6.0"
+ checksum: 2cd6d3e31ea78621fe2e068eedc3beb6a3cfc338c9033f04ec3e355b4b08e134febad655c54a80272a50737136a27436f9d14d6525b126e621a3b77524111056
+ languageName: node
+ linkType: hard
+
"scheduler@npm:^0.23.0":
version: 0.23.0
resolution: "scheduler@npm:0.23.0"
@@ -10686,12 +10783,12 @@ __metadata:
languageName: node
linkType: hard
-"smoldot@npm:2.0.7":
- version: 2.0.7
- resolution: "smoldot@npm:2.0.7"
+"smoldot@npm:2.0.21":
+ version: 2.0.21
+ resolution: "smoldot@npm:2.0.21"
dependencies:
ws: ^8.8.1
- checksum: fc039bfa0560312ae09c2136dd506f2a1994ead804b7234b49b2ecfac2fd19d306973a0fcfb66019645a8cf9a1702c270bc544a622ae40b63cf14790ea3531e0
+ checksum: 464f23dd20e8156ab63dfdccf719da9a9e245b4c1581844c3d76ab64384154f578261810d9f3d1957739577a1bccbf51b6a7467f7862f092c45b47f8e1e7b9a4
languageName: node
linkType: hard