evernode-js-client 0.4.46 → 0.4.50
Sign up to get free protection for your applications and to get access to all the features.
- 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) {
|