evernode-js-client 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- package/index.js +80 -3
- package/package.json +1 -1
package/index.js
CHANGED
@@ -12653,6 +12653,67 @@ class HostClient extends BaseEvernodeClient {
|
|
12653
12653
|
codec.decodeAccountID(this.xrplAcc.address).copy(buf, 4);
|
12654
12654
|
return buf.toString('hex');
|
12655
12655
|
}
|
12656
|
+
|
12657
|
+
async transfer(transfereeAddress = this.xrplAcc.address, options = {}) {
|
12658
|
+
if (!(await this.isRegistered()))
|
12659
|
+
throw "Host is not registered.";
|
12660
|
+
|
12661
|
+
const transfereeAcc = new XrplAccount(transfereeAddress, null, { xrplApi: this.xrplApi });
|
12662
|
+
|
12663
|
+
if (this.xrplAcc.address !== transfereeAddress) {
|
12664
|
+
// Find the new transferee also owns an Evernode Host Registration NFT.
|
12665
|
+
const nft = (await transfereeAcc.getNfts()).find(n => n.URI.startsWith(EvernodeConstants.NFT_PREFIX_HEX) && n.Issuer === this.registryAddress);
|
12666
|
+
if (nft) {
|
12667
|
+
// Check whether the token was actually issued from Evernode registry contract.
|
12668
|
+
const issuerHex = nft.NFTokenID.substr(8, 40);
|
12669
|
+
const issuerAddr = codec.encodeAccountID(Buffer.from(issuerHex, 'hex'));
|
12670
|
+
if (issuerAddr == this.registryAddress) {
|
12671
|
+
throw "The transferee is already registered in Evernode.";
|
12672
|
+
}
|
12673
|
+
}
|
12674
|
+
}
|
12675
|
+
|
12676
|
+
const regNFT = (await this.xrplAcc.getNfts()).find(n => n.URI.startsWith(EvernodeConstants.NFT_PREFIX_HEX) && n.Issuer === this.registryAddress);
|
12677
|
+
|
12678
|
+
let memoData = Buffer.allocUnsafe(20);
|
12679
|
+
codec.decodeAccountID(transfereeAddress).copy(memoData);
|
12680
|
+
|
12681
|
+
await this.xrplAcc.makePayment(this.registryAddress,
|
12682
|
+
XrplConstants.MIN_XRP_AMOUNT,
|
12683
|
+
XrplConstants.XRP,
|
12684
|
+
null,
|
12685
|
+
[{ type: MemoTypes.HOST_TRANSFER, format: MemoFormats.HEX, data: memoData.toString('hex') }],
|
12686
|
+
options.transactionOptions);
|
12687
|
+
|
12688
|
+
let offer = null;
|
12689
|
+
let attempts = 0;
|
12690
|
+
let offerLedgerIndex = 0;
|
12691
|
+
const regAcc = new XrplAccount(this.registryAddress, null, { xrplApi: this.xrplApi });
|
12692
|
+
|
12693
|
+
while (attempts < OFFER_WAIT_TIMEOUT) {
|
12694
|
+
offer = (await regAcc.getNftOffers()).find(o => (o.NFTokenID == regNFT.NFTokenID) && (o.Flags === 0));
|
12695
|
+
offerLedgerIndex = this.xrplApi.ledgerIndex;
|
12696
|
+
if (offer)
|
12697
|
+
break;
|
12698
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
12699
|
+
attempts++;
|
12700
|
+
}
|
12701
|
+
if (!offer)
|
12702
|
+
throw 'No buy offer found within timeout.';
|
12703
|
+
|
12704
|
+
console.log('Accepting the buy offer..');
|
12705
|
+
|
12706
|
+
// Wait until the next ledger after the offer is created.
|
12707
|
+
// Otherwise if the offer accepted in the same legder which it's been created,
|
12708
|
+
// We cannot fetch the offer from registry contract event handler since it's getting deleted immediately.
|
12709
|
+
await new Promise(async resolve => {
|
12710
|
+
while (this.xrplApi.ledgerIndex <= offerLedgerIndex)
|
12711
|
+
await new Promise(resolve2 => setTimeout(resolve2, 1000));
|
12712
|
+
resolve();
|
12713
|
+
});
|
12714
|
+
|
12715
|
+
await this.xrplAcc.sellNft(offer.index);
|
12716
|
+
}
|
12656
12717
|
}
|
12657
12718
|
|
12658
12719
|
module.exports = {
|
@@ -12677,6 +12738,7 @@ const RegistryEvents = {
|
|
12677
12738
|
Heartbeat: EvernodeEvents.Heartbeat,
|
12678
12739
|
HostPostDeregistered: EvernodeEvents.HostPostDeregistered,
|
12679
12740
|
DeadHostPrune: EvernodeEvents.DeadHostPrune,
|
12741
|
+
HostTransfer: EvernodeEvents.HostTransfer,
|
12680
12742
|
HostRebate: EvernodeEvents.HostRebate
|
12681
12743
|
}
|
12682
12744
|
|
@@ -13412,6 +13474,7 @@ const MemoTypes = {
|
|
13412
13474
|
HOST_UPDATE_INFO: 'evnHostUpdateReg',
|
13413
13475
|
HEARTBEAT: 'evnHeartbeat',
|
13414
13476
|
HOST_POST_DEREG: 'evnHostPostDereg',
|
13477
|
+
HOST_TRANSFER: 'evnTransfer',
|
13415
13478
|
EXTEND_LEASE: 'evnExtendLease',
|
13416
13479
|
EXTEND_SUCCESS: 'evnExtendSuccess',
|
13417
13480
|
EXTEND_ERROR: 'evnExtendError',
|
@@ -13472,12 +13535,14 @@ const HookStateKeys = {
|
|
13472
13535
|
// Prefixes
|
13473
13536
|
PREFIX_HOST_TOKENID: "45565202",
|
13474
13537
|
PREFIX_HOST_ADDR: "45565203",
|
13538
|
+
PREFIX_TRANSFEREE_ADDR: "45565204",
|
13475
13539
|
}
|
13476
13540
|
|
13477
13541
|
const EvernodeEvents = {
|
13478
13542
|
HostRegistered: "HostRegistered",
|
13479
13543
|
HostDeregistered: "HostDeregistered",
|
13480
13544
|
HostPostDeregistered: "HostPostDeregistered",
|
13545
|
+
HostTransfer: "HostTransfer",
|
13481
13546
|
AcquireLease: "AcquireLease",
|
13482
13547
|
AcquireSuccess: "AcquireSuccess",
|
13483
13548
|
AcquireError: "AcquireError",
|
@@ -13923,6 +13988,7 @@ const HOST_ACT_INS_COUNT_OFFSET = 88;
|
|
13923
13988
|
const HOST_HEARTBEAT_LEDGER_IDX_OFFSET = 92;
|
13924
13989
|
const HOST_VERSION_OFFSET = 100;
|
13925
13990
|
const HOST_REG_TIMESTAMP_OFFSET = 103;
|
13991
|
+
const HOST_TRANSFER_FLAG_OFFSET = 111;
|
13926
13992
|
|
13927
13993
|
const HOST_ADDRESS_OFFSET = 0;
|
13928
13994
|
const HOST_CPU_MODEL_NAME_OFFSET = 20;
|
@@ -13945,13 +14011,15 @@ const MOMENT_TYPES = {
|
|
13945
14011
|
const EVERNODE_PREFIX = 'EVR';
|
13946
14012
|
const HOST_ADDR_KEY_ZERO_COUNT = 8;
|
13947
14013
|
const HOOK_STATE_LEDGER_TYPE_PREFIX = 118; // Decimal value of ASCII 'v'
|
14014
|
+
const PENDING_TRANSFER = 1;
|
13948
14015
|
|
13949
14016
|
class StateHelpers {
|
13950
14017
|
static StateTypes = {
|
13951
14018
|
TOKEN_ID: 'tokenId',
|
13952
14019
|
HOST_ADDR: 'hostAddr',
|
13953
14020
|
SIGLETON: 'singleton',
|
13954
|
-
CONFIGURATION: 'configuration'
|
14021
|
+
CONFIGURATION: 'configuration',
|
14022
|
+
TRANSFEREE_ADDR: 'transfereeAddr'
|
13955
14023
|
}
|
13956
14024
|
|
13957
14025
|
static timeLines = {
|
@@ -13978,6 +14046,7 @@ class StateHelpers {
|
|
13978
14046
|
activeInstances: stateDataBuf.readUInt32BE(HOST_ACT_INS_COUNT_OFFSET),
|
13979
14047
|
lastHeartbeatIndex: Number(stateDataBuf.readBigUInt64BE(HOST_HEARTBEAT_LEDGER_IDX_OFFSET)),
|
13980
14048
|
version: `${stateDataBuf.readUInt8(HOST_VERSION_OFFSET)}.${stateDataBuf.readUInt8(HOST_VERSION_OFFSET + 1)}.${stateDataBuf.readUInt8(HOST_VERSION_OFFSET + 2)}`,
|
14049
|
+
hasPendingTransfer: (stateDataBuf.readUInt8(HOST_TRANSFER_FLAG_OFFSET) === PENDING_TRANSFER) ? true : false
|
13981
14050
|
}
|
13982
14051
|
if (stateDataBuf.length > HOST_REG_TIMESTAMP_OFFSET)
|
13983
14052
|
data.registrationTimestamp = Number(stateDataBuf.readBigUInt64BE(HOST_REG_TIMESTAMP_OFFSET));
|
@@ -14017,6 +14086,12 @@ class StateHelpers {
|
|
14017
14086
|
...this.decodeTokenIdState(stateData)
|
14018
14087
|
}
|
14019
14088
|
}
|
14089
|
+
else if (Buffer.from(HookStateKeys.PREFIX_TRANSFEREE_ADDR, 'hex').compare(stateKey, 0, 4) === 0) {
|
14090
|
+
return {
|
14091
|
+
type: this.StateTypes.TRANSFEREE_ADDR,
|
14092
|
+
key: hexKey
|
14093
|
+
}
|
14094
|
+
}
|
14020
14095
|
else if (Buffer.from(HookStateKeys.HOST_COUNT, 'hex').compare(stateKey) === 0) {
|
14021
14096
|
return {
|
14022
14097
|
type: this.StateTypes.SIGLETON,
|
@@ -14505,8 +14580,10 @@ class XrplAccount {
|
|
14505
14580
|
this.address = address;
|
14506
14581
|
|
14507
14582
|
this.secret = secret;
|
14508
|
-
if (this.secret)
|
14583
|
+
if (this.secret) {
|
14509
14584
|
this.wallet = xrpl.Wallet.fromSeed(this.secret);
|
14585
|
+
this.address= this.wallet.classicAddress;
|
14586
|
+
}
|
14510
14587
|
|
14511
14588
|
this.#txStreamHandler = (eventName, tx, error) => {
|
14512
14589
|
this.#events.emit(eventName, tx, error);
|
@@ -14602,7 +14679,7 @@ class XrplAccount {
|
|
14602
14679
|
}
|
14603
14680
|
|
14604
14681
|
async getAccountTrx(minLedgerIndex = -1, maxLedgerIndex = -1, isForward = true) {
|
14605
|
-
return await this.xrplApi.getAccountTrx(this.address, { ledger_index_min: minLedgerIndex, ledger_index_max: maxLedgerIndex, forward: isForward});
|
14682
|
+
return await this.xrplApi.getAccountTrx(this.address, { ledger_index_min: minLedgerIndex, ledger_index_max: maxLedgerIndex, forward: isForward });
|
14606
14683
|
}
|
14607
14684
|
|
14608
14685
|
setAccountFields(fields, options = {}) {
|