@xyo-network/chain-reward-redemption 1.15.21 → 1.15.23

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.
Files changed (48) hide show
  1. package/dist/node/index.mjs +316 -243
  2. package/dist/node/index.mjs.map +1 -1
  3. package/dist/node/manifest/getLocator.d.ts.map +1 -1
  4. package/dist/node/modules/ChainStepRewardsClaimSentinel/ChainStepRewardsClaimSentinel.d.ts +38 -0
  5. package/dist/node/modules/ChainStepRewardsClaimSentinel/ChainStepRewardsClaimSentinel.d.ts.map +1 -0
  6. package/dist/node/modules/ChainStepRewardsClaimSentinel/StepIdentityPayload.d.ts.map +1 -0
  7. package/dist/node/modules/ChainStepRewardsClaimSentinel/index.d.ts +3 -0
  8. package/dist/node/modules/ChainStepRewardsClaimSentinel/index.d.ts.map +1 -0
  9. package/dist/node/modules/DerivedAddressWalletTransferSentinel/DerivedAddressWalletTransferSentinel.d.ts +63 -0
  10. package/dist/node/modules/DerivedAddressWalletTransferSentinel/DerivedAddressWalletTransferSentinel.d.ts.map +1 -0
  11. package/dist/node/modules/DerivedAddressWalletTransferSentinel/index.d.ts +2 -0
  12. package/dist/node/modules/DerivedAddressWalletTransferSentinel/index.d.ts.map +1 -0
  13. package/dist/node/modules/DerivedAddressWalletTransferSentinel/spec/DerivedAddressWalletTransferSentinel.spec.d.ts +2 -0
  14. package/dist/node/modules/DerivedAddressWalletTransferSentinel/spec/DerivedAddressWalletTransferSentinel.spec.d.ts.map +1 -0
  15. package/dist/node/modules/helper/index.d.ts +2 -0
  16. package/dist/node/modules/helper/index.d.ts.map +1 -0
  17. package/dist/node/modules/helper/retry.d.ts +9 -0
  18. package/dist/node/modules/helper/retry.d.ts.map +1 -0
  19. package/dist/node/modules/index.d.ts +2 -2
  20. package/dist/node/modules/index.d.ts.map +1 -1
  21. package/dist/node/server/routes/rewardRedemption/routeDefinitions/getRouteDefinitions.d.ts.map +1 -1
  22. package/dist/node/server/routes/rewardRedemption/routeDefinitions/routes/index.d.ts +0 -1
  23. package/dist/node/server/routes/rewardRedemption/routeDefinitions/routes/index.d.ts.map +1 -1
  24. package/dist/node/server/routes/rewardRedemption/routeDefinitions/routes/redeem.d.ts +0 -22
  25. package/dist/node/server/routes/rewardRedemption/routeDefinitions/routes/redeem.d.ts.map +1 -1
  26. package/package.json +54 -53
  27. package/src/manifest/getLocator.ts +15 -13
  28. package/src/manifest/node.json +6 -21
  29. package/src/modules/{ChainRewardsClaimSentinel.ts → ChainStepRewardsClaimSentinel/ChainStepRewardsClaimSentinel.ts} +23 -20
  30. package/src/modules/ChainStepRewardsClaimSentinel/index.ts +2 -0
  31. package/src/modules/DerivedAddressWalletTransferSentinel/DerivedAddressWalletTransferSentinel.ts +172 -0
  32. package/src/modules/DerivedAddressWalletTransferSentinel/index.ts +1 -0
  33. package/src/modules/DerivedAddressWalletTransferSentinel/spec/DerivedAddressWalletTransferSentinel.spec.ts +146 -0
  34. package/src/modules/helper/index.ts +1 -0
  35. package/src/modules/helper/retry.ts +30 -0
  36. package/src/modules/index.ts +2 -2
  37. package/src/server/routes/rewardRedemption/routeDefinitions/getRouteDefinitions.ts +0 -1
  38. package/src/server/routes/rewardRedemption/routeDefinitions/routes/claimRange.ts +7 -7
  39. package/src/server/routes/rewardRedemption/routeDefinitions/routes/index.ts +0 -1
  40. package/src/server/routes/rewardRedemption/routeDefinitions/routes/redeem.ts +20 -91
  41. package/dist/node/modules/ChainRewardsClaimSentinel.d.ts +0 -38
  42. package/dist/node/modules/ChainRewardsClaimSentinel.d.ts.map +0 -1
  43. package/dist/node/modules/StepIdentityPayload.d.ts.map +0 -1
  44. package/dist/node/server/routes/rewardRedemption/routeDefinitions/routes/claimAddress.d.ts +0 -3
  45. package/dist/node/server/routes/rewardRedemption/routeDefinitions/routes/claimAddress.d.ts.map +0 -1
  46. package/src/server/routes/rewardRedemption/routeDefinitions/routes/claimAddress.ts +0 -133
  47. /package/dist/node/modules/{StepIdentityPayload.d.ts → ChainStepRewardsClaimSentinel/StepIdentityPayload.d.ts} +0 -0
  48. /package/src/modules/{StepIdentityPayload.ts → ChainStepRewardsClaimSentinel/StepIdentityPayload.ts} +0 -0
@@ -111,121 +111,44 @@ var addDataLakeRoutes = /* @__PURE__ */ __name((app) => {
111
111
  }));
112
112
  }, "addDataLakeRoutes");
113
113
 
114
- // src/server/routes/rewardRedemption/middleware/requestHandlerValidator.ts
115
- import { isDefined as isDefined2, isPromise } from "@xylabs/typeof";
116
- import { ReasonPhrases, StatusCodes } from "http-status-codes";
117
- import { z } from "zod";
118
- var EmptyParamsZod = z.object({}).catchall(z.string());
119
- var EmptyQueryParamsZod = z.object({}).catchall(z.union([
120
- z.string(),
121
- z.array(z.string())
122
- ]));
123
- var ValidateRequestDefaults = {
124
- params: EmptyParamsZod,
125
- query: EmptyQueryParamsZod,
126
- body: z.json().optional(),
127
- response: z.json().optional()
128
- };
129
- function requestHandlerValidator(schemas) {
130
- const validators = {
131
- ...ValidateRequestDefaults,
132
- ...schemas
133
- };
134
- return (handler) => {
135
- return async (req, res, next) => {
136
- const originalJson = res.json.bind(res);
137
- try {
138
- const errors = [];
139
- const keys = [
140
- "params",
141
- "query",
142
- "body"
143
- ];
144
- for (const key of keys) {
145
- const validator = validators[key];
146
- const result2 = validator.safeParse(req[key]);
147
- if (result2.success) {
148
- if (isDefined2(result2.data)) Object.assign(req[key], result2.data);
149
- } else {
150
- errors.push(...result2.error.issues.map((issue) => issue.path.length === 0 ? `${key}: ${issue.message}` : `${key}.${issue.path.join(".")}: ${issue.message}`));
151
- }
152
- }
153
- if (errors.length > 0) {
154
- const message = errors.join("; ");
155
- const err = new Error(message);
156
- err.name = ReasonPhrases.BAD_REQUEST;
157
- err.statusCode = StatusCodes.BAD_REQUEST;
158
- next(err);
159
- return false;
160
- }
161
- res.json = (data) => {
162
- const result2 = validators.response.safeParse(data);
163
- if (result2.success) {
164
- return originalJson(result2.data);
165
- } else {
166
- const message = result2.error.issues.map((issue) => issue.path.length === 0 ? `response: ${issue.message}` : `response.${issue.path.join(".")}: ${issue.message}`).join("; ");
167
- const err = new Error(message);
168
- err.name = ReasonPhrases.INTERNAL_SERVER_ERROR;
169
- err.statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
170
- res.json = originalJson;
171
- throw err;
172
- }
173
- };
174
- const result = handler(req, res, next);
175
- if (result && isPromise(result)) {
176
- await result;
177
- }
178
- } catch (err) {
179
- res.json = originalJson;
180
- next(err);
181
- }
182
- };
183
- };
184
- }
185
- __name(requestHandlerValidator, "requestHandlerValidator");
186
-
187
- // src/server/routes/rewardRedemption/routeDefinitions/util/getViewerFromConfig.ts
188
- import { isDefined as isDefined3 } from "@xylabs/typeof";
189
- import { HttpRpcTransport, JsonRpcXyoViewer, XyoViewerRpcSchemas } from "@xyo-network/xl1-rpc";
190
- var viewer;
191
- var getViewerFromConfig = /* @__PURE__ */ __name((config) => {
192
- if (isDefined3(viewer)) return viewer;
193
- const transport = new HttpRpcTransport(config.rewardRedemptionApi.chainRpcApiUrl, XyoViewerRpcSchemas);
194
- viewer = new JsonRpcXyoViewer(transport);
195
- return viewer;
196
- }, "getViewerFromConfig");
197
-
198
- // src/server/routes/rewardRedemption/routeDefinitions/util/rewardableSteps.ts
199
- var RewardableSteps = [
200
- 3,
201
- 4,
202
- 5,
203
- 6,
204
- 7,
205
- 8
206
- ];
207
-
208
114
  // src/server/routes/rewardRedemption/routeDefinitions/routes/claimRange.ts
209
- import { assertEx as assertEx2 } from "@xylabs/assert";
210
- import { isDefined as isDefined5 } from "@xylabs/typeof";
115
+ import { assertEx as assertEx3 } from "@xylabs/assert";
116
+ import { isDefined as isDefined6 } from "@xylabs/typeof";
211
117
  import { blockRangeSteps as blockRangeSteps2 } from "@xyo-network/chain-protocol";
212
118
  import { PayloadBuilder as PayloadBuilder2 } from "@xyo-network/payload-builder";
213
119
  import { PayloadZodLoose } from "@xyo-network/payload-model";
214
120
  import { asSentinelInstance } from "@xyo-network/sentinel-model";
215
121
  import { asXL1BlockNumber as asXL1BlockNumber2 } from "@xyo-network/xl1-protocol";
216
- import { z as z2 } from "zod";
122
+ import { z as z3 } from "zod";
217
123
 
218
- // src/modules/ChainRewardsClaimSentinel.ts
124
+ // src/modules/ChainStepRewardsClaimSentinel/ChainStepRewardsClaimSentinel.ts
219
125
  import { assertEx } from "@xylabs/assert";
220
126
  import { toAddress } from "@xylabs/hex";
221
- import { isDefined as isDefined4, isUndefined } from "@xylabs/typeof";
127
+ import { isDefined as isDefined2, isUndefined } from "@xylabs/typeof";
222
128
  import { blockRangeSteps, createTransferPayload } from "@xyo-network/chain-protocol";
223
129
  import { AbstractSentinel } from "@xyo-network/sentinel-abstract";
224
130
  import { asXL1BlockNumber, XYO_STEP_REWARD_ADDRESS } from "@xyo-network/xl1-protocol";
225
131
  import { completedStepRewardAddress, derivedReceiveAddress, flattenHydratedTransaction, flattenHydratedTransactions } from "@xyo-network/xl1-protocol-sdk";
226
132
  import { Mutex } from "async-mutex";
227
133
 
228
- // src/modules/StepIdentityPayload.ts
134
+ // src/modules/helper/retry.ts
135
+ import { delay } from "@xylabs/delay";
136
+ async function retry(fn, delayMs = 1e3, retries = 3) {
137
+ let lastError;
138
+ for (let attempt = 1; attempt <= retries; attempt++) {
139
+ try {
140
+ return await fn();
141
+ } catch (error) {
142
+ lastError = error;
143
+ if (attempt >= retries) throw lastError;
144
+ if (delayMs > 0) await delay(delayMs);
145
+ }
146
+ }
147
+ throw new Error("Retry logic failed unexpectedly");
148
+ }
149
+ __name(retry, "retry");
150
+
151
+ // src/modules/ChainStepRewardsClaimSentinel/StepIdentityPayload.ts
229
152
  import { AsObjectFactory } from "@xylabs/object";
230
153
  import { isPayloadOfZodType } from "@xyo-network/payload-model";
231
154
  import { StepIdentityZod } from "@xyo-network/xl1-rpc";
@@ -233,10 +156,12 @@ var StepIdentitySchema = "network.xyo.chain.step.identity";
233
156
  var isStepIdentityPayload = isPayloadOfZodType(StepIdentityZod, StepIdentitySchema);
234
157
  var asStepIdentityPayload = AsObjectFactory.create(isStepIdentityPayload);
235
158
 
236
- // src/modules/ChainRewardsClaimSentinel.ts
237
- var ChainRewardsClaimSentinelConfigSchema = "network.xyo.sentinel.chain.rewards.claim.config";
159
+ // src/modules/ChainStepRewardsClaimSentinel/ChainStepRewardsClaimSentinel.ts
160
+ var ChainStepRewardsClaimSentinelConfigSchema = "network.xyo.sentinel.chain.step.rewards.claim.config";
161
+ var retryAttempts = 3;
162
+ var retryDelayMs = 6e4;
238
163
  var scope = "reward-escrow";
239
- var RewardableSteps2 = [
164
+ var RewardableSteps = [
240
165
  3,
241
166
  4,
242
167
  5,
@@ -244,14 +169,14 @@ var RewardableSteps2 = [
244
169
  7,
245
170
  8
246
171
  ];
247
- var ChainRewardsClaimSentinel = class extends AbstractSentinel {
172
+ var ChainStepRewardsClaimSentinel = class extends AbstractSentinel {
248
173
  static {
249
- __name(this, "ChainRewardsClaimSentinel");
174
+ __name(this, "ChainStepRewardsClaimSentinel");
250
175
  }
251
176
  static configSchemas = [
252
- ChainRewardsClaimSentinelConfigSchema
177
+ ChainStepRewardsClaimSentinelConfigSchema
253
178
  ];
254
- static defaultConfigSchema = ChainRewardsClaimSentinelConfigSchema;
179
+ static defaultConfigSchema = ChainStepRewardsClaimSentinelConfigSchema;
255
180
  _claimAttemptsCounter;
256
181
  _claimCheckCounter;
257
182
  _claimErrorCounter;
@@ -262,16 +187,16 @@ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
262
187
  }
263
188
  async createHandler() {
264
189
  await super.createHandler();
265
- this._claimAttemptsCounter = this.meter?.createCounter("chain_rewards_claim_sentinel_attempts_total", {
190
+ this._claimAttemptsCounter = this.meter?.createCounter("chain_step_rewards_claim_sentinel_attempts_total", {
266
191
  description: "Number of claim attempts"
267
192
  });
268
- this._claimCheckCounter = this.meter?.createCounter("chain_rewards_claim_sentinel_check_total", {
193
+ this._claimCheckCounter = this.meter?.createCounter("chain_step_rewards_claim_sentinel_check_total", {
269
194
  description: "Number of claim checks"
270
195
  });
271
- this._claimSuccessCounter = this.meter?.createCounter("chain_rewards_claim_sentinel_success_total", {
196
+ this._claimSuccessCounter = this.meter?.createCounter("chain_step_rewards_claim_sentinel_success_total", {
272
197
  description: "Number of claim successes"
273
198
  });
274
- this._claimErrorCounter = this.meter?.createCounter("chain_rewards_claim_sentinel_errors_total", {
199
+ this._claimErrorCounter = this.meter?.createCounter("chain_step_rewards_claim_sentinel_errors_total", {
275
200
  description: "Number of claim errors"
276
201
  });
277
202
  }
@@ -292,10 +217,10 @@ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
292
217
  step,
293
218
  block
294
219
  };
295
- }).filter((stepIdentity) => RewardableSteps2.includes(stepIdentity.step));
220
+ }).filter((stepIdentity) => RewardableSteps.includes(stepIdentity.step));
296
221
  for (const stepIdentity of stepIdentities) {
297
222
  const result = await this.claimStepIdentity(stepIdentity);
298
- if (isDefined4(result)) response3.push(...flattenHydratedTransaction(result));
223
+ if (isDefined2(result)) response3.push(...flattenHydratedTransaction(result));
299
224
  }
300
225
  }
301
226
  return response3;
@@ -323,8 +248,8 @@ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
323
248
  const results = [];
324
249
  const connection = await this.gateway.connection();
325
250
  const { viewer: viewer2 } = connection;
326
- if (isDefined4(viewer2)) {
327
- for (const step of RewardableSteps2) {
251
+ if (isDefined2(viewer2)) {
252
+ for (const step of RewardableSteps) {
328
253
  const from = 0;
329
254
  const to = await viewer2.currentBlockNumber();
330
255
  const range = [
@@ -336,7 +261,7 @@ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
336
261
  ]);
337
262
  for (const stepIdentity of stepIdentities) {
338
263
  const result = await this.claimStepIdentity(stepIdentity);
339
- if (isDefined4(result)) results.push(result);
264
+ if (isDefined2(result)) results.push(result);
340
265
  }
341
266
  }
342
267
  }
@@ -355,9 +280,9 @@ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
355
280
  const stepRewardAddress = completedStepRewardAddress(stepIdentity);
356
281
  const balance = await viewer2.accountBalance(stepRewardAddress);
357
282
  if (balance > 0n) {
358
- this.logger?.info(`Found rewards to claim for step ${stepIdentity.step} at block ${stepIdentity.block}`);
283
+ this.logger?.info(`Found balance of ${balance} to claim for step ${stepIdentity.step} at block ${stepIdentity.block}`);
359
284
  this._claimAttemptsCounter?.add(1, claimCounterAttributes);
360
- const rewardsByStaker = await viewer2.networkStakeStepRewardPoolRewards(stepIdentity);
285
+ const rewardsByStaker = await retry(() => viewer2.networkStakeStepRewardPoolRewards(stepIdentity), retryDelayMs, retryAttempts);
361
286
  const addressDistributions = this.calculateAddressDistributions(rewardsByStaker, balance);
362
287
  const tx = await this.submitRewardDistributionTransaction(stepRewardAddress, addressDistributions, stepIdentity, this.gateway);
363
288
  this.logger?.info(`Claimed rewards for step ${stepIdentity.step} at block ${stepIdentity.block}`);
@@ -385,36 +310,241 @@ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
385
310
  nbf: currentBlock,
386
311
  exp: currentBlock + 1e3
387
312
  });
388
- if (isDefined4(result)) return result[1];
313
+ if (isDefined2(result)) return result[1];
389
314
  }
390
315
  };
391
316
 
317
+ // src/modules/DerivedAddressWalletTransferSentinel/DerivedAddressWalletTransferSentinel.ts
318
+ import { assertEx as assertEx2 } from "@xylabs/assert";
319
+ import { AddressZod, EthAddressZod, hexToBigInt, HexZod, toAddress as toAddress2, toHex } from "@xylabs/hex";
320
+ import { isDefined as isDefined3, isUndefined as isUndefined2 } from "@xylabs/typeof";
321
+ import { createTransferPayload as createTransferPayload2 } from "@xyo-network/chain-protocol";
322
+ import { AbstractSentinel as AbstractSentinel2 } from "@xyo-network/sentinel-abstract";
323
+ import { derivedReceiveAddress as derivedReceiveAddress2, flattenHydratedTransaction as flattenHydratedTransaction2, isEIP712DataPayload, isEIP712SignaturePayload, verifyEIP712Message } from "@xyo-network/xl1-protocol-sdk";
324
+ import z from "zod";
325
+ var DerivedAddressWalletTransferSentinelConfigSchema = "network.xyo.sentinel.chain.derived.address.wallet.transfer.config";
326
+ var scope2 = "reward-escrow";
327
+ var ConfirmedClaimValuesZod = z.object({
328
+ "From": EthAddressZod,
329
+ "To XL1 Address": AddressZod,
330
+ "XL1 Amount": z.string(),
331
+ "XL1 Amount (Hex)": HexZod,
332
+ "XL1 Not after block": z.number().int().nonnegative(),
333
+ "XL1 Not before block": z.number().int().nonnegative()
334
+ });
335
+ var parseConfirmedClaimValues = /* @__PURE__ */ __name((values) => {
336
+ return {
337
+ amount: values["XL1 Amount (Hex)"],
338
+ exp: values["XL1 Not after block"],
339
+ from: toAddress2(values.From),
340
+ nbf: values["XL1 Not before block"],
341
+ to: toAddress2(values["To XL1 Address"])
342
+ };
343
+ }, "parseConfirmedClaimValues");
344
+ var DerivedAddressWalletTransferSentinel = class extends AbstractSentinel2 {
345
+ static {
346
+ __name(this, "DerivedAddressWalletTransferSentinel");
347
+ }
348
+ static configSchemas = [
349
+ DerivedAddressWalletTransferSentinelConfigSchema
350
+ ];
351
+ static defaultConfigSchema = DerivedAddressWalletTransferSentinelConfigSchema;
352
+ _transferAttemptsCounter;
353
+ _transferErrorCounter;
354
+ _transferSuccessCounter;
355
+ get gateway() {
356
+ return this.params.gateway;
357
+ }
358
+ async createHandler() {
359
+ await super.createHandler();
360
+ this._transferAttemptsCounter = this.meter?.createCounter("derived_address_wallet_transfer_sentinel_attempts_total", {
361
+ description: "Number of transfer attempts"
362
+ });
363
+ this._transferSuccessCounter = this.meter?.createCounter("derived_address_wallet_transfer_sentinel_success_total", {
364
+ description: "Number of transfer successes"
365
+ });
366
+ this._transferErrorCounter = this.meter?.createCounter("derived_address_wallet_transfer_sentinel_errors_total", {
367
+ description: "Number of transfer errors"
368
+ });
369
+ }
370
+ async reportHandler(payloads) {
371
+ const data = payloads?.find(isEIP712DataPayload);
372
+ const signature = payloads?.find(isEIP712SignaturePayload);
373
+ if (isUndefined2(data) || isUndefined2(signature)) return [];
374
+ this._transferAttemptsCounter?.add(1);
375
+ const valid = await verifyEIP712Message(data, signature);
376
+ if (!valid) {
377
+ this._transferErrorCounter?.add(1);
378
+ throw new Error("Invalid EIP712 signature");
379
+ }
380
+ const values = data.values;
381
+ const parsed = parseConfirmedClaimValues(values);
382
+ const signatureAddress = toAddress2(signature.address);
383
+ const parsedAddress = toAddress2(parsed.from);
384
+ if (signatureAddress === parsedAddress) {
385
+ const tx = await this.submitRewardDistributionTransaction(parsed);
386
+ if (isDefined3(tx)) {
387
+ this._transferSuccessCounter?.add(1);
388
+ return flattenHydratedTransaction2(tx);
389
+ }
390
+ }
391
+ this._transferErrorCounter?.add(1);
392
+ return [];
393
+ }
394
+ submitRewardDistributionTransaction = /* @__PURE__ */ __name(async (claimValues) => {
395
+ const { amount, from: address, to, nbf, exp } = claimValues;
396
+ const signer = assertEx2(await this.gateway.signer(), () => "Signer is not defined in gateway");
397
+ const signerAddress = await signer.address();
398
+ const connection = await this.gateway.connection();
399
+ const viewer2 = assertEx2(connection.viewer, () => "Viewer is not defined in gateway connection");
400
+ const chainId = await viewer2.chainId();
401
+ const currentBlock = await viewer2.currentBlockNumber();
402
+ if (currentBlock < nbf || currentBlock > exp) throw new Error("Transaction is not within a valid block range");
403
+ const escrowAccount = derivedReceiveAddress2(address, scope2);
404
+ const balance = await viewer2.accountBalance(escrowAccount);
405
+ const redemptionAmount = hexToBigInt(toHex(amount));
406
+ assertEx2(balance === redemptionAmount, () => "Insufficient balance in escrow account");
407
+ const allowance = await viewer2.accountBalance(signerAddress);
408
+ assertEx2(allowance > 1000n, () => "Insufficient allowance to transfer from escrow account");
409
+ const transferPayload = createTransferPayload2(escrowAccount, {
410
+ [to]: hexToBigInt(toHex(amount))
411
+ });
412
+ transferPayload.context = {
413
+ address,
414
+ scope: scope2
415
+ };
416
+ const chain = await viewer2.chainId();
417
+ const result = await this.gateway.addPayloadsToChain?.([
418
+ transferPayload
419
+ ], [], {
420
+ chain,
421
+ nbf,
422
+ exp
423
+ });
424
+ if (isDefined3(result)) return result[1];
425
+ }, "submitRewardDistributionTransaction");
426
+ };
427
+
428
+ // src/server/routes/rewardRedemption/middleware/requestHandlerValidator.ts
429
+ import { isDefined as isDefined4, isPromise } from "@xylabs/typeof";
430
+ import { ReasonPhrases, StatusCodes } from "http-status-codes";
431
+ import { z as z2 } from "zod";
432
+ var EmptyParamsZod = z2.object({}).catchall(z2.string());
433
+ var EmptyQueryParamsZod = z2.object({}).catchall(z2.union([
434
+ z2.string(),
435
+ z2.array(z2.string())
436
+ ]));
437
+ var ValidateRequestDefaults = {
438
+ params: EmptyParamsZod,
439
+ query: EmptyQueryParamsZod,
440
+ body: z2.json().optional(),
441
+ response: z2.json().optional()
442
+ };
443
+ function requestHandlerValidator(schemas) {
444
+ const validators = {
445
+ ...ValidateRequestDefaults,
446
+ ...schemas
447
+ };
448
+ return (handler) => {
449
+ return async (req, res, next) => {
450
+ const originalJson = res.json.bind(res);
451
+ try {
452
+ const errors = [];
453
+ const keys = [
454
+ "params",
455
+ "query",
456
+ "body"
457
+ ];
458
+ for (const key of keys) {
459
+ const validator = validators[key];
460
+ const result2 = validator.safeParse(req[key]);
461
+ if (result2.success) {
462
+ if (isDefined4(result2.data)) Object.assign(req[key], result2.data);
463
+ } else {
464
+ errors.push(...result2.error.issues.map((issue) => issue.path.length === 0 ? `${key}: ${issue.message}` : `${key}.${issue.path.join(".")}: ${issue.message}`));
465
+ }
466
+ }
467
+ if (errors.length > 0) {
468
+ const message = errors.join("; ");
469
+ const err = new Error(message);
470
+ err.name = ReasonPhrases.BAD_REQUEST;
471
+ err.statusCode = StatusCodes.BAD_REQUEST;
472
+ next(err);
473
+ return false;
474
+ }
475
+ res.json = (data) => {
476
+ const result2 = validators.response.safeParse(data);
477
+ if (result2.success) {
478
+ return originalJson(result2.data);
479
+ } else {
480
+ const message = result2.error.issues.map((issue) => issue.path.length === 0 ? `response: ${issue.message}` : `response.${issue.path.join(".")}: ${issue.message}`).join("; ");
481
+ const err = new Error(message);
482
+ err.name = ReasonPhrases.INTERNAL_SERVER_ERROR;
483
+ err.statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
484
+ res.json = originalJson;
485
+ throw err;
486
+ }
487
+ };
488
+ const result = handler(req, res, next);
489
+ if (result && isPromise(result)) {
490
+ await result;
491
+ }
492
+ } catch (err) {
493
+ res.json = originalJson;
494
+ next(err);
495
+ }
496
+ };
497
+ };
498
+ }
499
+ __name(requestHandlerValidator, "requestHandlerValidator");
500
+
501
+ // src/server/routes/rewardRedemption/routeDefinitions/util/getViewerFromConfig.ts
502
+ import { isDefined as isDefined5 } from "@xylabs/typeof";
503
+ import { HttpRpcTransport, JsonRpcXyoViewer, XyoViewerRpcSchemas } from "@xyo-network/xl1-rpc";
504
+ var viewer;
505
+ var getViewerFromConfig = /* @__PURE__ */ __name((config) => {
506
+ if (isDefined5(viewer)) return viewer;
507
+ const transport = new HttpRpcTransport(config.rewardRedemptionApi.chainRpcApiUrl, XyoViewerRpcSchemas);
508
+ viewer = new JsonRpcXyoViewer(transport);
509
+ return viewer;
510
+ }, "getViewerFromConfig");
511
+
512
+ // src/server/routes/rewardRedemption/routeDefinitions/util/rewardableSteps.ts
513
+ var RewardableSteps2 = [
514
+ 3,
515
+ 4,
516
+ 5,
517
+ 6,
518
+ 7,
519
+ 8
520
+ ];
521
+
392
522
  // src/server/routes/rewardRedemption/routeDefinitions/routes/claimRange.ts
393
- var query = z2.object({
394
- fromBlock: z2.coerce.number().int().min(0).optional(),
395
- toBlock: z2.coerce.number().int().min(0).optional(),
396
- step: z2.coerce.number().min(Math.min(...RewardableSteps)).max(Math.max(...RewardableSteps)).int().optional().default(3)
523
+ var query = z3.object({
524
+ fromBlock: z3.coerce.number().int().nonnegative().optional(),
525
+ toBlock: z3.coerce.number().int().nonnegative().optional(),
526
+ step: z3.coerce.number().int().nonnegative().min(Math.min(...RewardableSteps2)).max(Math.max(...RewardableSteps2)).optional().default(3)
397
527
  });
398
- var response = z2.array(PayloadZodLoose);
528
+ var response = z3.array(PayloadZodLoose);
399
529
  var validateRequest = requestHandlerValidator({
400
530
  query,
401
531
  response
402
532
  });
403
- var getChainRewardsClaimSentinel = /* @__PURE__ */ __name(async (node) => {
404
- const mod = await node.resolve("XYORewardRedemptionNode:ChainRewardsClaimSentinel");
533
+ var getChainStepRewardsClaimSentinel = /* @__PURE__ */ __name(async (node) => {
534
+ const mod = await node.resolve("XYORewardRedemptionNode:ChainStepRewardsClaimSentinel");
405
535
  const sentinel = asSentinelInstance(mod);
406
- return assertEx2(sentinel, () => "ChainRewardsClaimSentinel not found on node");
407
- }, "getChainRewardsClaimSentinel");
536
+ return assertEx3(sentinel, () => "ChainStepRewardsClaimSentinel not found on node");
537
+ }, "getChainStepRewardsClaimSentinel");
408
538
  var postClaimRange = {
409
539
  method: "post",
410
540
  path: "/rewards/claimRange",
411
541
  handlers: validateRequest(async (req, res) => {
412
542
  const { config, node } = req.app;
413
- const { fromBlock, toBlock, step } = z2.parse(query, req.query);
543
+ const { fromBlock, toBlock, step } = z3.parse(query, req.query);
414
544
  const viewer2 = getViewerFromConfig(config);
415
- const from = isDefined5(fromBlock) ? fromBlock : 0;
545
+ const from = isDefined6(fromBlock) ? fromBlock : 0;
416
546
  const currentBlock = await viewer2.currentBlockNumber();
417
- const to = isDefined5(toBlock) ? Math.min(toBlock, currentBlock) : currentBlock;
547
+ const to = isDefined6(toBlock) ? Math.min(toBlock, currentBlock) : currentBlock;
418
548
  if (to <= from) {
419
549
  res.status(400);
420
550
  res.json([]);
@@ -429,7 +559,7 @@ var postClaimRange = {
429
559
  ]);
430
560
  const results = [];
431
561
  for (const stepIdentity of stepIdentities) {
432
- const mod = await getChainRewardsClaimSentinel(node);
562
+ const mod = await getChainStepRewardsClaimSentinel(node);
433
563
  const stepIdentityPayload = new PayloadBuilder2({
434
564
  schema: StepIdentitySchema
435
565
  }).fields(stepIdentity).build();
@@ -444,84 +574,35 @@ var postClaimRange = {
444
574
  };
445
575
 
446
576
  // src/server/routes/rewardRedemption/routeDefinitions/routes/redeem.ts
447
- import { assertEx as assertEx3 } from "@xylabs/assert";
448
- import { hexToBigInt, toAddress as toAddress2, toHex } from "@xylabs/hex";
449
- import { isDefined as isDefined6 } from "@xylabs/typeof";
450
- import { createTransferPayload as createTransferPayload2 } from "@xyo-network/chain-protocol";
451
- import { HDWallet } from "@xyo-network/wallet";
452
- import { verifyEIP712Message } from "@xyo-network/xl1-protocol-sdk";
453
- import { HttpRpcXyoConnection, MemoryXyoGateway, MemoryXyoSigner, SignedHydratedTransactionZod } from "@xyo-network/xl1-rpc";
454
- import { z as z3 } from "zod";
455
- var body = z3.any();
456
- var response2 = SignedHydratedTransactionZod;
577
+ import { assertEx as assertEx4 } from "@xylabs/assert";
578
+ import { PayloadZodLoose as PayloadZodLoose2, PayloadZodStrictOfSchema } from "@xyo-network/payload-model";
579
+ import { asSentinelInstance as asSentinelInstance2 } from "@xyo-network/sentinel-model";
580
+ import { EIP712DataPayloadFieldsZod, EIP712DataPayloadSchema, EIP712SignaturePayloadFieldsZod, EIP712SignaturePayloadSchema } from "@xyo-network/xl1-protocol-sdk";
581
+ import { z as z4 } from "zod";
582
+ var body = z4.tuple([
583
+ PayloadZodStrictOfSchema(EIP712DataPayloadSchema).extend(EIP712DataPayloadFieldsZod.shape),
584
+ PayloadZodStrictOfSchema(EIP712SignaturePayloadSchema).extend(EIP712SignaturePayloadFieldsZod.shape)
585
+ ]);
586
+ var response2 = z4.array(PayloadZodLoose2);
457
587
  var validateRequest2 = requestHandlerValidator({
458
588
  body,
459
589
  response: response2
460
590
  });
461
- var getGateway = /* @__PURE__ */ __name(async (config) => {
462
- const { mnemonic, chainRpcApiUrl: endpoint } = config.rewardRedemptionApi;
463
- const account = await HDWallet.fromPhrase(assertEx3(mnemonic, () => ""));
464
- const signer = new MemoryXyoSigner(account);
465
- const connection = new HttpRpcXyoConnection({
466
- endpoint,
467
- account
468
- });
469
- const gateway = new MemoryXyoGateway(signer, connection);
470
- return gateway;
471
- }, "getGateway");
472
- var submitRewardDistributionTransaction = /* @__PURE__ */ __name(async (to, amount, nbf, exp, gateway) => {
473
- const signer = assertEx3(await gateway.signer(), () => "Signer is not defined in gateway");
474
- const from = await signer.address();
475
- const transferPayload = createTransferPayload2(from, {
476
- [to]: hexToBigInt(toHex(amount))
477
- });
478
- const connection = await gateway.connection();
479
- const viewer2 = assertEx3(connection.viewer, () => "Viewer is not defined in gateway connection");
480
- const chain = await viewer2.chainId();
481
- const result = await gateway.addPayloadsToChain?.([
482
- transferPayload
483
- ], [], {
484
- chain,
485
- nbf,
486
- exp
487
- });
488
- if (isDefined6(result)) return result[1];
489
- }, "submitRewardDistributionTransaction");
490
- var parseConfirmedClaimValues = /* @__PURE__ */ __name((values) => {
491
- return {
492
- from: toAddress2(values.from),
493
- to: values["To XL1 Address"],
494
- amount: values["XL1 Amount (Hex)"],
495
- nbf: values["XL1 Not before block"],
496
- exp: values["XL1 Not after block"]
497
- };
498
- }, "parseConfirmedClaimValues");
591
+ var getDerivedAddressWalletTransferSentinel = /* @__PURE__ */ __name(async (node) => {
592
+ const mod = await node.resolve("XYORewardRedemptionNode:DerivedAddressWalletTransferSentinel");
593
+ const sentinel = asSentinelInstance2(mod);
594
+ return assertEx4(sentinel, () => "DerivedAddressWalletTransferSentinel not found on node");
595
+ }, "getDerivedAddressWalletTransferSentinel");
499
596
  var postRedeem = {
500
597
  method: "post",
501
598
  path: "/rewards/redeem",
502
599
  handlers: validateRequest2(async (req, res) => {
503
- const { config } = req.app;
600
+ const { node } = req.app;
504
601
  const { body: body2 } = req;
505
- const [payload, signature] = body2;
506
- const valid = await verifyEIP712Message(payload, signature);
507
- if (valid) {
508
- const values = payload.values;
509
- const { from, to, amount, nbf, exp } = parseConfirmedClaimValues(values);
510
- assertEx3(toAddress2(signature.address) === toAddress2(from), () => "Signature does not match from address");
511
- const gateway = await getGateway(config);
512
- const receiver = toAddress2(to);
513
- const tx = await submitRewardDistributionTransaction(receiver, amount, nbf, exp, gateway);
514
- if (isDefined6(tx)) {
515
- res.status(200);
516
- res.json(tx);
517
- } else {
518
- res.status(500);
519
- res.json();
520
- }
521
- } else {
522
- res.status(404);
523
- res.json();
524
- }
602
+ const sentinel = await getDerivedAddressWalletTransferSentinel(node);
603
+ const result = await sentinel.report(body2);
604
+ res.status(200);
605
+ res.json(result);
525
606
  })
526
607
  };
527
608
 
@@ -529,7 +610,6 @@ var postRedeem = {
529
610
  var getRouteDefinitions = /* @__PURE__ */ __name(() => {
530
611
  return [
531
612
  postClaimRange,
532
- // postClaim,
533
613
  postRedeem
534
614
  ];
535
615
  }, "getRouteDefinitions");
@@ -571,10 +651,10 @@ var getApp = /* @__PURE__ */ __name((node, config) => {
571
651
  }, "getApp");
572
652
 
573
653
  // src/server/server.ts
574
- import { assertEx as assertEx4 } from "@xylabs/assert";
654
+ import { assertEx as assertEx5 } from "@xylabs/assert";
575
655
  import { isDefined as isDefined8, isString } from "@xylabs/typeof";
576
656
  import { boot } from "@xyo-network/bios";
577
- import { HDWallet as HDWallet3 } from "@xyo-network/wallet";
657
+ import { HDWallet as HDWallet2 } from "@xyo-network/wallet";
578
658
 
579
659
  // src/manifest/getLocator.ts
580
660
  import { isDefined as isDefined7 } from "@xylabs/typeof";
@@ -585,9 +665,9 @@ import { initTelemetry } from "@xyo-network/chain-telemetry";
585
665
  import { AbstractModule, LoggerModuleStatusReporter } from "@xyo-network/module-abstract";
586
666
  import { ModuleFactoryLocator } from "@xyo-network/module-factory-locator";
587
667
  import { MemorySentinel } from "@xyo-network/sentinel-memory";
588
- import { HDWallet as HDWallet2 } from "@xyo-network/wallet";
668
+ import { HDWallet } from "@xyo-network/wallet";
589
669
  import { hasMongoConfig } from "@xyo-network/xl1-protocol-sdk";
590
- import { HttpRpcXyoConnection as HttpRpcXyoConnection2, MemoryXyoGateway as MemoryXyoGateway2, MemoryXyoSigner as MemoryXyoSigner2 } from "@xyo-network/xl1-rpc";
670
+ import { HttpRpcXyoConnection, MemoryXyoGateway, MemoryXyoSigner } from "@xyo-network/xl1-rpc";
591
671
  var getLocator = /* @__PURE__ */ __name(async (context) => {
592
672
  const { config, logger } = context;
593
673
  const { otlpEndpoint } = config.telemetry?.otel ?? {};
@@ -638,27 +718,35 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
638
718
  meterProvider,
639
719
  statusReporter
640
720
  }));
641
- await registerChainRewardsClaimSentinel(locator, config, traceProvider, meterProvider, statusReporter);
721
+ const gateway = await getGateway(config);
722
+ const chainStepRewardsClaimSentinelParams = {
723
+ gateway,
724
+ traceProvider,
725
+ meterProvider,
726
+ statusReporter
727
+ };
728
+ locator.register(ChainStepRewardsClaimSentinel.factory(chainStepRewardsClaimSentinelParams));
729
+ const derivedAddressWalletTransferSentinelParams = {
730
+ gateway,
731
+ traceProvider,
732
+ meterProvider,
733
+ statusReporter
734
+ };
735
+ locator.register(DerivedAddressWalletTransferSentinel.factory(derivedAddressWalletTransferSentinelParams));
642
736
  return locator;
643
737
  }, "getLocator");
644
- var registerChainRewardsClaimSentinel = /* @__PURE__ */ __name(async (locator, config, traceProvider, meterProvider, statusReporter) => {
738
+ var getGateway = /* @__PURE__ */ __name(async (config) => {
645
739
  const { mnemonic, chainRpcApiUrl: endpoint } = config.rewardRedemptionApi;
646
- const walletPromise = isDefined7(mnemonic) ? HDWallet2.fromPhrase(mnemonic) : HDWallet2.random();
740
+ const walletPromise = isDefined7(mnemonic) ? HDWallet.fromPhrase(mnemonic) : HDWallet.random();
647
741
  const account = await walletPromise;
648
- const signer = new MemoryXyoSigner2(account);
649
- const connection = new HttpRpcXyoConnection2({
742
+ const signer = new MemoryXyoSigner(account);
743
+ const connection = new HttpRpcXyoConnection({
650
744
  endpoint,
651
745
  account
652
746
  });
653
- const gateway = new MemoryXyoGateway2(signer, connection);
654
- const chainRewardsClaimSentinelParams = {
655
- gateway,
656
- traceProvider,
657
- meterProvider,
658
- statusReporter
659
- };
660
- locator.register(ChainRewardsClaimSentinel.factory(chainRewardsClaimSentinelParams));
661
- }, "registerChainRewardsClaimSentinel");
747
+ const gateway = new MemoryXyoGateway(signer, connection);
748
+ return gateway;
749
+ }, "getGateway");
662
750
 
663
751
  // src/manifest/getNode.ts
664
752
  import { ManifestWrapper } from "@xyo-network/manifest-wrapper";
@@ -692,30 +780,15 @@ var node_default = {
692
780
  {
693
781
  config: {
694
782
  accountPath: "1/1'/2'",
695
- name: "ChainRewardsClaimSentinel",
696
- schema: "network.xyo.sentinel.chain.rewards.claim.config"
783
+ name: "ChainStepRewardsClaimSentinel",
784
+ schema: "network.xyo.sentinel.chain.step.rewards.claim.config"
697
785
  }
698
786
  },
699
787
  {
700
788
  config: {
701
- accountPath: "1/1'/3'",
702
- automations: [
703
- {
704
- frequency: 6e4,
705
- frequencyUnits: "millis",
706
- schema: "network.xyo.automation.interval",
707
- type: "interval"
708
- }
709
- ],
710
- name: "ChainRewardsClaimIntervalSentinel",
711
- schema: "network.xyo.sentinel.config",
712
- synchronous: true,
713
- tasks: [
714
- {
715
- mod: "ChainRewardsClaimSentinel",
716
- endPoint: "report"
717
- }
718
- ]
789
+ accountPath: "1/1'/4'",
790
+ name: "DerivedAddressWalletTransferSentinel",
791
+ schema: "network.xyo.sentinel.chain.derived.address.wallet.transfer.config"
719
792
  }
720
793
  }
721
794
  ],
@@ -779,20 +852,20 @@ var getSeedPhrase = /* @__PURE__ */ __name(async (bios, config, logger) => {
779
852
  if (isString(mnemonic)) {
780
853
  seedPhrase = mnemonic;
781
854
  } else {
782
- seedPhrase = HDWallet3.generateMnemonic();
855
+ seedPhrase = HDWallet2.generateMnemonic();
783
856
  logger?.log("[Bridge] No mnemonic provided, using random mnemonic. This is not recommended for production use.");
784
857
  logger?.log(`[Bridge] Mnemonic: ${seedPhrase}`);
785
858
  }
786
859
  await bios.seedPhraseStore.set("os", seedPhrase);
787
860
  }
788
- return assertEx4(await bios.seedPhraseStore.get("os"), () => "Unable to acquire mnemonic from bios");
861
+ return assertEx5(await bios.seedPhraseStore.get("os"), () => "Unable to acquire mnemonic from bios");
789
862
  }, "getSeedPhrase");
790
863
  var getServer = /* @__PURE__ */ __name(async (context) => {
791
864
  const { logger, config } = context;
792
865
  const { port, mnemonic } = config.rewardRedemptionApi;
793
866
  const bios = await boot();
794
867
  const seedPhrase = isDefined8(mnemonic) ? mnemonic : await getSeedPhrase(bios, config, logger);
795
- const wallet = await HDWallet3.fromPhrase(seedPhrase);
868
+ const wallet = await HDWallet2.fromPhrase(seedPhrase);
796
869
  const nodeContext = {
797
870
  wallet,
798
871
  logger,