evernode-js-client 0.4.46 → 0.4.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +154 -26
- package/package.json +1 -1
package/index.js
CHANGED
@@ -11708,7 +11708,7 @@ const codec = __nccwpck_require__(597);
|
|
11708
11708
|
const { Buffer } = __nccwpck_require__(4300);
|
11709
11709
|
const { XrplApi } = __nccwpck_require__(1850);
|
11710
11710
|
const { XrplAccount } = __nccwpck_require__(9329);
|
11711
|
-
const { XrplApiEvents } = __nccwpck_require__(3307);
|
11711
|
+
const { XrplApiEvents, XrplConstants } = __nccwpck_require__(3307);
|
11712
11712
|
const { EvernodeEvents, MemoTypes, MemoFormats, EvernodeConstants, HookStateKeys } = __nccwpck_require__(9849);
|
11713
11713
|
const { DefaultValues } = __nccwpck_require__(8262);
|
11714
11714
|
const { EncryptionHelper } = __nccwpck_require__(4832);
|
@@ -12055,23 +12055,52 @@ class BaseEvernodeClient {
|
|
12055
12055
|
}
|
12056
12056
|
}
|
12057
12057
|
}
|
12058
|
+
else if (tx.Memos.length >= 1 &&
|
12059
|
+
tx.Memos[0].type === MemoTypes.DEAD_HOST_PRUNE && tx.Memos[0].format === MemoFormats.HEX && tx.Memos[0].data) {
|
12060
|
+
|
12061
|
+
const addrsBuf = Buffer.from(tx.Memos[0].data, 'hex');
|
12062
|
+
|
12063
|
+
return {
|
12064
|
+
name: EvernodeEvents.DeadHostPrune,
|
12065
|
+
data: {
|
12066
|
+
transaction: tx,
|
12067
|
+
host: codec.encodeAccountID(addrsBuf)
|
12068
|
+
}
|
12069
|
+
}
|
12070
|
+
}
|
12058
12071
|
|
12059
12072
|
return null;
|
12060
12073
|
}
|
12061
12074
|
|
12062
12075
|
// To get Host details from Hook States.
|
12063
12076
|
async getHostInfo(hostAddress = this.xrplAcc.address) {
|
12064
|
-
|
12065
|
-
|
12066
|
-
|
12067
|
-
|
12068
|
-
|
12069
|
-
|
12070
|
-
|
12071
|
-
|
12072
|
-
|
12073
|
-
|
12074
|
-
|
12077
|
+
try {
|
12078
|
+
const addrStateKey = StateHelpers.generateHostAddrStateKey(hostAddress);
|
12079
|
+
const addrStateIndex = StateHelpers.getHookStateIndex(this.registryAddress, addrStateKey);
|
12080
|
+
const addrLedgerEntry = await this.xrplApi.getLedgerEntry(addrStateIndex);
|
12081
|
+
const addrStateData = addrLedgerEntry?.HookStateData;
|
12082
|
+
if (addrStateData) {
|
12083
|
+
const addrStateDecoded = StateHelpers.decodeHostAddressState(Buffer.from(addrStateKey, 'hex'), Buffer.from(addrStateData, 'hex'));
|
12084
|
+
const curMomentStartIdx = await this.getMomentStartIndex();
|
12085
|
+
addrStateDecoded.active = (addrStateDecoded.lastHeartbeatLedger > (this.config.hostHeartbeatFreq * this.config.momentSize) ?
|
12086
|
+
(addrStateDecoded.lastHeartbeatLedger >= (curMomentStartIdx - (this.config.hostHeartbeatFreq * this.config.momentSize))) :
|
12087
|
+
(addrStateDecoded.lastHeartbeatLedger > 0))
|
12088
|
+
|
12089
|
+
const nftIdStatekey = StateHelpers.generateTokenIdStateKey(addrStateDecoded.nfTokenId);
|
12090
|
+
const nftIdStateIndex = StateHelpers.getHookStateIndex(this.registryAddress, nftIdStatekey);
|
12091
|
+
const nftIdLedgerEntry = await this.xrplApi.getLedgerEntry(nftIdStateIndex);
|
12092
|
+
|
12093
|
+
const nftIdStateData = nftIdLedgerEntry?.HookStateData;
|
12094
|
+
if (nftIdStateData) {
|
12095
|
+
const nftIdStateDecoded = StateHelpers.decodeTokenIdState(Buffer.from(nftIdStateData, 'hex'));
|
12096
|
+
return { ...addrStateDecoded, ...nftIdStateDecoded };
|
12097
|
+
}
|
12098
|
+
}
|
12099
|
+
}
|
12100
|
+
catch (e) {
|
12101
|
+
// If the exeption is entryNotFound from Rippled there's no entry for the host, So return null.
|
12102
|
+
if (e?.data?.error !== 'entryNotFound')
|
12103
|
+
throw e;
|
12075
12104
|
}
|
12076
12105
|
|
12077
12106
|
return null;
|
@@ -12129,6 +12158,22 @@ class BaseEvernodeClient {
|
|
12129
12158
|
|
12130
12159
|
return fullHostList;
|
12131
12160
|
}
|
12161
|
+
|
12162
|
+
// To prune an inactive host/
|
12163
|
+
async pruneDeadHost(hostAddress) {
|
12164
|
+
if (this.xrplAcc.address === this.registryAddress)
|
12165
|
+
throw 'Invalid function call';
|
12166
|
+
|
12167
|
+
let memoData = Buffer.allocUnsafe(20);
|
12168
|
+
codec.decodeAccountID(hostAddress).copy(memoData);
|
12169
|
+
|
12170
|
+
await this.xrplAcc.makePayment(this.registryAddress,
|
12171
|
+
XrplConstants.MIN_XRP_AMOUNT,
|
12172
|
+
XrplConstants.XRP,
|
12173
|
+
null,
|
12174
|
+
[{ type: MemoTypes.DEAD_HOST_PRUNE, format: MemoFormats.HEX, data: memoData.toString('hex') }]);
|
12175
|
+
|
12176
|
+
}
|
12132
12177
|
}
|
12133
12178
|
|
12134
12179
|
module.exports = {
|
@@ -12513,7 +12558,8 @@ const RegistryEvents = {
|
|
12513
12558
|
HostRegUpdated: EvernodeEvents.HostRegUpdated,
|
12514
12559
|
RegistryInitialized: EvernodeEvents.RegistryInitialized,
|
12515
12560
|
Heartbeat: EvernodeEvents.Heartbeat,
|
12516
|
-
HostPostDeregistered: EvernodeEvents.HostPostDeregistered
|
12561
|
+
HostPostDeregistered: EvernodeEvents.HostPostDeregistered,
|
12562
|
+
DeadHostPrune: EvernodeEvents.DeadHostPrune
|
12517
12563
|
}
|
12518
12564
|
|
12519
12565
|
class RegistryClient extends BaseEvernodeClient {
|
@@ -12621,9 +12667,9 @@ class TenantClient extends BaseEvernodeClient {
|
|
12621
12667
|
|
12622
12668
|
// Check whether active.
|
12623
12669
|
const hostInfo = await this.getHostInfo(host.address);
|
12624
|
-
if (hostInfo)
|
12670
|
+
if (!hostInfo)
|
12625
12671
|
throw { reason: ErrorReasons.HOST_INVALID, error: "Host is not registered." };
|
12626
|
-
else if (hostInfo.active)
|
12672
|
+
else if (!hostInfo.active)
|
12627
12673
|
throw { reason: ErrorReasons.HOST_INACTIVE, error: "Host is not active." };
|
12628
12674
|
|
12629
12675
|
return host;
|
@@ -13178,7 +13224,8 @@ const MemoTypes = {
|
|
13178
13224
|
EXTEND_REF: 'evnExtendRef',
|
13179
13225
|
REGISTRY_INIT: 'evnInitialize',
|
13180
13226
|
REFUND: 'evnRefund',
|
13181
|
-
REFUND_REF: 'evnRefundRef'
|
13227
|
+
REFUND_REF: 'evnRefundRef',
|
13228
|
+
DEAD_HOST_PRUNE: 'evnDeadHostPrune'
|
13182
13229
|
}
|
13183
13230
|
|
13184
13231
|
const MemoFormats = {
|
@@ -13216,11 +13263,15 @@ const HookStateKeys = {
|
|
13216
13263
|
HOST_HEARTBEAT_FREQ: "4556520100000000000000000000000000000000000000000000000000000006",
|
13217
13264
|
PURCHASER_TARGET_PRICE: "4556520100000000000000000000000000000000000000000000000000000007",
|
13218
13265
|
LEASE_ACQUIRE_WINDOW: "4556520100000000000000000000000000000000000000000000000000000008",
|
13266
|
+
REWARD_CONFIGURATION: "4556520100000000000000000000000000000000000000000000000000000009",
|
13267
|
+
MAX_TOLERABLE_DOWNTIME: "455652010000000000000000000000000000000000000000000000000000000A",
|
13268
|
+
|
13219
13269
|
// Singleton
|
13220
13270
|
HOST_COUNT: "4556523200000000000000000000000000000000000000000000000000000000",
|
13221
13271
|
MOMENT_BASE_IDX: "4556523300000000000000000000000000000000000000000000000000000000",
|
13222
13272
|
HOST_REG_FEE: "4556523400000000000000000000000000000000000000000000000000000000",
|
13223
13273
|
MAX_REG: "4556523500000000000000000000000000000000000000000000000000000000",
|
13274
|
+
REWARD_INFO: "4556523600000000000000000000000000000000000000000000000000000000",
|
13224
13275
|
|
13225
13276
|
// Prefixes
|
13226
13277
|
PREFIX_HOST_TOKENID: "45565202",
|
@@ -13240,7 +13291,8 @@ const EvernodeEvents = {
|
|
13240
13291
|
ExtendError: "ExtendError",
|
13241
13292
|
HostRegUpdated: "HostRegUpdated",
|
13242
13293
|
HostReRegistered: "HostReRegistered",
|
13243
|
-
RegistryInitialized: "RegistryInitialized"
|
13294
|
+
RegistryInitialized: "RegistryInitialized",
|
13295
|
+
DeadHostPrune: "DeadHostPrune"
|
13244
13296
|
}
|
13245
13297
|
|
13246
13298
|
module.exports = {
|
@@ -13313,6 +13365,13 @@ class FirestoreHandler {
|
|
13313
13365
|
case 'floatValue':
|
13314
13366
|
parsed = parseFloat(value[type]);
|
13315
13367
|
break;
|
13368
|
+
case 'mapValue':
|
13369
|
+
parsed = {};
|
13370
|
+
for (const [subKey, subValue] of Object.entries(value[type].fields)) {
|
13371
|
+
const field = this.#parseValue(subKey, subValue);
|
13372
|
+
parsed[field.key] = field.value;
|
13373
|
+
}
|
13374
|
+
break;
|
13316
13375
|
default:
|
13317
13376
|
parsed = value[type];
|
13318
13377
|
break;
|
@@ -13520,9 +13579,32 @@ class FirestoreHandler {
|
|
13520
13579
|
convertValue(key, value) {
|
13521
13580
|
// Convert camelCase to snake_case.
|
13522
13581
|
const uKey = key.replace(/([A-Z])/g, function (g) { return `_${g[0].toLocaleLowerCase()}`; });
|
13523
|
-
|
13582
|
+
let val = {};
|
13583
|
+
let type
|
13584
|
+
switch (typeof value) {
|
13585
|
+
case 'number':
|
13586
|
+
type = (value % 1 > 0 ? 'float' : 'integer');
|
13587
|
+
val = value;
|
13588
|
+
break;
|
13589
|
+
case 'object':
|
13590
|
+
type = 'map';
|
13591
|
+
val = {
|
13592
|
+
fields: {}
|
13593
|
+
}
|
13594
|
+
// Prepare the firestore write body with the given data object.
|
13595
|
+
for (const [subKey, subValue] of Object.entries(value)) {
|
13596
|
+
const field = this.convertValue(subKey, subValue);
|
13597
|
+
val.fields[field.key] = field.value;
|
13598
|
+
}
|
13599
|
+
break;
|
13600
|
+
default:
|
13601
|
+
type = 'string';
|
13602
|
+
val = value;
|
13603
|
+
break;
|
13604
|
+
}
|
13605
|
+
type = `${type}Value`;
|
13524
13606
|
let obj = {};
|
13525
|
-
obj[type] =
|
13607
|
+
obj[type] = val;
|
13526
13608
|
return { key: uKey, value: obj };
|
13527
13609
|
}
|
13528
13610
|
|
@@ -13608,7 +13690,18 @@ const { HookStateKeys, EvernodeConstants } = __nccwpck_require__(9849);
|
|
13608
13690
|
const { XflHelpers } = __nccwpck_require__(3243);
|
13609
13691
|
const crypto = __nccwpck_require__(6113);
|
13610
13692
|
|
13611
|
-
const NFTOKEN_PREFIX = '
|
13693
|
+
const NFTOKEN_PREFIX = '00000000';
|
13694
|
+
|
13695
|
+
const EPOCH_OFFSET = 0;
|
13696
|
+
const SAVED_MOMENT_OFFSET = 1;
|
13697
|
+
const PREV_MOMENT_ACTIVE_HOST_COUNT_OFFSET = 5;
|
13698
|
+
const CUR_MOMENT_ACTIVE_HOST_COUNT_OFFSET = 9;
|
13699
|
+
const EPOCH_POOL_OFFSET = 13;
|
13700
|
+
|
13701
|
+
const EPOCH_COUNT_OFFSET = 0;
|
13702
|
+
const FIRST_EPOCH_REWARD_QUOTA_OFFSET = 1;
|
13703
|
+
const EPOCH_REWARD_AMOUNT_OFFSET = 5;
|
13704
|
+
const REWARD_START_MOMENT_OFFSET = 9;
|
13612
13705
|
|
13613
13706
|
const HOST_TOKEN_ID_OFFSET = 0;
|
13614
13707
|
const HOST_COUNTRY_CODE_OFFSET = 32;
|
@@ -13664,7 +13757,7 @@ class StateHelpers {
|
|
13664
13757
|
static decodeTokenIdState(stateDataBuf) {
|
13665
13758
|
return {
|
13666
13759
|
address: codec.encodeAccountID(stateDataBuf.slice(HOST_ADDRESS_OFFSET, HOST_CPU_MODEL_NAME_OFFSET)),
|
13667
|
-
cpuModelName: stateDataBuf.slice(HOST_CPU_MODEL_NAME_OFFSET, HOST_CPU_COUNT_OFFSET).toString(),
|
13760
|
+
cpuModelName: stateDataBuf.slice(HOST_CPU_MODEL_NAME_OFFSET, HOST_CPU_COUNT_OFFSET).toString().replace(/\x00+$/, ''), // Remove trailing \x00 characters.
|
13668
13761
|
cpuCount: stateDataBuf.readUInt16BE(HOST_CPU_COUNT_OFFSET),
|
13669
13762
|
cpuMHz: stateDataBuf.readUInt16BE(HOST_CPU_SPEED_OFFSET),
|
13670
13763
|
cpuMicrosec: stateDataBuf.readUInt32BE(HOST_CPU_MICROSEC_OFFSET),
|
@@ -13747,6 +13840,38 @@ class StateHelpers {
|
|
13747
13840
|
value: val
|
13748
13841
|
}
|
13749
13842
|
}
|
13843
|
+
else if (Buffer.from(HookStateKeys.REWARD_CONFIGURATION, 'hex').compare(stateKey) === 0) {
|
13844
|
+
return {
|
13845
|
+
type: this.StateTypes.CONFIGURATION,
|
13846
|
+
key: hexKey,
|
13847
|
+
value: {
|
13848
|
+
epochCount: stateData.readUInt8(EPOCH_COUNT_OFFSET),
|
13849
|
+
firstEpochRewardQuota: stateData.readUInt32BE(FIRST_EPOCH_REWARD_QUOTA_OFFSET),
|
13850
|
+
epochRewardAmount: stateData.readUInt32BE(EPOCH_REWARD_AMOUNT_OFFSET),
|
13851
|
+
rewardStartMoment: stateData.readUInt32BE(REWARD_START_MOMENT_OFFSET)
|
13852
|
+
}
|
13853
|
+
}
|
13854
|
+
}
|
13855
|
+
else if (Buffer.from(HookStateKeys.REWARD_INFO, 'hex').compare(stateKey) === 0) {
|
13856
|
+
return {
|
13857
|
+
type: this.StateTypes.SIGLETON,
|
13858
|
+
key: hexKey,
|
13859
|
+
value: {
|
13860
|
+
epoch: stateData.readUInt8(EPOCH_OFFSET),
|
13861
|
+
savedMoment: stateData.readUInt32BE(SAVED_MOMENT_OFFSET),
|
13862
|
+
prevMomentActiveHostCount: stateData.readUInt32BE(PREV_MOMENT_ACTIVE_HOST_COUNT_OFFSET),
|
13863
|
+
curMomentActiveHostCount: stateData.readUInt32BE(CUR_MOMENT_ACTIVE_HOST_COUNT_OFFSET),
|
13864
|
+
epochPool: XflHelpers.toString(stateData.readBigInt64BE(EPOCH_POOL_OFFSET))
|
13865
|
+
}
|
13866
|
+
}
|
13867
|
+
}
|
13868
|
+
else if (Buffer.from(HookStateKeys.MAX_TOLERABLE_DOWNTIME, 'hex').compare(stateKey) === 0) {
|
13869
|
+
return {
|
13870
|
+
type: this.StateTypes.CONFIGURATION,
|
13871
|
+
key: hexKey,
|
13872
|
+
value: stateData.readUInt16BE()
|
13873
|
+
}
|
13874
|
+
}
|
13750
13875
|
else
|
13751
13876
|
throw { type: 'Validation Error', message: 'Invalid state key.' };
|
13752
13877
|
}
|
@@ -13768,7 +13893,8 @@ class StateHelpers {
|
|
13768
13893
|
else if (Buffer.from(HookStateKeys.HOST_COUNT, 'hex').compare(stateKey) === 0 ||
|
13769
13894
|
Buffer.from(HookStateKeys.MOMENT_BASE_IDX, 'hex').compare(stateKey) === 0 ||
|
13770
13895
|
Buffer.from(HookStateKeys.HOST_REG_FEE, 'hex').compare(stateKey) === 0 ||
|
13771
|
-
Buffer.from(HookStateKeys.MAX_REG, 'hex').compare(stateKey) === 0
|
13896
|
+
Buffer.from(HookStateKeys.MAX_REG, 'hex').compare(stateKey) === 0 ||
|
13897
|
+
Buffer.from(HookStateKeys.REWARD_INFO, 'hex').compare(stateKey) === 0) {
|
13772
13898
|
return {
|
13773
13899
|
key: hexKey,
|
13774
13900
|
type: this.STATE_TYPES.SIGLETON
|
@@ -13781,7 +13907,9 @@ class StateHelpers {
|
|
13781
13907
|
Buffer.from(HookStateKeys.HOST_HEARTBEAT_FREQ, 'hex').compare(stateKey) ||
|
13782
13908
|
Buffer.from(HookStateKeys.MINT_LIMIT, 'hex').compare(stateKey) === 0 ||
|
13783
13909
|
Buffer.from(HookStateKeys.FIXED_REG_FEE, 'hex').compare(stateKey) === 0 ||
|
13784
|
-
Buffer.from(HookStateKeys.LEASE_ACQUIRE_WINDOW, 'hex').compare(stateKey) === 0
|
13910
|
+
Buffer.from(HookStateKeys.LEASE_ACQUIRE_WINDOW, 'hex').compare(stateKey) === 0 ||
|
13911
|
+
Buffer.from(HookStateKeys.REWARD_CONFIGURATION, 'hex').compare(stateKey) === 0 ||
|
13912
|
+
Buffer.from(HookStateKeys.MAX_TOLERABLE_DOWNTIME, 'hex').compare(stateKey) === 0) {
|
13785
13913
|
return {
|
13786
13914
|
key: hexKey,
|
13787
13915
|
type: this.STATE_TYPES.CONFIGURATION
|
@@ -13807,7 +13935,7 @@ class StateHelpers {
|
|
13807
13935
|
let buf = Buffer.allocUnsafe(9);
|
13808
13936
|
buf.writeUInt8(STATE_KEY_TYPES.HOST_ADDR);
|
13809
13937
|
for (let i = 0; i < HOST_ADDR_KEY_ZERO_COUNT; i++) {
|
13810
|
-
buf.writeUInt8(0, i+1);
|
13938
|
+
buf.writeUInt8(0, i + 1);
|
13811
13939
|
}
|
13812
13940
|
|
13813
13941
|
const addrBuf = Buffer.from(codec.decodeAccountID(address), "hex");
|
@@ -13815,7 +13943,7 @@ class StateHelpers {
|
|
13815
13943
|
return stateKeyBuf.toString('hex').toUpperCase();
|
13816
13944
|
}
|
13817
13945
|
|
13818
|
-
static
|
13946
|
+
static getHookStateIndex(hookAccount, stateKey, hookNamespace = EvernodeConstants.HOOK_NAMESPACE) {
|
13819
13947
|
const typeBuf = Buffer.allocUnsafe(2);
|
13820
13948
|
typeBuf.writeInt16BE(HOOK_STATE_LEDGER_TYPE_PREFIX);
|
13821
13949
|
|
@@ -14798,7 +14926,7 @@ class XrplApi {
|
|
14798
14926
|
|
14799
14927
|
async getLedgerEntry(index, options) {
|
14800
14928
|
const resp = (await this.#client.request({ command: 'ledger_entry', index: index, ledger_index: "validated", ...options }));
|
14801
|
-
|
14929
|
+
return resp?.result?.node;
|
14802
14930
|
}
|
14803
14931
|
|
14804
14932
|
async submitAndVerify(tx, options) {
|