evernode-js-client 0.5.9 → 0.5.10
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 +262 -47
- package/package.json +1 -1
package/index.js
CHANGED
@@ -11732,6 +11732,7 @@ const { EventEmitter } = __nccwpck_require__(6170);
|
|
11732
11732
|
const { UtilHelpers } = __nccwpck_require__(6687);
|
11733
11733
|
const { FirestoreHandler } = __nccwpck_require__(9718);
|
11734
11734
|
const { StateHelpers } = __nccwpck_require__(3860);
|
11735
|
+
const { EvernodeHelpers } = __nccwpck_require__(2523);
|
11735
11736
|
|
11736
11737
|
class BaseEvernodeClient {
|
11737
11738
|
|
@@ -12037,17 +12038,13 @@ class BaseEvernodeClient {
|
|
12037
12038
|
}
|
12038
12039
|
}
|
12039
12040
|
else if (tx.Memos.length >= 1 &&
|
12040
|
-
tx.Memos[0].type === MemoTypes.HOST_REG && tx.Memos[0].format === MemoFormats.
|
12041
|
+
tx.Memos[0].type === MemoTypes.HOST_REG && tx.Memos[0].format === MemoFormats.HEX && tx.Memos[0].data) {
|
12041
12042
|
|
12042
|
-
const parts = tx.Memos[0].data.split(';');
|
12043
12043
|
return {
|
12044
12044
|
name: EvernodeEvents.HostRegistered,
|
12045
12045
|
data: {
|
12046
12046
|
transaction: tx,
|
12047
|
-
host: tx.Account
|
12048
|
-
token: parts[0],
|
12049
|
-
instanceSize: parts[1],
|
12050
|
-
location: parts[2]
|
12047
|
+
host: tx.Account
|
12051
12048
|
}
|
12052
12049
|
}
|
12053
12050
|
}
|
@@ -12135,17 +12132,13 @@ class BaseEvernodeClient {
|
|
12135
12132
|
}
|
12136
12133
|
}
|
12137
12134
|
else if (tx.Memos.length >= 1 &&
|
12138
|
-
tx.Memos[0].type === MemoTypes.HOST_UPDATE_INFO && tx.Memos[0].format === MemoFormats.
|
12139
|
-
|
12140
|
-
const specs = tx.Memos[0].data.split(';');
|
12135
|
+
tx.Memos[0].type === MemoTypes.HOST_UPDATE_INFO && tx.Memos[0].format === MemoFormats.HEX && tx.Memos[0].data) {
|
12141
12136
|
|
12142
12137
|
return {
|
12143
12138
|
name: EvernodeEvents.HostRegUpdated,
|
12144
12139
|
data: {
|
12145
12140
|
transaction: tx,
|
12146
|
-
host: tx.Account
|
12147
|
-
version: specs[specs.length - 1],
|
12148
|
-
specs: specs,
|
12141
|
+
host: tx.Account
|
12149
12142
|
}
|
12150
12143
|
}
|
12151
12144
|
}
|
@@ -12238,13 +12231,16 @@ class BaseEvernodeClient {
|
|
12238
12231
|
async getHosts(filters = null, pageSize = null, nextPageToken = null) {
|
12239
12232
|
const hosts = await this.#firestoreHandler.getHosts(filters, pageSize, nextPageToken);
|
12240
12233
|
const curMomentStartIdx = await this.getMomentStartIndex();
|
12241
|
-
|
12242
|
-
(hosts.nextPageToken ? hosts.data : hosts).
|
12243
|
-
|
12244
|
-
|
12245
|
-
|
12246
|
-
|
12247
|
-
|
12234
|
+
|
12235
|
+
return await Promise.all((hosts.nextPageToken ? hosts.data : hosts).map(async host => {
|
12236
|
+
const hostAcc = new XrplAccount(host.address);
|
12237
|
+
host.domain = await hostAcc.getDomain();
|
12238
|
+
|
12239
|
+
host.active = (host.lastHeartbeatIndex > (this.config.hostHeartbeatFreq * this.config.momentSize) ?
|
12240
|
+
(host.lastHeartbeatIndex >= (curMomentStartIdx - (this.config.hostHeartbeatFreq * this.config.momentSize))) :
|
12241
|
+
(host.lastHeartbeatIndex > 0));
|
12242
|
+
return host;
|
12243
|
+
}));
|
12248
12244
|
}
|
12249
12245
|
|
12250
12246
|
/**
|
@@ -12304,11 +12300,28 @@ class BaseEvernodeClient {
|
|
12304
12300
|
let memoData = Buffer.allocUnsafe(20);
|
12305
12301
|
codec.decodeAccountID(hostAddress).copy(memoData);
|
12306
12302
|
|
12307
|
-
|
12308
|
-
|
12309
|
-
|
12310
|
-
|
12311
|
-
|
12303
|
+
// To obtain registration NFT Page Keylet and index.
|
12304
|
+
const hostAcc = new XrplAccount(hostAddress, null, { xrplApi: this.xrplApi });
|
12305
|
+
const regNFT = (await hostAcc.getNfts()).find(n => n.URI.startsWith(EvernodeConstants.NFT_PREFIX_HEX) && n.Issuer === this.registryAddress);
|
12306
|
+
if (regNFT) {
|
12307
|
+
// Check whether the token was actually issued from Evernode registry contract.
|
12308
|
+
const issuerHex = regNFT.NFTokenID.substr(8, 40);
|
12309
|
+
const issuerAddr = codec.encodeAccountID(Buffer.from(issuerHex, 'hex'));
|
12310
|
+
if (issuerAddr == this.registryAddress) {
|
12311
|
+
const nftPageDataBuf = await EvernodeHelpers.getNFTPageAndLocation(regNFT.NFTokenID, hostAcc, this.xrplApi);
|
12312
|
+
|
12313
|
+
await this.xrplAcc.makePayment(this.registryAddress,
|
12314
|
+
XrplConstants.MIN_XRP_AMOUNT,
|
12315
|
+
XrplConstants.XRP,
|
12316
|
+
null,
|
12317
|
+
[
|
12318
|
+
{ type: MemoTypes.DEAD_HOST_PRUNE, format: MemoFormats.HEX, data: memoData.toString('hex') },
|
12319
|
+
{ type: MemoTypes.HOST_REGISTRY_REF, format: MemoFormats.HEX, data: nftPageDataBuf.toString('hex') }
|
12320
|
+
]);
|
12321
|
+
} else
|
12322
|
+
throw "Invalid Registration NFT."
|
12323
|
+
} else
|
12324
|
+
throw "No Registration NFT was found for the Host account."
|
12312
12325
|
|
12313
12326
|
}
|
12314
12327
|
}
|
@@ -12341,6 +12354,29 @@ const HostEvents = {
|
|
12341
12354
|
ExtendLease: EvernodeEvents.ExtendLease
|
12342
12355
|
}
|
12343
12356
|
|
12357
|
+
const HOST_COUNTRY_CODE_MEMO_OFFSET = 0;
|
12358
|
+
const HOST_CPU_MICROSEC_MEMO_OFFSET = 2;
|
12359
|
+
const HOST_RAM_MB_MEMO_OFFSET = 6;
|
12360
|
+
const HOST_DISK_MB_MEMO_OFFSET = 10;
|
12361
|
+
const HOST_TOT_INS_COUNT_MEMO_OFFSET = 14;
|
12362
|
+
const HOST_CPU_MODEL_NAME_MEMO_OFFSET = 18;
|
12363
|
+
const HOST_CPU_COUNT_MEMO_OFFSET = 58;
|
12364
|
+
const HOST_CPU_SPEED_MEMO_OFFSET = 60;
|
12365
|
+
const HOST_DESCRIPTION_MEMO_OFFSET = 62;
|
12366
|
+
const HOST_EMAIL_ADDRESS_MEMO_OFFSET = 88;
|
12367
|
+
const HOST_REG_MEMO_SIZE = 128;
|
12368
|
+
|
12369
|
+
const HOST_UPDATE_TOKEN_ID_MEMO_OFFSET = 0;
|
12370
|
+
const HOST_UPDATE_COUNTRY_CODE_MEMO_OFFSET = 32;
|
12371
|
+
const HOST_UPDATE_CPU_MICROSEC_MEMO_OFFSET = 34;
|
12372
|
+
const HOST_UPDATE_RAM_MB_MEMO_OFFSET = 38;
|
12373
|
+
const HOST_UPDATE_DISK_MB_MEMO_OFFSET = 42;
|
12374
|
+
const HOST_UPDATE_TOT_INS_COUNT_MEMO_OFFSET = 46;
|
12375
|
+
const HOST_UPDATE_ACT_INS_COUNT_MEMO_OFFSET = 50;
|
12376
|
+
const HOST_UPDATE_DESCRIPTION_MEMO_OFFSET = 54;
|
12377
|
+
const HOST_UPDATE_VERSION_MEMO_OFFSET = 80;
|
12378
|
+
const HOST_UPDATE_MEMO_SIZE = 83;
|
12379
|
+
|
12344
12380
|
class HostClient extends BaseEvernodeClient {
|
12345
12381
|
|
12346
12382
|
constructor(xrpAddress, xrpSecret, options = {}) {
|
@@ -12460,8 +12496,8 @@ class HostClient extends BaseEvernodeClient {
|
|
12460
12496
|
throw "description should consist of 0-26 ascii characters except ';'";
|
12461
12497
|
|
12462
12498
|
else if (!emailAddress || !(/[a-z0-9]+@[a-z]+.[a-z]{2,3}/.test(emailAddress)) || (emailAddress.length > 40))
|
12463
|
-
throw "Email address should be valid and can not have more than 40 characters.";
|
12464
|
-
|
12499
|
+
throw "Email address should be valid and can not have more than 40 characters.";
|
12500
|
+
|
12465
12501
|
if (await this.isRegistered())
|
12466
12502
|
throw "Host already registered.";
|
12467
12503
|
|
@@ -12501,12 +12537,24 @@ class HostClient extends BaseEvernodeClient {
|
|
12501
12537
|
console.log("No initiated transfers were found.");
|
12502
12538
|
}
|
12503
12539
|
|
12504
|
-
|
12540
|
+
// <country_code(2)><cpu_microsec(4)><ram_mb(4)><disk_mb(4)><no_of_total_instances(4)><cpu_model(40)><cpu_count(2)><cpu_speed(2)><description(26)><email_address(40)>
|
12541
|
+
const memoBuf = Buffer.alloc(HOST_REG_MEMO_SIZE, 0);
|
12542
|
+
Buffer.from(countryCode.substr(0, 2), "utf-8").copy(memoBuf, HOST_COUNTRY_CODE_MEMO_OFFSET);
|
12543
|
+
memoBuf.writeUInt32BE(cpuMicroSec, HOST_CPU_MICROSEC_MEMO_OFFSET);
|
12544
|
+
memoBuf.writeUInt32BE(ramMb, HOST_RAM_MB_MEMO_OFFSET);
|
12545
|
+
memoBuf.writeUInt32BE(diskMb, HOST_DISK_MB_MEMO_OFFSET);
|
12546
|
+
memoBuf.writeUInt32BE(totalInstanceCount, HOST_TOT_INS_COUNT_MEMO_OFFSET);
|
12547
|
+
Buffer.from(cpuModel.substr(0, 40), "utf-8").copy(memoBuf, HOST_CPU_MODEL_NAME_MEMO_OFFSET);
|
12548
|
+
memoBuf.writeUInt16BE(cpuCount, HOST_CPU_COUNT_MEMO_OFFSET);
|
12549
|
+
memoBuf.writeUInt16BE(cpuSpeed, HOST_CPU_SPEED_MEMO_OFFSET);
|
12550
|
+
Buffer.from(description.substr(0, 26), "utf-8").copy(memoBuf, HOST_DESCRIPTION_MEMO_OFFSET);
|
12551
|
+
Buffer.from(emailAddress.substr(0, 40), "utf-8").copy(memoBuf, HOST_EMAIL_ADDRESS_MEMO_OFFSET);
|
12552
|
+
|
12505
12553
|
const tx = await this.xrplAcc.makePayment(this.registryAddress,
|
12506
12554
|
(transferredNFTokenId) ? EvernodeConstants.NOW_IN_EVRS : this.config.hostRegFee.toString(),
|
12507
12555
|
EvernodeConstants.EVR,
|
12508
12556
|
this.config.evrIssuerAddress,
|
12509
|
-
[{ type: MemoTypes.HOST_REG, format: MemoFormats.
|
12557
|
+
[{ type: MemoTypes.HOST_REG, format: MemoFormats.HEX, data: memoBuf.toString('hex') }],
|
12510
12558
|
options.transactionOptions);
|
12511
12559
|
|
12512
12560
|
console.log('Waiting for the sell offer')
|
@@ -12551,11 +12599,18 @@ class HostClient extends BaseEvernodeClient {
|
|
12551
12599
|
throw "Host not registered."
|
12552
12600
|
|
12553
12601
|
const regNFT = await this.getRegistrationNft();
|
12602
|
+
|
12603
|
+
// To obtain registration NFT Page Keylet and index.
|
12604
|
+
const nftPageDataBuf = await EvernodeHelpers.getNFTPageAndLocation(regNFT.NFTokenID, this.xrplAcc, this.xrplApi);
|
12605
|
+
|
12554
12606
|
await this.xrplAcc.makePayment(this.registryAddress,
|
12555
12607
|
XrplConstants.MIN_XRP_AMOUNT,
|
12556
12608
|
XrplConstants.XRP,
|
12557
12609
|
null,
|
12558
|
-
[
|
12610
|
+
[
|
12611
|
+
{ type: MemoTypes.HOST_DEREG, format: MemoFormats.HEX, data: regNFT.NFTokenID },
|
12612
|
+
{ type: MemoTypes.HOST_REGISTRY_REF, format: MemoFormats.HEX, data: nftPageDataBuf.toString('hex') }
|
12613
|
+
],
|
12559
12614
|
options.transactionOptions);
|
12560
12615
|
|
12561
12616
|
console.log('Waiting for the buy offer')
|
@@ -12594,21 +12649,62 @@ class HostClient extends BaseEvernodeClient {
|
|
12594
12649
|
}
|
12595
12650
|
|
12596
12651
|
async updateRegInfo(activeInstanceCount = null, version = null, totalInstanceCount = null, tokenID = null, countryCode = null, cpuMicroSec = null, ramMb = null, diskMb = null, description = null, options = {}) {
|
12597
|
-
|
12652
|
+
// <token_id(32)><country_code(2)><cpu_microsec(4)><ram_mb(4)><disk_mb(4)><total_instance_count(4)><active_instances(4)><description(26)><version(3)>
|
12653
|
+
const memoBuf = Buffer.alloc(HOST_UPDATE_MEMO_SIZE, 0);
|
12654
|
+
if (tokenID)
|
12655
|
+
Buffer.from(tokenID.substr(0, 32), "hex").copy(memoBuf, HOST_UPDATE_TOKEN_ID_MEMO_OFFSET);
|
12656
|
+
if (countryCode)
|
12657
|
+
Buffer.from(countryCode.substr(0, 2), "utf-8").copy(memoBuf, HOST_UPDATE_COUNTRY_CODE_MEMO_OFFSET);
|
12658
|
+
if (cpuMicroSec)
|
12659
|
+
memoBuf.writeUInt32BE(cpuMicroSec, HOST_UPDATE_CPU_MICROSEC_MEMO_OFFSET);
|
12660
|
+
if (ramMb)
|
12661
|
+
memoBuf.writeUInt32BE(ramMb, HOST_UPDATE_RAM_MB_MEMO_OFFSET);
|
12662
|
+
if (diskMb)
|
12663
|
+
memoBuf.writeUInt32BE(diskMb, HOST_UPDATE_DISK_MB_MEMO_OFFSET);
|
12664
|
+
if (totalInstanceCount)
|
12665
|
+
memoBuf.writeUInt32BE(totalInstanceCount, HOST_UPDATE_TOT_INS_COUNT_MEMO_OFFSET);
|
12666
|
+
if (activeInstanceCount)
|
12667
|
+
memoBuf.writeUInt32BE(activeInstanceCount, HOST_UPDATE_ACT_INS_COUNT_MEMO_OFFSET);
|
12668
|
+
if (description)
|
12669
|
+
Buffer.from(description.substr(0, 26), "utf-8").copy(memoBuf, HOST_UPDATE_DESCRIPTION_MEMO_OFFSET);
|
12670
|
+
if (version) {
|
12671
|
+
const components = version.split('.').map(v => parseInt(v));
|
12672
|
+
if (components.length != 3)
|
12673
|
+
throw 'Invalid version format.';
|
12674
|
+
memoBuf.writeUInt8(components[0], HOST_UPDATE_VERSION_MEMO_OFFSET);
|
12675
|
+
memoBuf.writeUInt8(components[1], HOST_UPDATE_VERSION_MEMO_OFFSET + 1);
|
12676
|
+
memoBuf.writeUInt8(components[2], HOST_UPDATE_VERSION_MEMO_OFFSET + 2);
|
12677
|
+
}
|
12678
|
+
|
12679
|
+
// To obtain registration NFT Page Keylet and index.
|
12680
|
+
if (!tokenID)
|
12681
|
+
tokenID = (await this.getRegistrationNft()).NFTokenID;
|
12682
|
+
const nftPageDataBuf = await EvernodeHelpers.getNFTPageAndLocation(tokenID, this.xrplAcc, this.xrplApi);
|
12683
|
+
|
12598
12684
|
return await this.xrplAcc.makePayment(this.registryAddress,
|
12599
12685
|
XrplConstants.MIN_XRP_AMOUNT,
|
12600
12686
|
XrplConstants.XRP,
|
12601
12687
|
null,
|
12602
|
-
[
|
12688
|
+
[
|
12689
|
+
{ type: MemoTypes.HOST_UPDATE_INFO, format: MemoFormats.HEX, data: memoBuf.toString('hex') },
|
12690
|
+
{ type: MemoTypes.HOST_REGISTRY_REF, format: MemoFormats.HEX, data: nftPageDataBuf.toString('hex') }
|
12691
|
+
],
|
12603
12692
|
options.transactionOptions);
|
12604
12693
|
}
|
12605
12694
|
|
12606
12695
|
async heartbeat(options = {}) {
|
12696
|
+
// To obtain registration NFT Page Keylet and index.
|
12697
|
+
const regNFT = await this.getRegistrationNft();
|
12698
|
+
const nftPageDataBuf = await EvernodeHelpers.getNFTPageAndLocation(regNFT.NFTokenID, this.xrplAcc, this.xrplApi);
|
12699
|
+
|
12607
12700
|
return this.xrplAcc.makePayment(this.registryAddress,
|
12608
12701
|
XrplConstants.MIN_XRP_AMOUNT,
|
12609
12702
|
XrplConstants.XRP,
|
12610
12703
|
null,
|
12611
|
-
[
|
12704
|
+
[
|
12705
|
+
{ type: MemoTypes.HEARTBEAT, format: "", data: "" },
|
12706
|
+
{ type: MemoTypes.HOST_REGISTRY_REF, format: MemoFormats.HEX, data: nftPageDataBuf.toString('hex') }
|
12707
|
+
],
|
12612
12708
|
options.transactionOptions);
|
12613
12709
|
}
|
12614
12710
|
|
@@ -12692,11 +12788,19 @@ class HostClient extends BaseEvernodeClient {
|
|
12692
12788
|
}
|
12693
12789
|
|
12694
12790
|
async requestRebate(options = {}) {
|
12791
|
+
|
12792
|
+
// To obtain registration NFT Page Keylet and index.
|
12793
|
+
const regNFT = await this.getRegistrationNft();
|
12794
|
+
const nftPageDataBuf = await EvernodeHelpers.getNFTPageAndLocation(regNFT.NFTokenID, this.xrplAcc, this.xrplApi);
|
12795
|
+
|
12695
12796
|
return this.xrplAcc.makePayment(this.registryAddress,
|
12696
12797
|
XrplConstants.MIN_XRP_AMOUNT,
|
12697
12798
|
XrplConstants.XRP,
|
12698
12799
|
null,
|
12699
|
-
[
|
12800
|
+
[
|
12801
|
+
{ type: MemoTypes.HOST_REBATE, format: "", data: "" },
|
12802
|
+
{ type: MemoTypes.HOST_REGISTRY_REF, format: MemoFormats.HEX, data: nftPageDataBuf.toString('hex') }
|
12803
|
+
],
|
12700
12804
|
options.transactionOptions);
|
12701
12805
|
}
|
12702
12806
|
|
@@ -12727,16 +12831,21 @@ class HostClient extends BaseEvernodeClient {
|
|
12727
12831
|
}
|
12728
12832
|
}
|
12729
12833
|
|
12730
|
-
const regNFT = (await this.xrplAcc.getNfts()).find(n => n.URI.startsWith(EvernodeConstants.NFT_PREFIX_HEX) && n.Issuer === this.registryAddress);
|
12731
|
-
|
12732
12834
|
let memoData = Buffer.allocUnsafe(20);
|
12733
12835
|
codec.decodeAccountID(transfereeAddress).copy(memoData);
|
12734
12836
|
|
12837
|
+
// To obtain registration NFT Page Keylet and index.
|
12838
|
+
const regNFT = await this.getRegistrationNft();
|
12839
|
+
const nftPageDataBuf = await EvernodeHelpers.getNFTPageAndLocation(regNFT.NFTokenID, this.xrplAcc, this.xrplApi);
|
12840
|
+
|
12735
12841
|
await this.xrplAcc.makePayment(this.registryAddress,
|
12736
12842
|
XrplConstants.MIN_XRP_AMOUNT,
|
12737
12843
|
XrplConstants.XRP,
|
12738
12844
|
null,
|
12739
|
-
[
|
12845
|
+
[
|
12846
|
+
{ type: MemoTypes.HOST_TRANSFER, format: MemoFormats.HEX, data: memoData.toString('hex') },
|
12847
|
+
{ type: MemoTypes.HOST_REGISTRY_REF, format: MemoFormats.HEX, data: nftPageDataBuf.toString('hex') }
|
12848
|
+
],
|
12740
12849
|
options.transactionOptions);
|
12741
12850
|
|
12742
12851
|
let offer = null;
|
@@ -12768,6 +12877,19 @@ class HostClient extends BaseEvernodeClient {
|
|
12768
12877
|
|
12769
12878
|
await this.xrplAcc.sellNft(offer.index);
|
12770
12879
|
}
|
12880
|
+
|
12881
|
+
async hasPendingTransfer() {
|
12882
|
+
|
12883
|
+
// Check the availability of TRANSFEREE state for this host address.
|
12884
|
+
const stateTransfereeAddrKey = StateHelpers.generateTransfereeAddrStateKey(this.xrplAcc.address);
|
12885
|
+
const stateTransfereeAddrIndex = StateHelpers.getHookStateIndex(this.registryAddress, stateTransfereeAddrKey);
|
12886
|
+
const res = await this.xrplApi.getLedgerEntry(stateTransfereeAddrIndex);
|
12887
|
+
|
12888
|
+
if (res && res?.HookStateData)
|
12889
|
+
return true;
|
12890
|
+
|
12891
|
+
return false;
|
12892
|
+
}
|
12771
12893
|
}
|
12772
12894
|
|
12773
12895
|
module.exports = {
|
@@ -13594,7 +13716,8 @@ const MemoTypes = {
|
|
13594
13716
|
REFUND: 'evnRefund',
|
13595
13717
|
REFUND_REF: 'evnRefundRef',
|
13596
13718
|
DEAD_HOST_PRUNE: 'evnDeadHostPrune',
|
13597
|
-
HOST_REBATE: 'evnHostRebate'
|
13719
|
+
HOST_REBATE: 'evnHostRebate',
|
13720
|
+
HOST_REGISTRY_REF: 'evnHostRegistryRef'
|
13598
13721
|
}
|
13599
13722
|
|
13600
13723
|
const MemoFormats = {
|
@@ -13686,6 +13809,7 @@ module.exports = {
|
|
13686
13809
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
13687
13810
|
|
13688
13811
|
const { EvernodeConstants } = __nccwpck_require__(9849);
|
13812
|
+
const NFT_PAGE_LEDGER_ENTRY_TYPE_HEX = '0050';
|
13689
13813
|
|
13690
13814
|
class EvernodeHelpers {
|
13691
13815
|
static async getLeaseOffers(xrplAcc) {
|
@@ -13694,6 +13818,36 @@ class EvernodeHelpers {
|
|
13694
13818
|
const nftOffers = (await xrplAcc.getNftOffers())?.filter(offer => (offer.Flags == 1 && hostTokenIDs.includes(offer.NFTokenID))); // Filter only sell offers
|
13695
13819
|
return nftOffers;
|
13696
13820
|
}
|
13821
|
+
|
13822
|
+
static async getNFTPageAndLocation(nfTokenId, xrplAcc, xrplApi, buffer = true) {
|
13823
|
+
|
13824
|
+
const nftPageApprxKeylet = xrplAcc.generateKeylet('nftPage', { nfTokenId: nfTokenId });
|
13825
|
+
const nftPageMaxKeylet = xrplAcc.generateKeylet('nftPageMax');
|
13826
|
+
// Index is the last 32 bytes of the Keylet (Last 64 HEX characters).
|
13827
|
+
let page = await xrplApi.getLedgerEntry(nftPageMaxKeylet.substring(4, 68));
|
13828
|
+
while (page?.PreviousPageMin) {
|
13829
|
+
// Compare the low 96 bits. (Last 24 HEX characters).
|
13830
|
+
if (Number('0x' + page.index.substring(40, 64)) >= Number('0x' + nftPageApprxKeylet.substring(40, 64))) {
|
13831
|
+
// Check the existence of the NFToken
|
13832
|
+
let token = page.NFTokens.find(n => n.NFToken.NFTokenID == nfTokenId);
|
13833
|
+
if (!token) {
|
13834
|
+
page = await xrplApi.getLedgerEntry(page.PreviousPageMin);
|
13835
|
+
}
|
13836
|
+
else
|
13837
|
+
break;
|
13838
|
+
}
|
13839
|
+
}
|
13840
|
+
|
13841
|
+
const nftPageInfo = page.NFTokens.map((n, loc) => { return { NFTPage: NFT_PAGE_LEDGER_ENTRY_TYPE_HEX + page.index, NFTokenID: n.NFToken.NFTokenID, location: loc } }).find(n => n.NFTokenID == nfTokenId);
|
13842
|
+
if (buffer) {
|
13843
|
+
let locBuf = Buffer.allocUnsafe(2);
|
13844
|
+
locBuf.writeUInt16BE(nftPageInfo.location);
|
13845
|
+
// <NFT_PAGE_KEYLET(34 bytes)><LOCATION(2 bytes)>
|
13846
|
+
return Buffer.concat([Buffer.from(nftPageInfo.NFTPage, "hex"), locBuf]);
|
13847
|
+
}
|
13848
|
+
|
13849
|
+
return nftPageInfo;
|
13850
|
+
}
|
13697
13851
|
}
|
13698
13852
|
|
13699
13853
|
module.exports = {
|
@@ -14110,7 +14264,7 @@ const HOST_CPU_SPEED_OFFSET = 62;
|
|
14110
14264
|
const HOST_CPU_MICROSEC_OFFSET = 64;
|
14111
14265
|
const HOST_RAM_MB_OFFSET = 68;
|
14112
14266
|
const HOST_DISK_MB_OFFSET = 72;
|
14113
|
-
const
|
14267
|
+
const HOST_EMAIL_ADDRESS_OFFSET = 76;
|
14114
14268
|
|
14115
14269
|
const PREV_HOST_ADDRESS_OFFSET = 0;
|
14116
14270
|
const TRANSFER_LEDGER_IDX_OFFSET = 20;
|
@@ -14137,6 +14291,7 @@ const HOST_ADDR_KEY_ZERO_COUNT = 8;
|
|
14137
14291
|
const TRANSFEREE_ADDR_KEY_ZERO_COUNT = 8;
|
14138
14292
|
const HOOK_STATE_LEDGER_TYPE_PREFIX = 118; // Decimal value of ASCII 'v'
|
14139
14293
|
const PENDING_TRANSFER = 1;
|
14294
|
+
const HOST_EMAIL_ADDRESS_LEN = 40;
|
14140
14295
|
|
14141
14296
|
class StateHelpers {
|
14142
14297
|
static StateTypes = {
|
@@ -14187,7 +14342,9 @@ class StateHelpers {
|
|
14187
14342
|
cpuMicrosec: stateDataBuf.readUInt32BE(HOST_CPU_MICROSEC_OFFSET),
|
14188
14343
|
ramMb: stateDataBuf.readUInt32BE(HOST_RAM_MB_OFFSET),
|
14189
14344
|
diskMb: stateDataBuf.readUInt32BE(HOST_DISK_MB_OFFSET),
|
14190
|
-
email: (stateDataBuf.length >
|
14345
|
+
email: (stateDataBuf.length > HOST_EMAIL_ADDRESS_OFFSET ?
|
14346
|
+
stateDataBuf.slice(HOST_EMAIL_ADDRESS_OFFSET, HOST_EMAIL_ADDRESS_OFFSET + HOST_EMAIL_ADDRESS_LEN).toString().toString().replace(/\0/g, '') :
|
14347
|
+
"")
|
14191
14348
|
}
|
14192
14349
|
}
|
14193
14350
|
|
@@ -14738,18 +14895,27 @@ class XrplAccount {
|
|
14738
14895
|
#subscribed = false;
|
14739
14896
|
#txStreamHandler;
|
14740
14897
|
|
14741
|
-
constructor(address, secret = null, options = {}) {
|
14898
|
+
constructor(address = null, secret = null, options = {}) {
|
14899
|
+
if (!address && !secret)
|
14900
|
+
throw "Both address and secret cannot be empty";
|
14901
|
+
|
14902
|
+
this.address = address;
|
14903
|
+
this.secret = secret;
|
14742
14904
|
this.xrplApi = options.xrplApi || DefaultValues.xrplApi;
|
14743
14905
|
|
14744
14906
|
if (!this.xrplApi)
|
14745
14907
|
throw "XrplAccount: xrplApi not specified.";
|
14746
14908
|
|
14747
|
-
this.address
|
14748
|
-
|
14749
|
-
this.secret = secret;
|
14750
|
-
if (this.secret) {
|
14909
|
+
if (!this.address && this.secret) {
|
14751
14910
|
this.wallet = xrpl.Wallet.fromSeed(this.secret);
|
14752
|
-
this.address= this.wallet.classicAddress;
|
14911
|
+
this.address = this.wallet.classicAddress;
|
14912
|
+
} else if (this.secret) {
|
14913
|
+
const keypair = kp.deriveKeypair(this.secret);
|
14914
|
+
const derivedPubKeyAddress = kp.deriveAddress(keypair.publicKey);
|
14915
|
+
if (this.address == derivedPubKeyAddress)
|
14916
|
+
this.wallet = xrpl.Wallet.fromSeed(this.secret);
|
14917
|
+
else
|
14918
|
+
this.wallet = xrpl.Wallet.fromSeed(this.secret, { masterAddress: this.address });
|
14753
14919
|
}
|
14754
14920
|
|
14755
14921
|
this.#txStreamHandler = (eventName, tx, error) => {
|
@@ -14776,6 +14942,10 @@ class XrplAccount {
|
|
14776
14942
|
return kp.deriveKeypair(this.secret);
|
14777
14943
|
}
|
14778
14944
|
|
14945
|
+
async exists() {
|
14946
|
+
return await this.xrplApi.isAccountExists(this.address);
|
14947
|
+
}
|
14948
|
+
|
14779
14949
|
async getInfo() {
|
14780
14950
|
return await this.xrplApi.getAccountInfo(this.address);
|
14781
14951
|
}
|
@@ -14849,6 +15019,10 @@ class XrplAccount {
|
|
14849
15019
|
return await this.xrplApi.getAccountTrx(this.address, { ledger_index_min: minLedgerIndex, ledger_index_max: maxLedgerIndex, forward: isForward });
|
14850
15020
|
}
|
14851
15021
|
|
15022
|
+
async hasValidKeyPair() {
|
15023
|
+
return await this.xrplApi.isValidKeyForAddress(this.wallet.publicKey, this.address);
|
15024
|
+
}
|
15025
|
+
|
14852
15026
|
setAccountFields(fields, options = {}) {
|
14853
15027
|
/**
|
14854
15028
|
* Example for fields
|
@@ -15072,6 +15246,29 @@ class XrplAccount {
|
|
15072
15246
|
return this.#submitAndVerifyTransaction(owner ? { ...tx, Owner: owner } : tx, options);
|
15073
15247
|
}
|
15074
15248
|
|
15249
|
+
generateKeylet(type, data = {}) {
|
15250
|
+
switch (type) {
|
15251
|
+
case 'nftPage': {
|
15252
|
+
const accIdHex = (codec.decodeAccountID(this.address)).toString('hex').toUpperCase();
|
15253
|
+
const tokenPortion = data?.nfTokenId.substr(40, 64);
|
15254
|
+
return '0050' + accIdHex + tokenPortion;
|
15255
|
+
}
|
15256
|
+
|
15257
|
+
case 'nftPageMax': {
|
15258
|
+
const accIdHex = (codec.decodeAccountID(this.address)).toString('hex').toUpperCase();
|
15259
|
+
return '0050' + accIdHex + 'F'.repeat(24);
|
15260
|
+
}
|
15261
|
+
|
15262
|
+
case 'nftPageMin': {
|
15263
|
+
const accIdHex = (codec.decodeAccountID(this.address)).toString('hex').toUpperCase();
|
15264
|
+
return '0050' + accIdHex + '0'.repeat(24);
|
15265
|
+
}
|
15266
|
+
|
15267
|
+
default:
|
15268
|
+
return null;
|
15269
|
+
}
|
15270
|
+
}
|
15271
|
+
|
15075
15272
|
async subscribe() {
|
15076
15273
|
// Subscribe only once. Otherwise event handlers will be duplicated.
|
15077
15274
|
if (this.#subscribed)
|
@@ -15407,6 +15604,17 @@ class XrplApi {
|
|
15407
15604
|
return derivedPubKeyAddress === address || (regularKey && derivedPubKeyAddress === regularKey);
|
15408
15605
|
}
|
15409
15606
|
|
15607
|
+
async isAccountExists(address) {
|
15608
|
+
try {
|
15609
|
+
await this.#client.request({ command: 'account_info', account: address });
|
15610
|
+
return true;
|
15611
|
+
}
|
15612
|
+
catch (e) {
|
15613
|
+
if (e.data.error === 'actNotFound') return false;
|
15614
|
+
else throw e;
|
15615
|
+
}
|
15616
|
+
}
|
15617
|
+
|
15410
15618
|
async getAccountInfo(address) {
|
15411
15619
|
const resp = (await this.#client.request({ command: 'account_info', account: address }));
|
15412
15620
|
return resp?.result?.account_data;
|
@@ -15451,8 +15659,15 @@ class XrplApi {
|
|
15451
15659
|
}
|
15452
15660
|
|
15453
15661
|
async getLedgerEntry(index, options) {
|
15454
|
-
|
15455
|
-
|
15662
|
+
try {
|
15663
|
+
const resp = (await this.#client.request({ command: 'ledger_entry', index: index, ledger_index: "validated", ...options }));
|
15664
|
+
return resp?.result?.node;
|
15665
|
+
|
15666
|
+
} catch (e) {
|
15667
|
+
if (e?.data?.error === 'entryNotFound')
|
15668
|
+
return null;
|
15669
|
+
throw e;
|
15670
|
+
}
|
15456
15671
|
}
|
15457
15672
|
|
15458
15673
|
async submitAndVerify(tx, options) {
|