evernode-js-client 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- }
@@ -1,283 +0,0 @@
1
- const codec = require('ripple-address-codec');
2
- const { Buffer } = require('buffer');
3
- const { HookStateKeys, EvernodeConstants } = require('./evernode-common');
4
- const { XflHelpers } = require('./xfl-helpers');
5
- const crypto = require("crypto");
6
-
7
- const NFTOKEN_PREFIX = '00000000';
8
-
9
- const EPOCH_OFFSET = 0;
10
- const SAVED_MOMENT_OFFSET = 1;
11
- const PREV_MOMENT_ACTIVE_HOST_COUNT_OFFSET = 5;
12
- const CUR_MOMENT_ACTIVE_HOST_COUNT_OFFSET = 9;
13
- const EPOCH_POOL_OFFSET = 13;
14
-
15
- const EPOCH_COUNT_OFFSET = 0;
16
- const FIRST_EPOCH_REWARD_QUOTA_OFFSET = 1;
17
- const EPOCH_REWARD_AMOUNT_OFFSET = 5;
18
- const REWARD_START_MOMENT_OFFSET = 9;
19
-
20
- const HOST_TOKEN_ID_OFFSET = 0;
21
- const HOST_COUNTRY_CODE_OFFSET = 32;
22
- const HOST_RESERVED_OFFSET = 34;
23
- const HOST_DESCRIPTION_OFFSET = 42;
24
- const HOST_REG_LEDGER_OFFSET = 68;
25
- const HOST_REG_FEE_OFFSET = 76;
26
- const HOST_TOT_INS_COUNT_OFFSET = 84;
27
- const HOST_ACT_INS_COUNT_OFFSET = 88;
28
- const HOST_HEARTBEAT_LEDGER_IDX_OFFSET = 92;
29
- const HOST_VERSION_OFFSET = 100;
30
-
31
- const HOST_ADDRESS_OFFSET = 0;
32
- const HOST_CPU_MODEL_NAME_OFFSET = 20;
33
- const HOST_CPU_COUNT_OFFSET = 60;
34
- const HOST_CPU_SPEED_OFFSET = 62;
35
- const HOST_CPU_MICROSEC_OFFSET = 64;
36
- const HOST_RAM_MB_OFFSET = 68;
37
- const HOST_DISK_MB_OFFSET = 72;
38
-
39
- const STATE_KEY_TYPES = {
40
- TOKEN_ID: 2,
41
- HOST_ADDR: 3
42
- }
43
-
44
- const EVERNODE_PREFIX = 'EVR';
45
- const HOST_ADDR_KEY_ZERO_COUNT = 8;
46
- const HOOK_STATE_LEDGER_TYPE_PREFIX = 118; // Decimal value of ASCII 'v'
47
-
48
- class StateHelpers {
49
- static StateTypes = {
50
- TOKEN_ID: 'tokenId',
51
- HOST_ADDR: 'hostAddr',
52
- SIGLETON: 'singleton',
53
- CONFIGURATION: 'configuration'
54
- }
55
-
56
- static decodeHostAddressState(stateKeyBuf, stateDataBuf) {
57
- return {
58
- address: codec.encodeAccountID(stateKeyBuf.slice(12)),
59
- nfTokenId: stateDataBuf.slice(HOST_TOKEN_ID_OFFSET, HOST_COUNTRY_CODE_OFFSET).toString('hex').toUpperCase(),
60
- countryCode: stateDataBuf.slice(HOST_COUNTRY_CODE_OFFSET, HOST_RESERVED_OFFSET).toString(),
61
- description: stateDataBuf.slice(HOST_DESCRIPTION_OFFSET, HOST_REG_LEDGER_OFFSET).toString().replace(/\0/g, ''),
62
- registrationLedger: Number(stateDataBuf.readBigUInt64BE(HOST_REG_LEDGER_OFFSET)),
63
- registrationFee: Number(stateDataBuf.readBigUInt64BE(HOST_REG_FEE_OFFSET)),
64
- maxInstances: stateDataBuf.readUInt32BE(HOST_TOT_INS_COUNT_OFFSET),
65
- activeInstances: stateDataBuf.readUInt32BE(HOST_ACT_INS_COUNT_OFFSET),
66
- lastHeartbeatLedger: Number(stateDataBuf.readBigUInt64BE(HOST_HEARTBEAT_LEDGER_IDX_OFFSET)),
67
- version: `${stateDataBuf.readUInt8(HOST_VERSION_OFFSET)}.${stateDataBuf.readUInt8(HOST_VERSION_OFFSET + 1)}.${stateDataBuf.readUInt8(HOST_VERSION_OFFSET + 2)}`
68
- }
69
- }
70
-
71
- static decodeTokenIdState(stateDataBuf) {
72
- return {
73
- address: codec.encodeAccountID(stateDataBuf.slice(HOST_ADDRESS_OFFSET, HOST_CPU_MODEL_NAME_OFFSET)),
74
- cpuModelName: stateDataBuf.slice(HOST_CPU_MODEL_NAME_OFFSET, HOST_CPU_COUNT_OFFSET).toString().replace(/\x00+$/, ''), // Remove trailing \x00 characters.
75
- cpuCount: stateDataBuf.readUInt16BE(HOST_CPU_COUNT_OFFSET),
76
- cpuMHz: stateDataBuf.readUInt16BE(HOST_CPU_SPEED_OFFSET),
77
- cpuMicrosec: stateDataBuf.readUInt32BE(HOST_CPU_MICROSEC_OFFSET),
78
- ramMb: stateDataBuf.readUInt32BE(HOST_RAM_MB_OFFSET),
79
- diskMb: stateDataBuf.readUInt32BE(HOST_DISK_MB_OFFSET)
80
- }
81
- }
82
-
83
- static decodeStateData(stateKey, stateData) {
84
- const hexKey = stateKey.toString('hex').toUpperCase();
85
- if (Buffer.from(HookStateKeys.PREFIX_HOST_ADDR, 'hex').compare(stateKey, 0, 4) === 0) {
86
- return {
87
- type: this.StateTypes.HOST_ADDR,
88
- key: hexKey,
89
- ...this.decodeHostAddressState(stateKey, stateData)
90
- }
91
- }
92
- else if (Buffer.from(HookStateKeys.PREFIX_HOST_TOKENID, 'hex').compare(stateKey, 0, 4) === 0) {
93
- // Generate the address state key.
94
- const addressKeyBuf = Buffer.alloc(32, 0);
95
- Buffer.from(HookStateKeys.PREFIX_HOST_ADDR, 'hex').copy(addressKeyBuf);
96
- stateData.copy(addressKeyBuf, 12, HOST_ADDRESS_OFFSET, HOST_CPU_MODEL_NAME_OFFSET)
97
- return {
98
- type: this.StateTypes.TOKEN_ID,
99
- key: hexKey,
100
- addressKey: addressKeyBuf.toString('hex').toUpperCase(),
101
- ...this.decodeTokenIdState(stateData)
102
- }
103
- }
104
- else if (Buffer.from(HookStateKeys.HOST_COUNT, 'hex').compare(stateKey) === 0) {
105
- return {
106
- type: this.StateTypes.SIGLETON,
107
- key: hexKey,
108
- value: stateData.readUInt32BE()
109
- }
110
- }
111
- else if (Buffer.from(HookStateKeys.MOMENT_BASE_IDX, 'hex').compare(stateKey) === 0) {
112
- return {
113
- type: this.StateTypes.SIGLETON,
114
- key: hexKey,
115
- value: Number(stateData.readBigInt64BE())
116
- }
117
- }
118
- else if (Buffer.from(HookStateKeys.HOST_REG_FEE, 'hex').compare(stateKey) === 0 || Buffer.from(HookStateKeys.MAX_REG, 'hex').compare(stateKey) === 0) {
119
- return {
120
- type: this.StateTypes.SIGLETON,
121
- key: hexKey,
122
- value: Number(stateData.readBigUInt64BE())
123
- }
124
- }
125
- else if (Buffer.from(HookStateKeys.EVR_ISSUER_ADDR, 'hex').compare(stateKey) === 0 || Buffer.from(HookStateKeys.FOUNDATION_ADDR, 'hex').compare(stateKey) === 0) {
126
- return {
127
- type: this.StateTypes.CONFIGURATION,
128
- key: hexKey,
129
- value: codec.encodeAccountID(stateData)
130
- }
131
- }
132
- else if (Buffer.from(HookStateKeys.MOMENT_SIZE, 'hex').compare(stateKey) === 0 ||
133
- Buffer.from(HookStateKeys.HOST_HEARTBEAT_FREQ, 'hex').compare(stateKey) === 0 ||
134
- Buffer.from(HookStateKeys.LEASE_ACQUIRE_WINDOW, 'hex').compare(stateKey) === 0) {
135
- return {
136
- type: this.StateTypes.CONFIGURATION,
137
- key: hexKey,
138
- value: stateData.readUInt16BE()
139
- }
140
- }
141
- else if (Buffer.from(HookStateKeys.MINT_LIMIT, 'hex').compare(stateKey) === 0 || Buffer.from(HookStateKeys.FIXED_REG_FEE, 'hex').compare(stateKey) === 0) {
142
- return {
143
- type: this.StateTypes.CONFIGURATION,
144
- key: hexKey,
145
- value: Number(stateData.readBigUInt64BE())
146
- }
147
- }
148
- else if (Buffer.from(HookStateKeys.PURCHASER_TARGET_PRICE, 'hex').compare(stateKey) === 0) {
149
- const xfl = stateData.readBigInt64BE(0);
150
- const val = XflHelpers.toString(xfl);
151
- return {
152
- type: this.StateTypes.CONFIGURATION,
153
- key: hexKey,
154
- value: val
155
- }
156
- }
157
- else if (Buffer.from(HookStateKeys.REWARD_CONFIGURATION, 'hex').compare(stateKey) === 0) {
158
- return {
159
- type: this.StateTypes.CONFIGURATION,
160
- key: hexKey,
161
- value: {
162
- epochCount: stateData.readUInt8(EPOCH_COUNT_OFFSET),
163
- firstEpochRewardQuota: stateData.readUInt32BE(FIRST_EPOCH_REWARD_QUOTA_OFFSET),
164
- epochRewardAmount: stateData.readUInt32BE(EPOCH_REWARD_AMOUNT_OFFSET),
165
- rewardStartMoment: stateData.readUInt32BE(REWARD_START_MOMENT_OFFSET)
166
- }
167
- }
168
- }
169
- else if (Buffer.from(HookStateKeys.REWARD_INFO, 'hex').compare(stateKey) === 0) {
170
- return {
171
- type: this.StateTypes.SIGLETON,
172
- key: hexKey,
173
- value: {
174
- epoch: stateData.readUInt8(EPOCH_OFFSET),
175
- savedMoment: stateData.readUInt32BE(SAVED_MOMENT_OFFSET),
176
- prevMomentActiveHostCount: stateData.readUInt32BE(PREV_MOMENT_ACTIVE_HOST_COUNT_OFFSET),
177
- curMomentActiveHostCount: stateData.readUInt32BE(CUR_MOMENT_ACTIVE_HOST_COUNT_OFFSET),
178
- epochPool: XflHelpers.toString(stateData.readBigInt64BE(EPOCH_POOL_OFFSET))
179
- }
180
- }
181
- }
182
- else if (Buffer.from(HookStateKeys.MAX_TOLERABLE_DOWNTIME, 'hex').compare(stateKey) === 0) {
183
- return {
184
- type: this.StateTypes.CONFIGURATION,
185
- key: hexKey,
186
- value: stateData.readUInt16BE()
187
- }
188
- }
189
- else
190
- throw { type: 'Validation Error', message: 'Invalid state key.' };
191
- }
192
-
193
- static decodeStateKey(stateKey) {
194
- const hexKey = stateKey.toString('hex').toUpperCase();
195
- if (Buffer.from(HookStateKeys.PREFIX_HOST_ADDR, 'hex').compare(stateKey, 0, 4) === 0) {
196
- return {
197
- key: hexKey,
198
- type: this.StateTypes.HOST_ADDR
199
- };
200
- }
201
- else if (Buffer.from(HookStateKeys.PREFIX_HOST_TOKENID, 'hex').compare(stateKey, 0, 4) === 0) {
202
- return {
203
- key: hexKey,
204
- type: this.StateTypes.TOKEN_ID
205
- };
206
- }
207
- else if (Buffer.from(HookStateKeys.HOST_COUNT, 'hex').compare(stateKey) === 0 ||
208
- Buffer.from(HookStateKeys.MOMENT_BASE_IDX, 'hex').compare(stateKey) === 0 ||
209
- Buffer.from(HookStateKeys.HOST_REG_FEE, 'hex').compare(stateKey) === 0 ||
210
- Buffer.from(HookStateKeys.MAX_REG, 'hex').compare(stateKey) === 0 ||
211
- Buffer.from(HookStateKeys.REWARD_INFO, 'hex').compare(stateKey) === 0) {
212
- return {
213
- key: hexKey,
214
- type: this.STATE_TYPES.SIGLETON
215
- };
216
- }
217
- else if (Buffer.from(HookStateKeys.EVR_ISSUER_ADDR, 'hex').compare(stateKey) === 0 ||
218
- Buffer.from(HookStateKeys.FOUNDATION_ADDR, 'hex').compare(stateKey) === 0 ||
219
- Buffer.from(HookStateKeys.MOMENT_SIZE, 'hex').compare(stateKey) === 0 ||
220
- Buffer.from(HookStateKeys.PURCHASER_TARGET_PRICE, 'hex').compare(stateKey) === 0 ||
221
- Buffer.from(HookStateKeys.HOST_HEARTBEAT_FREQ, 'hex').compare(stateKey) ||
222
- Buffer.from(HookStateKeys.MINT_LIMIT, 'hex').compare(stateKey) === 0 ||
223
- Buffer.from(HookStateKeys.FIXED_REG_FEE, 'hex').compare(stateKey) === 0 ||
224
- Buffer.from(HookStateKeys.LEASE_ACQUIRE_WINDOW, 'hex').compare(stateKey) === 0 ||
225
- Buffer.from(HookStateKeys.REWARD_CONFIGURATION, 'hex').compare(stateKey) === 0 ||
226
- Buffer.from(HookStateKeys.MAX_TOLERABLE_DOWNTIME, 'hex').compare(stateKey) === 0) {
227
- return {
228
- key: hexKey,
229
- type: this.STATE_TYPES.CONFIGURATION
230
- };
231
- }
232
- else
233
- throw { type: 'Validation Error', message: 'Invalid state key.' };
234
- }
235
-
236
- static generateTokenIdStateKey(nfTokenId) {
237
- // 1 byte - Key Type.
238
- let buf = Buffer.allocUnsafe(1);
239
- buf.writeUInt8(STATE_KEY_TYPES.TOKEN_ID);
240
-
241
- const nfTokenIdBuf = Buffer.from(nfTokenId, "hex");
242
- const stateKeyBuf = (Buffer.concat([Buffer.from(EVERNODE_PREFIX, "utf-8"), buf, nfTokenIdBuf.slice(4, 32)]));
243
- return stateKeyBuf.toString('hex').toUpperCase();
244
- }
245
-
246
- static generateHostAddrStateKey(address) {
247
- // 1 byte - Key Type.
248
- // 8 bytes - Zeros.
249
- let buf = Buffer.allocUnsafe(9);
250
- buf.writeUInt8(STATE_KEY_TYPES.HOST_ADDR);
251
- for (let i = 0; i < HOST_ADDR_KEY_ZERO_COUNT; i++) {
252
- buf.writeUInt8(0, i + 1);
253
- }
254
-
255
- const addrBuf = Buffer.from(codec.decodeAccountID(address), "hex");
256
- const stateKeyBuf = Buffer.concat([Buffer.from(EVERNODE_PREFIX, "utf-8"), buf, addrBuf]);
257
- return stateKeyBuf.toString('hex').toUpperCase();
258
- }
259
-
260
- static getHookStateIndex(hookAccount, stateKey, hookNamespace = EvernodeConstants.HOOK_NAMESPACE) {
261
- const typeBuf = Buffer.allocUnsafe(2);
262
- typeBuf.writeInt16BE(HOOK_STATE_LEDGER_TYPE_PREFIX);
263
-
264
- const accIdBuf = codec.decodeAccountID(hookAccount);
265
- const stateKeyBuf = Buffer.from(stateKey, 'hex');
266
- const namespaceBuf = Buffer.from(hookNamespace, 'hex');
267
-
268
- let hash = crypto.createHash('sha512');
269
-
270
- let data = hash.update(typeBuf);
271
- data = hash.update(accIdBuf);
272
- data = hash.update(stateKeyBuf);
273
- data = hash.update(namespaceBuf);
274
-
275
- const digest = data.digest('hex');
276
- // Get the first 32 bytes of hash.
277
- return digest.substring(0, 64).toUpperCase();
278
- }
279
- }
280
-
281
- module.exports = {
282
- StateHelpers
283
- }
@@ -1,62 +0,0 @@
1
- const { MemoFormats } = require('./evernode-common');
2
-
3
- class TransactionHelper {
4
-
5
- // Convert memos from our object type to xrpl lib object type.
6
- static formatMemos(memos) {
7
- return memos ? memos.filter(m => m.type).map(m => {
8
- const data = (m.format === MemoFormats.HEX) ? m.data :
9
- TransactionHelper.asciiToHex((typeof m.data === "object") ? JSON.stringify(m.data) : m.data)
10
- return {
11
- Memo: {
12
- MemoType: TransactionHelper.asciiToHex(m.type),
13
- MemoFormat: TransactionHelper.asciiToHex(m.format),
14
- MemoData: data
15
- }
16
- }
17
- }) : [];
18
- }
19
-
20
- // Convert memos from xrpl lib object type to our object type.
21
- static deserializeMemos(memos) {
22
- if (!memos)
23
- return [];
24
-
25
- return memos.filter(m => m.Memo).map(m => {
26
- const format = m.Memo.MemoFormat ? TransactionHelper.hexToASCII(m.Memo.MemoFormat) : null;
27
- const data = m.Memo.MemoData ?
28
- ((format === MemoFormats.HEX) ? m.Memo.MemoData : TransactionHelper.hexToASCII(m.Memo.MemoData)) : null;
29
- return {
30
- type: m.Memo.MemoType ? TransactionHelper.hexToASCII(m.Memo.MemoType) : null,
31
- format: format,
32
- data: data
33
- }
34
- })
35
- }
36
-
37
- static hexToASCII(hex) {
38
- if (!hex)
39
- return "";
40
-
41
- let str = "";
42
- for (let n = 0; n < hex.length; n += 2) {
43
- str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
44
- }
45
- return str;
46
- }
47
-
48
- static asciiToHex(str) {
49
- if (!str)
50
- return "";
51
-
52
- let hex = "";
53
- for (let n = 0; n < str.length; n++) {
54
- hex += str.charCodeAt(n).toString(16)
55
- }
56
- return hex;
57
- }
58
- }
59
-
60
- module.exports = {
61
- TransactionHelper
62
- }