evernode-js-client 0.6.50 → 0.6.51

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. package/index.js +165 -54
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -59620,6 +59620,9 @@ class BaseEvernodeClient {
59620
59620
  if (!options.xrplApi && !Defaults.values.xrplApi)
59621
59621
  this.#ownsXrplApi = true;
59622
59622
 
59623
+ if (options.config)
59624
+ this.config = options.config;
59625
+
59623
59626
  this.xrplAcc = new XrplAccount(xrpAddress, xrpSecret, { xrplApi: this.xrplApi });
59624
59627
  this.accKeyPair = xrpSecret && this.xrplAcc.deriveKeypair();
59625
59628
  this.messagePrivateKey = options.messagePrivateKey || (this.accKeyPair ? this.accKeyPair.privateKey : null);
@@ -59665,7 +59668,7 @@ class BaseEvernodeClient {
59665
59668
  * Connects the client to xrpl server and do the config loading and subscriptions. 'subscribe' is called inside this.
59666
59669
  * @returns boolean value, 'true' if success.
59667
59670
  */
59668
- async connect() {
59671
+ async connect(options = {}) {
59669
59672
  if (this.connected)
59670
59673
  return true;
59671
59674
 
@@ -59675,7 +59678,9 @@ class BaseEvernodeClient {
59675
59678
  // identify a network reset from XRPL.
59676
59679
  await this.xrplAcc.getInfo();
59677
59680
 
59678
- this.config = await this.#getEvernodeConfig();
59681
+ if (!this.config && !options.skipConfigs)
59682
+ this.config = await this.#getEvernodeConfig();
59683
+
59679
59684
  this.connected = true;
59680
59685
 
59681
59686
  if (this.#autoSubscribe)
@@ -59764,7 +59769,6 @@ class BaseEvernodeClient {
59764
59769
  * @returns An object with all the configuration and their values.
59765
59770
  */
59766
59771
  async #getEvernodeConfig() {
59767
- let states = await this.getHookStates();
59768
59772
  const configStateKeys = {
59769
59773
  registryAddress: HookStateKeys.REGISTRY_ADDR,
59770
59774
  heartbeatAddress: HookStateKeys.HEARTBEAT_ADDR,
@@ -59788,12 +59792,12 @@ class BaseEvernodeClient {
59788
59792
  }
59789
59793
  let config = {};
59790
59794
  for (const [key, value] of Object.entries(configStateKeys)) {
59791
- const stateKey = Buffer.from(value, 'hex');
59792
- const stateDataBin = StateHelpers.getStateData(states, value);
59793
- if (stateDataBin) {
59794
- const stateData = Buffer.from(StateHelpers.getStateData(states, value), 'hex');
59795
- const decoded = StateHelpers.decodeStateData(stateKey, stateData);
59796
- config[key] = decoded.value;
59795
+ const index = StateHelpers.getHookStateIndex(this.governorAddress, value);
59796
+ const ledgerEntry = await this.xrplApi.getLedgerEntry(index);
59797
+ const stateData = ledgerEntry?.HookStateData;
59798
+ if (stateData) {
59799
+ const stateDecoded = StateHelpers.decodeStateData(Buffer.from(value, 'hex'), Buffer.from(stateData, 'hex'));
59800
+ config[key] = stateDecoded.value;
59797
59801
  }
59798
59802
  }
59799
59803
  return config;
@@ -60485,13 +60489,63 @@ class BaseEvernodeClient {
60485
60489
  return null;
60486
60490
  }
60487
60491
 
60492
+ async getReputationAddressByOrderId(hostReputationOrderedId, moment = null) {
60493
+ try {
60494
+ const repMoment = moment ?? await this.getMoment();
60495
+ const orderedIdStateKey = StateHelpers.generateHostReputationOrderedIdStateKey(hostReputationOrderedId, repMoment);
60496
+ const orderedIdStateIndex = StateHelpers.getHookStateIndex(this.xrplAcc.address, orderedIdStateKey);
60497
+ const orderedIdLedgerEntry = await this.xrplApi.getLedgerEntry(orderedIdStateIndex);
60498
+ const orderedIdStateData = orderedIdLedgerEntry?.HookStateData;
60499
+
60500
+ if (orderedIdStateData) {
60501
+ const orderedIdStateDecoded = StateHelpers.decodeHostReputationOrderedIdState(Buffer.from(orderedIdStateKey, 'hex'), Buffer.from(orderedIdStateData, 'hex'));
60502
+ return orderedIdStateDecoded;
60503
+ }
60504
+ }
60505
+ catch (e) {
60506
+ // If the exception is entryNotFound from Rippled there's no entry for the host, So return null.
60507
+ if (e?.data?.error !== 'entryNotFound')
60508
+ throw e;
60509
+ }
60510
+
60511
+ return null;
60512
+ }
60513
+
60488
60514
  /**
60489
60515
  * Get reputation info of given host.
60490
60516
  * @param {string} hostReputationAddress Host's reputation address.
60491
60517
  * @param {number} moment (optional) Moment to get reputation info for.
60492
60518
  * @returns Reputation info object.
60493
60519
  */
60494
- async _getReputationInfoByAddress(hostReputationAddress, moment = null) {
60520
+ async getReputationOrderByAddress(hostReputationAddress, moment = null) {
60521
+ try {
60522
+ const repMoment = moment ?? await this.getMoment();
60523
+ const orderedAddrStateKey = StateHelpers.generateHostReputationOrderAddressStateKey(hostReputationAddress, repMoment);
60524
+ const orderedAddrStateIndex = StateHelpers.getHookStateIndex(this.config.reputationAddress, orderedAddrStateKey);
60525
+ const orderedAddrLedgerEntry = await this.xrplApi.getLedgerEntry(orderedAddrStateIndex);
60526
+ const orderedAddrStateData = orderedAddrLedgerEntry?.HookStateData;
60527
+
60528
+ if (orderedAddrStateData) {
60529
+ const orderedAddrStateDecoded = StateHelpers.decodeHostReputationOrderAddressState(Buffer.from(orderedAddrStateKey, 'hex'), Buffer.from(orderedAddrStateData, 'hex'));
60530
+ return orderedAddrStateDecoded;
60531
+ }
60532
+ }
60533
+ catch (e) {
60534
+ // If the exception is entryNotFound from Rippled there's no entry for the host, So return null.
60535
+ if (e?.data?.error !== 'entryNotFound')
60536
+ throw e;
60537
+ }
60538
+
60539
+ return null;
60540
+ }
60541
+
60542
+ /**
60543
+ * Get reputation info of given host.
60544
+ * @param {string} hostReputationAddress Host's reputation address.
60545
+ * @param {number} moment (optional) Moment to get reputation info for.
60546
+ * @returns Reputation info object.
60547
+ */
60548
+ async getReputationInfoByAddress(hostReputationAddress, moment = null) {
60495
60549
  try {
60496
60550
  const addrStateKey = StateHelpers.generateHostReputationAddrStateKey(hostReputationAddress);
60497
60551
  const addrStateIndex = StateHelpers.getHookStateIndex(this.config.reputationAddress, addrStateKey);
@@ -60505,15 +60559,6 @@ class BaseEvernodeClient {
60505
60559
  }
60506
60560
 
60507
60561
  const repMoment = moment ?? await this.getMoment();
60508
- const orderedAddrStateKey = StateHelpers.generateHostReputationOrderAddressStateKey(hostReputationAddress, repMoment);
60509
- const orderedAddrStateIndex = StateHelpers.getHookStateIndex(this.config.reputationAddress, orderedAddrStateKey);
60510
- const orderedAddrLedgerEntry = await this.xrplApi.getLedgerEntry(orderedAddrStateIndex);
60511
- const orderedAddrStateData = orderedAddrLedgerEntry?.HookStateData;
60512
-
60513
- if (orderedAddrStateData) {
60514
- const orderedAddrStateDecoded = StateHelpers.decodeHostReputationOrderAddressState(Buffer.from(orderedAddrStateKey, 'hex'), Buffer.from(orderedAddrStateData, 'hex'));
60515
- data = { ...data, ...orderedAddrStateDecoded };
60516
- }
60517
60562
 
60518
60563
  const hostRepAcc = new XrplAccount(hostReputationAddress, null, { xrplApi: this.xrplApi });
60519
60564
  const [wl, rep] = await Promise.all([
@@ -60922,26 +60967,39 @@ class HookClientFactory {
60922
60967
  * @param {string} hookType Type of the Required Hook. (Supported Hook types 'GOVERNOR', 'REGISTRY' and 'HEARTBEAT')
60923
60968
  * @returns Instance of requested HookClient type.
60924
60969
  */
60925
- static async create(hookType) {
60970
+ static async create(hookType, options = {}) {
60971
+ let governorClient;
60972
+ if (hookType !== HookTypes.governor && !options.config) {
60973
+ governorClient = new GovernorClient(options);
60974
+ try {
60975
+ await governorClient.connect();
60976
+ options.config = governorClient.config;
60977
+ } catch (error) {
60978
+ throw (error)
60979
+ } finally {
60980
+ await governorClient.disconnect();
60981
+ }
60982
+ }
60983
+
60926
60984
  let hookClient;
60927
60985
  switch (hookType) {
60928
60986
  case HookTypes.governor: {
60929
- hookClient = new GovernorClient();
60987
+ hookClient = new GovernorClient(options);
60930
60988
  break;
60931
60989
  }
60932
60990
  case HookTypes.registry: {
60933
- const registryAddress = await HookClientFactory.#getAccountAddress(hookType);
60934
- hookClient = new RegistryClient({ registryAddress: registryAddress });
60991
+ const registryAddress = await HookClientFactory.#getAccountAddress(hookType, options.config);
60992
+ hookClient = new RegistryClient({ ...options, registryAddress: registryAddress });
60935
60993
  break;
60936
60994
  }
60937
60995
  case HookTypes.heartbeat: {
60938
- const heartbeatAddress = await HookClientFactory.#getAccountAddress(hookType);
60939
- hookClient = new HeartbeatClient({ heartbeatAddress: heartbeatAddress });
60996
+ const heartbeatAddress = await HookClientFactory.#getAccountAddress(hookType, options.config);
60997
+ hookClient = new HeartbeatClient({ ...options, heartbeatAddress: heartbeatAddress });
60940
60998
  break;
60941
60999
  }
60942
61000
  case HookTypes.reputation: {
60943
- const reputationAddress = await HookClientFactory.#getAccountAddress(hookType);
60944
- hookClient = new ReputationClient({ reputationAddress: reputationAddress });
61001
+ const reputationAddress = await HookClientFactory.#getAccountAddress(hookType, options.config);
61002
+ hookClient = new ReputationClient({ ...options, reputationAddress: reputationAddress });
60945
61003
  break;
60946
61004
  }
60947
61005
  default: {
@@ -60953,25 +61011,13 @@ class HookClientFactory {
60953
61011
  return hookClient;
60954
61012
  }
60955
61013
 
60956
- static async #getAccountAddress(hookType) {
60957
- const governorHook = await HookClientFactory.create(HookTypes.governor);
60958
-
60959
- let configs;
60960
- try {
60961
- await governorHook.connect();
60962
- configs = governorHook.config;
60963
- } catch (error) {
60964
- throw (error)
60965
- } finally {
60966
- await governorHook.disconnect();
60967
- }
60968
-
61014
+ static async #getAccountAddress(hookType, config) {
60969
61015
  if (hookType == HookTypes.registry)
60970
- return configs.registryAddress;
61016
+ return config.registryAddress;
60971
61017
  else if (hookType == HookTypes.heartbeat)
60972
- return configs.heartbeatAddress;
61018
+ return config.heartbeatAddress;
60973
61019
  else if (hookType == HookTypes.reputation)
60974
- return configs.reputationAddress;
61020
+ return config.reputationAddress;
60975
61021
  }
60976
61022
  }
60977
61023
 
@@ -61024,8 +61070,11 @@ module.exports = {
61024
61070
  /***/ 7541:
61025
61071
  /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
61026
61072
 
61073
+ const codec = __nccwpck_require__(597);
61027
61074
  const { StateHelpers } = __nccwpck_require__(3860);
61075
+ const { XrplAccount } = __nccwpck_require__(9329);
61028
61076
  const { BaseEvernodeClient } = __nccwpck_require__(6263);
61077
+ const { ReputationConstants } = __nccwpck_require__(9849);
61029
61078
 
61030
61079
  const ReputationEvents = {}
61031
61080
 
@@ -61035,6 +61084,53 @@ class ReputationClient extends BaseEvernodeClient {
61035
61084
  super(options.reputationAddress, null, Object.values(ReputationEvents), false, options);
61036
61085
  }
61037
61086
 
61087
+ async getReputationContractInfoByOrderedId(hostReputationOrderedId, moment = null) {
61088
+ try {
61089
+ const repMoment = moment ?? await this.getMoment();
61090
+ const addressInfo = await this.getReputationAddressByOrderId(hostReputationOrderedId, repMoment);
61091
+ if (addressInfo?.address) {
61092
+ let data = addressInfo;
61093
+
61094
+ const hostRepAcc = new XrplAccount(addressInfo?.address, null, { xrplApi: this.xrplApi });
61095
+ const [wl, rep] = await Promise.all([
61096
+ hostRepAcc.getWalletLocator(),
61097
+ hostRepAcc.getDomain()]);
61098
+
61099
+ if (wl && rep && rep.length > 0) {
61100
+ const hostReputationAccId = wl.slice(0, 40);
61101
+ const hostAddress = codec.encodeAccountID(Buffer.from(hostReputationAccId, 'hex'));
61102
+ const hostAcc = new XrplAccount(hostAddress, null, { xrplApi: this.xrplApi });
61103
+
61104
+ const repBuf = Buffer.from(rep, 'hex');
61105
+ const publicKey = repBuf.slice(0, ReputationConstants.REP_INFO_PEER_PORT_OFFSET).toString('hex').toLocaleLowerCase();
61106
+ const peerPort = repBuf.readUInt16LE(ReputationConstants.REP_INFO_PEER_PORT_OFFSET);
61107
+ const instanceMoment = (repBuf.length > ReputationConstants.REP_INFO_MOMENT_OFFSET) ? Number(repBuf.readBigUInt64LE(ReputationConstants.REP_INFO_MOMENT_OFFSET)) : null;
61108
+ const domain = await hostAcc.getDomain();
61109
+
61110
+ if (instanceMoment === repMoment) {
61111
+ data = {
61112
+ ...data,
61113
+ contract: {
61114
+ domain: domain,
61115
+ pubkey: publicKey,
61116
+ peerPort: peerPort
61117
+ }
61118
+ }
61119
+ }
61120
+ }
61121
+ return data;
61122
+ }
61123
+
61124
+ }
61125
+ catch (e) {
61126
+ // If the exception is entryNotFound from Rippled there's no entry for the host, So return null.
61127
+ if (e?.data?.error !== 'entryNotFound')
61128
+ throw e;
61129
+ }
61130
+
61131
+ return null;
61132
+ }
61133
+
61038
61134
  /**
61039
61135
  * Get reputation info of given host reputation orderId.
61040
61136
  * @param {number} hostReputationOrderedId Reputation order id of the host.
@@ -61044,14 +61140,11 @@ class ReputationClient extends BaseEvernodeClient {
61044
61140
  async getReputationInfoByOrderedId(hostReputationOrderedId, moment = null) {
61045
61141
  try {
61046
61142
  const repMoment = moment ?? await this.getMoment();
61047
- const orderedIdStateKey = StateHelpers.generateHostReputationOrderedIdStateKey(hostReputationOrderedId, repMoment);
61048
- const orderedIdStateIndex = StateHelpers.getHookStateIndex(this.xrplAcc.address, orderedIdStateKey);
61049
- const orderedIdLedgerEntry = await this.xrplApi.getLedgerEntry(orderedIdStateIndex);
61050
- const orderedIdStateData = orderedIdLedgerEntry?.HookStateData;
61143
+ const addressInfo = this.getReputationAddressByOrderId(hostReputationOrderedId, repMoment);
61051
61144
 
61052
- if (orderedIdStateData) {
61053
- const orderedIdStateDecoded = StateHelpers.decodeHostReputationOrderedIdState(Buffer.from(orderedIdStateKey, 'hex'), Buffer.from(orderedIdStateData, 'hex'));
61054
- return await this._getReputationInfoByAddress(orderedIdStateDecoded.address, moment);
61145
+ if (addressInfo?.address) {
61146
+ const info = await this.getReputationInfoByAddress(addressInfo?.address, repMoment);
61147
+ return info ? { ...addressInfo, ...info } : addressInfo;
61055
61148
  }
61056
61149
  }
61057
61150
  catch (e) {
@@ -61162,7 +61255,7 @@ class HostClient extends BaseEvernodeClient {
61162
61255
  }
61163
61256
 
61164
61257
  async connect(options = {}) {
61165
- const res = await super.connect();
61258
+ const res = await super.connect(options);
61166
61259
  await this.setReputationAcc(options.reputationAddress, options.reputationSecret);
61167
61260
  return res;
61168
61261
  }
@@ -61398,7 +61491,22 @@ class HostClient extends BaseEvernodeClient {
61398
61491
  if (!this.reputationAcc)
61399
61492
  return null;
61400
61493
 
61401
- return await this._getReputationInfoByAddress(this.reputationAcc.address, moment);
61494
+ try {
61495
+ const repMoment = moment ?? await this.getMoment();
61496
+ const orderInfo = await this.getReputationOrderByAddress(this.reputationAcc.address, repMoment);
61497
+
61498
+ if (orderInfo?.orderedId) {
61499
+ const info = await this.getReputationInfoByAddress(this.reputationAcc.address, repMoment);
61500
+ return info ? { ...orderInfo, ...info } : orderInfo;
61501
+ }
61502
+ }
61503
+ catch (e) {
61504
+ // If the exception is entryNotFound from Rippled there's no entry for the host, So return null.
61505
+ if (e?.data?.error !== 'entryNotFound')
61506
+ throw e;
61507
+ }
61508
+
61509
+ return null;
61402
61510
  }
61403
61511
 
61404
61512
  /**
@@ -61407,7 +61515,10 @@ class HostClient extends BaseEvernodeClient {
61407
61515
  * @returns Unified reputation score array.
61408
61516
  */
61409
61517
  async prepareHostReputationScores(collectedScores = {}) {
61410
- const myReputationInfo = await this.getReputationInfo();
61518
+ const myReputationInfo = await this.getReputationOrderByAddress(this.reputationAcc.address);
61519
+ if (!myReputationInfo?.orderedId)
61520
+ throw 'You are not registered for reputation for this moment.';
61521
+
61411
61522
  const myOrderId = myReputationInfo.orderedId;
61412
61523
 
61413
61524
  // Deciding universe.
@@ -61418,7 +61529,7 @@ class HostClient extends BaseEvernodeClient {
61418
61529
  let data = {};
61419
61530
  await Promise.all(Array.from({ length: 64 }, (_, i) => i + universeStartIndex).map(async (i) => {
61420
61531
  try {
61421
- const hostReputationInfo = await reputationClient.getReputationInfoByOrderedId(i);
61532
+ const hostReputationInfo = await reputationClient.getReputationContractInfoByOrderedId(i);
61422
61533
  if (!hostReputationInfo)
61423
61534
  throw 'No reputation info for this order id';
61424
61535
  data[i.toString()] = {
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  ],
7
7
  "homepage": "https://github.com/HotPocketDev/evernode-js-client",
8
8
  "license": "SEE LICENSE IN https://raw.githubusercontent.com/EvernodeXRPL/evernode-resources/main/license/evernode-license.pdf",
9
- "version": "0.6.50",
9
+ "version": "0.6.51",
10
10
  "dependencies": {
11
11
  "elliptic": "6.5.4",
12
12
  "libsodium-wrappers": "0.7.10",