evernode-js-client 0.5.11 → 0.5.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,45 +0,0 @@
1
- class EventEmitter {
2
- constructor() {
3
- this.handlers = {};
4
- }
5
-
6
- on(event, handler) {
7
- if (!this.handlers[event])
8
- this.handlers[event] = [];
9
- this.handlers[event].push({
10
- once: false,
11
- func: handler
12
- });
13
- }
14
-
15
- once(event, handler) {
16
- if (!this.handlers[event])
17
- this.handlers[event] = [];
18
- this.handlers[event].push({
19
- once: true,
20
- func: handler
21
- });
22
- }
23
-
24
- off(event, handler = null) {
25
- if (this.handlers[event]) {
26
- if (handler)
27
- this.handlers[event] = this.handlers[event].filter(h => h !== handler);
28
- else
29
- delete this.handlers[event];
30
- }
31
- }
32
-
33
- emit(event, value, error = null) {
34
- if (this.handlers[event]) {
35
- this.handlers[event].forEach(handler => handler.func(value, error));
36
-
37
- // Rmove all handlers marked as 'once'.
38
- this.handlers[event] = this.handlers[event].filter(h => !h.once);
39
- }
40
- }
41
- }
42
-
43
- module.exports = {
44
- EventEmitter
45
- }
@@ -1,113 +0,0 @@
1
- const EvernodeConstants = {
2
- EVR: 'EVR',
3
- NFT_PREFIX_HEX: '657672686F7374', // evrhost
4
- LEASE_NFT_PREFIX_HEX: '6576726C65617365', // evrlease
5
- HOOK_NAMESPACE: '01EAF09326B4911554384121FF56FA8FECC215FDDE2EC35D9E59F2C53EC665A0',
6
- NOW_IN_EVRS: "0.00000001"
7
- }
8
-
9
- const MemoTypes = {
10
- ACQUIRE_LEASE: 'evnAcquireLease',
11
- ACQUIRE_SUCCESS: 'evnAcquireSuccess',
12
- ACQUIRE_ERROR: 'evnAcquireError',
13
- ACQUIRE_REF: 'evnAcquireRef',
14
- HOST_REG: 'evnHostReg',
15
- HOST_DEREG: 'evnHostDereg',
16
- HOST_UPDATE_INFO: 'evnHostUpdateReg',
17
- HEARTBEAT: 'evnHeartbeat',
18
- HOST_POST_DEREG: 'evnHostPostDereg',
19
- HOST_TRANSFER: 'evnTransfer',
20
- EXTEND_LEASE: 'evnExtendLease',
21
- EXTEND_SUCCESS: 'evnExtendSuccess',
22
- EXTEND_ERROR: 'evnExtendError',
23
- EXTEND_REF: 'evnExtendRef',
24
- REGISTRY_INIT: 'evnInitialize',
25
- REFUND: 'evnRefund',
26
- REFUND_REF: 'evnRefundRef',
27
- DEAD_HOST_PRUNE: 'evnDeadHostPrune',
28
- HOST_REBATE: 'evnHostRebate',
29
- HOST_REGISTRY_REF: 'evnHostRegistryRef'
30
- }
31
-
32
- const MemoFormats = {
33
- TEXT: 'text/plain',
34
- JSON: 'text/json',
35
- BASE64: 'base64',
36
- HEX: 'hex'
37
- }
38
-
39
- const ErrorCodes = {
40
- ACQUIRE_ERR: 'ACQUIRE_ERR',
41
- EXTEND_ERR: 'EXTEND_ERR'
42
- }
43
-
44
- const ErrorReasons = {
45
- TRANSACTION_FAILURE: 'TRANSACTION_FAILURE',
46
- NO_OFFER: 'NO_OFFER',
47
- NO_NFT: 'NO_NFT',
48
- INTERNAL_ERR: 'INTERNAL_ERR',
49
- TIMEOUT: 'TIMEOUT',
50
- HOST_INVALID: 'HOST_INVALID',
51
- HOST_INACTIVE: 'HOST_INACTIVE',
52
- NO_STATE_KEY: 'NO_STATE_KEY'
53
- }
54
-
55
- // All keys are prefixed with 'EVR' (0x455652)
56
- // Config keys sub-prefix: 0x01
57
- const HookStateKeys = {
58
- // Configuration.
59
- EVR_ISSUER_ADDR: "4556520100000000000000000000000000000000000000000000000000000001",
60
- FOUNDATION_ADDR: "4556520100000000000000000000000000000000000000000000000000000002",
61
- MOMENT_SIZE: "4556520100000000000000000000000000000000000000000000000000000003",
62
- MINT_LIMIT: "4556520100000000000000000000000000000000000000000000000000000004",
63
- FIXED_REG_FEE: "4556520100000000000000000000000000000000000000000000000000000005",
64
- HOST_HEARTBEAT_FREQ: "4556520100000000000000000000000000000000000000000000000000000006",
65
- PURCHASER_TARGET_PRICE: "4556520100000000000000000000000000000000000000000000000000000007",
66
- LEASE_ACQUIRE_WINDOW: "4556520100000000000000000000000000000000000000000000000000000008",
67
- REWARD_CONFIGURATION: "4556520100000000000000000000000000000000000000000000000000000009",
68
- MAX_TOLERABLE_DOWNTIME: "455652010000000000000000000000000000000000000000000000000000000A",
69
- MOMENT_TRANSIT_INFO: "455652010000000000000000000000000000000000000000000000000000000B",
70
- MAX_TRX_EMISSION_FEE: "455652010000000000000000000000000000000000000000000000000000000C",
71
-
72
-
73
- // Singleton
74
- HOST_COUNT: "4556523200000000000000000000000000000000000000000000000000000000",
75
- MOMENT_BASE_INFO: "4556523300000000000000000000000000000000000000000000000000000000",
76
- HOST_REG_FEE: "4556523400000000000000000000000000000000000000000000000000000000",
77
- MAX_REG: "4556523500000000000000000000000000000000000000000000000000000000",
78
- REWARD_INFO: "4556523600000000000000000000000000000000000000000000000000000000",
79
-
80
- // Prefixes
81
- PREFIX_HOST_TOKENID: "45565202",
82
- PREFIX_HOST_ADDR: "45565203",
83
- PREFIX_TRANSFEREE_ADDR: "45565204",
84
- }
85
-
86
- const EvernodeEvents = {
87
- HostRegistered: "HostRegistered",
88
- HostDeregistered: "HostDeregistered",
89
- HostPostDeregistered: "HostPostDeregistered",
90
- HostTransfer: "HostTransfer",
91
- AcquireLease: "AcquireLease",
92
- AcquireSuccess: "AcquireSuccess",
93
- AcquireError: "AcquireError",
94
- Heartbeat: "Heartbeat",
95
- ExtendLease: "ExtendLease",
96
- ExtendSuccess: "ExtendSuccess",
97
- ExtendError: "ExtendError",
98
- HostRegUpdated: "HostRegUpdated",
99
- HostReRegistered: "HostReRegistered",
100
- RegistryInitialized: "RegistryInitialized",
101
- DeadHostPrune: "DeadHostPrune",
102
- HostRebate: "HostRebate"
103
- }
104
-
105
- module.exports = {
106
- EvernodeConstants,
107
- MemoTypes,
108
- MemoFormats,
109
- ErrorCodes,
110
- ErrorReasons,
111
- HookStateKeys,
112
- EvernodeEvents
113
- }
@@ -1,45 +0,0 @@
1
- const { EvernodeConstants } = require('./evernode-common');
2
- const NFT_PAGE_LEDGER_ENTRY_TYPE_HEX = '0050';
3
-
4
- class EvernodeHelpers {
5
- static async getLeaseOffers(xrplAcc) {
6
- const hostNfts = (await xrplAcc.getNfts()).filter(nft => nft.URI.startsWith(EvernodeConstants.LEASE_NFT_PREFIX_HEX));
7
- const hostTokenIDs = hostNfts.map(nft => nft.NFTokenID);
8
- const nftOffers = (await xrplAcc.getNftOffers())?.filter(offer => (offer.Flags == 1 && hostTokenIDs.includes(offer.NFTokenID))); // Filter only sell offers
9
- return nftOffers;
10
- }
11
-
12
- static async getNFTPageAndLocation(nfTokenId, xrplAcc, xrplApi, buffer = true) {
13
-
14
- const nftPageApprxKeylet = xrplAcc.generateKeylet('nftPage', { nfTokenId: nfTokenId });
15
- const nftPageMaxKeylet = xrplAcc.generateKeylet('nftPageMax');
16
- // Index is the last 32 bytes of the Keylet (Last 64 HEX characters).
17
- let page = await xrplApi.getLedgerEntry(nftPageMaxKeylet.substring(4, 68));
18
- while (page?.PreviousPageMin) {
19
- // Compare the low 96 bits. (Last 24 HEX characters).
20
- if (Number('0x' + page.index.substring(40, 64)) >= Number('0x' + nftPageApprxKeylet.substring(40, 64))) {
21
- // Check the existence of the NFToken
22
- let token = page.NFTokens.find(n => n.NFToken.NFTokenID == nfTokenId);
23
- if (!token) {
24
- page = await xrplApi.getLedgerEntry(page.PreviousPageMin);
25
- }
26
- else
27
- break;
28
- }
29
- }
30
-
31
- 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);
32
- if (buffer) {
33
- let locBuf = Buffer.allocUnsafe(2);
34
- locBuf.writeUInt16BE(nftPageInfo.location);
35
- // <NFT_PAGE_KEYLET(34 bytes)><LOCATION(2 bytes)>
36
- return Buffer.concat([Buffer.from(nftPageInfo.NFTPage, "hex"), locBuf]);
37
- }
38
-
39
- return nftPageInfo;
40
- }
41
- }
42
-
43
- module.exports = {
44
- EvernodeHelpers
45
- }
@@ -1,309 +0,0 @@
1
- const https = require('https');
2
- const { DefaultValues } = require('../defaults');
3
-
4
- const FirestoreOperations = {
5
- EQUAL: 'EQUAL',
6
- AND: 'AND'
7
- }
8
-
9
- class FirestoreHandler {
10
- #projectId = null;
11
- #collectionPrefix = null;
12
-
13
- constructor(options = {}) {
14
- this.#projectId = options.stateIndexId || DefaultValues.stateIndexId;
15
- this.#collectionPrefix = options.collectionPrefix || DefaultValues.registryAddress;
16
- }
17
-
18
- /**
19
- * Convert given document value object to real format and snake_case key to camelCase.
20
- * @param key Name of the property.
21
- * @param value Value to be parsed.
22
- * @returns Parsed key and value.
23
- */
24
- #parseValue(key, value) {
25
- // Convert snake_case to camelCase.
26
- const ccKey = key.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); });
27
- const type = Object.keys(value)[0];
28
- let parsed;
29
- switch (type) {
30
- case 'integerValue':
31
- parsed = parseInt(value[type]);
32
- break;
33
- case 'floatValue':
34
- parsed = parseFloat(value[type]);
35
- break;
36
- case 'mapValue':
37
- parsed = {};
38
- for (const [subKey, subValue] of Object.entries(value[type].fields)) {
39
- const field = this.#parseValue(subKey, subValue);
40
- parsed[field.key] = field.value;
41
- }
42
- break;
43
- default:
44
- parsed = value[type];
45
- break;
46
- }
47
- return { key: ccKey, value: parsed };
48
- }
49
-
50
- /**
51
- * Get values filtered according to the given body.
52
- * @param body Body to parsed in to the query reqest.
53
- * @returns Result set.
54
- */
55
- async #runQuery(body) {
56
- const url = this.buildApiPath(null, null, true);
57
- return await this.sendRequest('POST', url, null, body);
58
- }
59
-
60
- /**
61
- * Get documents from a collection.
62
- * @param collectionId Name of the collection.
63
- * @param pageSize Optianal page size if result set needed to be paginated
64
- * @param nextPageToken Next page token of a paginated result set.
65
- * @returns Result set.
66
- */
67
- async #read(collectionId, pageSize = null, nextPageToken = null) {
68
- if (!collectionId)
69
- throw { type: 'Validation Error', message: 'collectionId is required' };
70
-
71
- const url = this.buildApiPath(collectionId);
72
- let params = (pageSize || nextPageToken) ? {} : null;
73
- if (pageSize)
74
- params = { pageSize: pageSize };
75
- if (nextPageToken)
76
- params = { pageToken: nextPageToken, ...params };
77
-
78
- return await this.sendRequest('GET', url, params);
79
- }
80
-
81
- /**
82
- * Get documents from a collection with filtering support.
83
- * @param collectionId Name of the collection.
84
- * @param filter Optional filters to filter documents.
85
- * @param pageSize Optianal page size if result set needed to be paginated
86
- * @param nextPageToken Next page token of a paginated result set.
87
- * @returns Parsed readable result set.
88
- */
89
- async #getDocuments(collectionId, filters = null, pageSize = null, nextPageToken = null) {
90
- if (filters && (pageSize || nextPageToken))
91
- throw { type: 'Validation Error', message: 'Pagination isn\'t supported with filter.' };
92
-
93
- let data;
94
- // If there are filters send requst in query mode.
95
- if (filters) {
96
- // Prepare the query body from given filters.
97
- let where = {
98
- compositeFilter: {
99
- filters: Object.entries(filters).map(([key, value]) => {
100
- const field = this.convertValue(key, value);
101
- return {
102
- fieldFilter: {
103
- field: { fieldPath: field.key },
104
- op: FirestoreOperations.EQUAL,
105
- value: field.value
106
- }
107
- }
108
- }),
109
- op: filters.operator ? filters.operator : FirestoreOperations.AND
110
- }
111
- };
112
- for (const [key, value] of Object.entries(filters)) {
113
- const field = this.convertValue(key, value);
114
- let fieldFilter = {
115
- field: { fieldPath: field.key },
116
- op: FirestoreOperations.EQUAL,
117
- value: field.value
118
- }
119
- where.compositeFilter.filters.push({ fieldFilter: fieldFilter });
120
- }
121
-
122
- let body = {
123
- structuredQuery: {
124
- where: where,
125
- from: [{ collectionId: collectionId }]
126
- }
127
- };
128
- data = await this.#runQuery(body);
129
- data = data ? JSON.parse(data) : [];
130
- if (data && data.length && data[0].document) {
131
- return data.map(d => {
132
- return this.parseDocument(d.document);
133
- });
134
- }
135
- }
136
- else {
137
- data = await this.#read(collectionId, pageSize, nextPageToken);
138
- data = data ? JSON.parse(data) : {};
139
- if (data.documents && data.documents.length) {
140
- const list = data.documents.map(d => {
141
- return this.parseDocument(d);
142
- });
143
- return data.nextPageToken ? {
144
- data: list,
145
- nextPageToken: data.nextPageToken
146
- } : list;
147
- }
148
- }
149
-
150
- return [];
151
- }
152
-
153
- getCollectionId(collection) {
154
- // Document if is generated with given prefix.
155
- return `${this.#collectionPrefix}_${collection}`;
156
- }
157
-
158
- /**
159
- * Send http requst.
160
- * @param httpMethod GET/POST/PATCH/DELETE
161
- * @param url Url for the request.
162
- * @param params Optional query params.
163
- * @param data Optional request body.
164
- * @param options Optional options.
165
- * @returns Result set.
166
- */
167
- async sendRequest(httpMethod, url, params = null, data = null, options = null) {
168
- const urlObj = new URL(url);
169
- // Populate uri params to the URL object.
170
- if (params) {
171
- for (const [key, value] of Object.entries(params)) {
172
- if (value) {
173
- // If value is a array, populate it with same name.
174
- if (typeof value === 'object') {
175
- for (const val of value) {
176
- if (val)
177
- urlObj.searchParams.append(key, val);
178
- }
179
- }
180
- else
181
- urlObj.searchParams.set(key, value);
182
- }
183
- }
184
- }
185
-
186
- let reqOptions = {
187
- method: httpMethod,
188
- protocol: urlObj.protocol,
189
- hostname: urlObj.hostname,
190
- port: urlObj.port,
191
- path: `${urlObj.pathname}?${urlObj.searchParams.toString()}`,
192
- ...(options ? options : {})
193
- };
194
-
195
- return new Promise(async (resolve, reject) => {
196
- // Send request and collect data chuncks to a buffer. Then return the result set on end event.
197
- // Resolve only if the status is 200.
198
- const req = https.request(reqOptions, (res) => {
199
- let resData = '';
200
- res.on('data', (d) => {
201
- resData += d;
202
- });
203
- res.on('end', async () => {
204
- if (res.statusCode === 200) {
205
- resolve(resData);
206
- return;
207
- }
208
- reject({ status: res.statusCode, data: resData });
209
- return;
210
- });
211
- }).on('error', async (e) => {
212
- reject(e);
213
- return;
214
- });
215
-
216
- if (data)
217
- req.write(typeof data === 'object' ? JSON.stringify(data) : data);
218
-
219
- req.end();
220
- });
221
- }
222
-
223
- /**
224
- * Generate url for firestore.
225
- * @param collectionId Optional collection name.
226
- * @param documentId Optional document name.
227
- * @param isQuery Whether a query request or not.
228
- * @returns The generated url.
229
- */
230
- buildApiPath(collectionId = null, documentId = null, isQuery = false) {
231
- let path = `https://firestore.googleapis.com/v1/projects/${this.#projectId}/databases/(default)/documents`;
232
- if (collectionId)
233
- path += `/${collectionId.toString()}`;
234
- if (documentId)
235
- path += `/${documentId.toString()}`;
236
- if (isQuery)
237
- path += ':runQuery';
238
- return path;
239
- }
240
-
241
- /**
242
- * Generate firestore document value object from given key and value, Convert camelCase key to snake_case.
243
- * @param key Name of the value.
244
- * @param value Value to be parsed.
245
- * @returns Generated firestore document object.
246
- */
247
- convertValue(key, value) {
248
- // Convert camelCase to snake_case.
249
- const uKey = key.replace(/([A-Z])/g, function (g) { return `_${g[0].toLocaleLowerCase()}`; });
250
- let val = {};
251
- let type
252
- switch (typeof value) {
253
- case 'number':
254
- type = (value % 1 > 0 ? 'float' : 'integer');
255
- val = value;
256
- break;
257
- case 'object':
258
- type = 'map';
259
- val = {
260
- fields: {}
261
- }
262
- // Prepare the firestore write body with the given data object.
263
- for (const [subKey, subValue] of Object.entries(value)) {
264
- const field = this.convertValue(subKey, subValue);
265
- val.fields[field.key] = field.value;
266
- }
267
- break;
268
- default:
269
- type = 'string';
270
- val = value;
271
- break;
272
- }
273
- type = `${type}Value`;
274
- let obj = {};
275
- obj[type] = val;
276
- return { key: uKey, value: obj };
277
- }
278
-
279
- /**
280
- * Convert the firestore document to human readable simplified json object.
281
- * @param document Firestore document.
282
- * @returns Simplified json object for the document.
283
- */
284
- parseDocument(document) {
285
- let item = {
286
- id: document.name.split('/').pop(),
287
- createTime: new Date(document.createTime),
288
- updateTime: new Date(document.updateTime)
289
- };
290
- for (const [key, value] of Object.entries(document.fields)) {
291
- const field = this.#parseValue(key, value);
292
- item[field.key] = field.value;
293
- }
294
- return item;
295
- }
296
-
297
- async getHosts(filters = null, pageSize = null, nextPageToken = null) {
298
- return await this.#getDocuments(this.getCollectionId('hosts'), filters, pageSize, nextPageToken);
299
- }
300
-
301
- async getConfigs(filters = null, pageSize = null, nextPageToken = null) {
302
- return await this.#getDocuments(this.getCollectionId('configs'), filters, pageSize, nextPageToken);
303
- }
304
- }
305
-
306
- module.exports = {
307
- FirestoreHandler,
308
- FirestoreOperations
309
- }
package/src/index.js DELETED
@@ -1,37 +0,0 @@
1
- const { Defaults } = require('./defaults');
2
- const { RegistryClient, RegistryEvents } = require("./clients/registry-client");
3
- const { TenantClient, TenantEvents } = require("./clients/tenant-client");
4
- const { HostClient, HostEvents } = require("./clients/host-client");
5
- const { XrplApi } = require('./xrpl-api');
6
- const { XrplApiEvents, XrplConstants } = require('./xrpl-common');
7
- const { XrplAccount } = require('./xrpl-account');
8
- const { EvernodeConstants, HookStateKeys, MemoTypes } = require('./evernode-common');
9
- const { XflHelpers } = require('./xfl-helpers');
10
- const { FirestoreHandler } = require('./firestore/firestore-handler');
11
- const { StateHelpers } = require('./state-helpers');
12
- const { UtilHelpers } = require('./util-helpers');
13
- const { TransactionHelper } = require('./transaction-helper');
14
- const { EncryptionHelper } = require('./encryption-helper');
15
-
16
- module.exports = {
17
- RegistryClient,
18
- RegistryEvents,
19
- TenantClient,
20
- TenantEvents,
21
- HostClient,
22
- HostEvents,
23
- XrplApi,
24
- XrplApiEvents,
25
- XrplConstants,
26
- XrplAccount,
27
- EvernodeConstants,
28
- Defaults,
29
- XflHelpers,
30
- StateHelpers,
31
- FirestoreHandler,
32
- UtilHelpers,
33
- TransactionHelper,
34
- EncryptionHelper,
35
- HookStateKeys,
36
- MemoTypes
37
- }