@xyo-network/chain-reward-redemption 1.15.16 → 1.15.18

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.
@@ -48,10 +48,10 @@ var archivistMiddleware = /* @__PURE__ */ __name((options) => {
48
48
  });
49
49
  router.post("/insert", async (req, res) => {
50
50
  setRawResponseFormat(res);
51
- const body3 = Array.isArray(req.body) ? req.body : [
51
+ const body2 = Array.isArray(req.body) ? req.body : [
52
52
  req.body
53
53
  ];
54
- const payloads = (await PayloadBuilder.hashPairs(body3)).map((p) => p[0]);
54
+ const payloads = (await PayloadBuilder.hashPairs(body2)).map((p) => p[0]);
55
55
  const archivist = await getArchivist(node, archivistModuleIdentifier);
56
56
  const result = await archivist.insert(payloads);
57
57
  res.status(200).json(result);
@@ -111,16 +111,6 @@ var addDataLakeRoutes = /* @__PURE__ */ __name((app) => {
111
111
  }));
112
112
  }, "addDataLakeRoutes");
113
113
 
114
- // src/server/routes/rewardRedemption/routeDefinitions/routes/claimAddress.ts
115
- import { asAddress } from "@xylabs/hex";
116
- import { isUndefined } from "@xylabs/typeof";
117
- import { createTransferPayload } from "@xyo-network/chain-protocol";
118
- import { PayloadZodLoose } from "@xyo-network/payload-model";
119
- import { asStepIdentity } from "@xyo-network/xl1-protocol";
120
- import { buildTransaction, completedStepRewardAddress, derivedReceiveAddress } from "@xyo-network/xl1-protocol-sdk";
121
- import { SignedHydratedTransactionZod } from "@xyo-network/xl1-rpc";
122
- import { z as z2 } from "zod";
123
-
124
114
  // src/server/routes/rewardRedemption/middleware/requestHandlerValidator.ts
125
115
  import { isDefined as isDefined2, isPromise } from "@xylabs/typeof";
126
116
  import { ReasonPhrases, StatusCodes } from "http-status-codes";
@@ -194,28 +184,12 @@ function requestHandlerValidator(schemas) {
194
184
  }
195
185
  __name(requestHandlerValidator, "requestHandlerValidator");
196
186
 
197
- // src/server/routes/rewardRedemption/routeDefinitions/pathParams/AddressPathParam.ts
198
- import { EthAddressFromStringZod } from "@xylabs/hex";
199
-
200
- // src/server/routes/rewardRedemption/routeDefinitions/util/getAccountFromConfig.ts
201
- import { assertEx } from "@xylabs/assert";
202
- import { isDefined as isDefined3 } from "@xylabs/typeof";
203
- import { HDWallet } from "@xyo-network/wallet";
204
- var account;
205
- var getAccountFromConfig = /* @__PURE__ */ __name(async (config) => {
206
- if (isDefined3(account)) {
207
- return account;
208
- }
209
- account = await HDWallet.fromPhrase(assertEx(config.rewardRedemptionApi.mnemonic, () => "Mnemonic is required for reward redemption"));
210
- return account;
211
- }, "getAccountFromConfig");
212
-
213
187
  // src/server/routes/rewardRedemption/routeDefinitions/util/getViewerFromConfig.ts
214
- import { isDefined as isDefined4 } from "@xylabs/typeof";
188
+ import { isDefined as isDefined3 } from "@xylabs/typeof";
215
189
  import { HttpRpcTransport, JsonRpcXyoViewer, XyoViewerRpcSchemas } from "@xyo-network/xl1-rpc";
216
190
  var viewer;
217
191
  var getViewerFromConfig = /* @__PURE__ */ __name((config) => {
218
- if (isDefined4(viewer)) return viewer;
192
+ if (isDefined3(viewer)) return viewer;
219
193
  const transport = new HttpRpcTransport(config.rewardRedemptionApi.chainRpcApiUrl, XyoViewerRpcSchemas);
220
194
  viewer = new JsonRpcXyoViewer(transport);
221
195
  return viewer;
@@ -231,200 +205,293 @@ var RewardableSteps = [
231
205
  8
232
206
  ];
233
207
 
234
- // src/server/routes/rewardRedemption/routeDefinitions/routes/claimAddress.ts
208
+ // src/server/routes/rewardRedemption/routeDefinitions/routes/claimRange.ts
209
+ import { assertEx as assertEx2 } from "@xylabs/assert";
210
+ import { isDefined as isDefined5 } from "@xylabs/typeof";
211
+ import { blockRangeSteps as blockRangeSteps2 } from "@xyo-network/chain-protocol";
212
+ import { PayloadBuilder as PayloadBuilder2 } from "@xyo-network/payload-builder";
213
+ import { PayloadZodLoose } from "@xyo-network/payload-model";
214
+ import { asSentinelInstance } from "@xyo-network/sentinel-model";
215
+ import { asXL1BlockNumber as asXL1BlockNumber2 } from "@xyo-network/xl1-protocol";
216
+ import { z as z2 } from "zod";
217
+
218
+ // src/modules/ChainRewardsClaimSentinel.ts
219
+ import { assertEx } from "@xylabs/assert";
220
+ import { toAddress } from "@xylabs/hex";
221
+ import { isDefined as isDefined4, isUndefined } from "@xylabs/typeof";
222
+ import { blockRangeSteps, createTransferPayload } from "@xyo-network/chain-protocol";
223
+ import { AbstractSentinel } from "@xyo-network/sentinel-abstract";
224
+ import { asXL1BlockNumber, XYO_STEP_REWARD_ADDRESS } from "@xyo-network/xl1-protocol";
225
+ import { completedStepRewardAddress, derivedReceiveAddress, flattenHydratedTransaction, flattenHydratedTransactions } from "@xyo-network/xl1-protocol-sdk";
226
+ import { Mutex } from "async-mutex";
227
+
228
+ // src/modules/StepIdentityPayload.ts
229
+ import { AsObjectFactory } from "@xylabs/object";
230
+ import { isPayloadOfZodType } from "@xyo-network/payload-model";
231
+ import { StepIdentityZod } from "@xyo-network/xl1-rpc";
232
+ var StepIdentitySchema = "network.xyo.chain.step.identity";
233
+ var isStepIdentityPayload = isPayloadOfZodType(StepIdentityZod, StepIdentitySchema);
234
+ var asStepIdentityPayload = AsObjectFactory.create(isStepIdentityPayload);
235
+
236
+ // src/modules/ChainRewardsClaimSentinel.ts
237
+ var ChainRewardsClaimSentinelConfigSchema = "network.xyo.sentinel.chain.rewards.claim.config";
235
238
  var scope = "reward-escrow";
236
- var params = z2.object({
237
- address: EthAddressFromStringZod
238
- });
239
- var body = PayloadZodLoose;
240
- var response = SignedHydratedTransactionZod;
241
- var validateRequest = requestHandlerValidator({
242
- params,
243
- body,
244
- response
245
- });
246
- var getStakesForStaker = /* @__PURE__ */ __name(async (viewer2, stakerAddress) => {
247
- const stakes = await viewer2.stakesByStaker(stakerAddress);
248
- return stakes;
249
- }, "getStakesForStaker");
250
- var getRewardsForStake = /* @__PURE__ */ __name(async (viewer2, stakes, fromBlock = 0, toBlock) => {
251
- if (isUndefined(toBlock)) {
252
- toBlock = await viewer2.currentBlockNumber();
253
- }
254
- const rewards = [];
255
- for (const stake of stakes) {
256
- const { id } = stake;
257
- const reward = await viewer2.networkStakeStepRewardsForPosition(id, [
258
- fromBlock,
259
- toBlock
260
- ]);
261
- rewards.push(reward);
239
+ var RewardableSteps2 = [
240
+ 3,
241
+ 4,
242
+ 5,
243
+ 6,
244
+ 7,
245
+ 8
246
+ ];
247
+ var ChainRewardsClaimSentinel = class extends AbstractSentinel {
248
+ static {
249
+ __name(this, "ChainRewardsClaimSentinel");
262
250
  }
263
- return rewards;
264
- }, "getRewardsForStake");
265
- var sumNetworkStakeStepRewards = /* @__PURE__ */ __name((records) => {
266
- const totals = {};
267
- for (const record of records) {
268
- for (const [key, [first]] of Object.entries(record)) {
269
- if (isUndefined(totals[key])) {
270
- totals[key] = 0n;
271
- }
272
- totals[key] += first;
273
- }
251
+ static configSchemas = [
252
+ ChainRewardsClaimSentinelConfigSchema
253
+ ];
254
+ static defaultConfigSchema = ChainRewardsClaimSentinelConfigSchema;
255
+ _reportMutex = new Mutex();
256
+ get gateway() {
257
+ return this.params.gateway;
274
258
  }
275
- return totals;
276
- }, "sumNetworkStakeStepRewards");
277
- var postClaim = {
278
- method: "post",
279
- path: "/rewards/claim/:address",
280
- handlers: validateRequest(async (req, res) => {
281
- const { config } = req.app;
282
- const { address } = req.params;
283
- const stakerAddress = asAddress(address);
284
- if (!stakerAddress) {
285
- res.status(400);
286
- return;
259
+ async reportHandler(payloads) {
260
+ if (this._reportMutex.isLocked()) {
261
+ this.logger?.debug(`ChainRewardsClaimSentinel [${this.id}] is already running, skipping divine [${Date.now()}]`);
262
+ return [];
287
263
  }
288
- const account2 = await getAccountFromConfig(config);
289
- const viewer2 = getViewerFromConfig(config);
290
- const stakes = await getStakesForStaker(viewer2, stakerAddress);
291
- if (stakes.length > 0) {
292
- const currentBlock = await viewer2.currentBlockNumber();
293
- const rewards = await getRewardsForStake(viewer2, stakes, 0, currentBlock);
294
- if (Object.keys(rewards).length > 0) {
295
- const totalRewards = sumNetworkStakeStepRewards(rewards);
296
- const totalTransfers = [];
297
- for (const [stepIdentityString, accrued] of Object.entries(totalRewards)) {
298
- const stepIdentity = asStepIdentity(stepIdentityString);
299
- if (isUndefined(stepIdentity)) continue;
300
- const stepRewardsAddress = completedStepRewardAddress(stepIdentity);
301
- const receiveAddress = derivedReceiveAddress(stakerAddress, scope);
302
- const claimed = await viewer2.transferPairBalance([
303
- stepRewardsAddress,
304
- receiveAddress
305
- ]);
306
- const unclaimed = accrued - claimed;
307
- if (unclaimed <= 0n) continue;
308
- const transferPayload = createTransferPayload(stepRewardsAddress, {
309
- [receiveAddress]: unclaimed
310
- });
311
- transferPayload.context = {
312
- address: stakerAddress,
313
- scope
264
+ return await this._reportMutex.runExclusive(async () => {
265
+ const response3 = [];
266
+ if (isUndefined(payloads) || payloads.length === 0) {
267
+ await this.claimAllSteps();
268
+ } else {
269
+ const stepIdentities = payloads.filter(isStepIdentityPayload).map((p) => {
270
+ const { step, block: blockNumber } = p;
271
+ const block = asXL1BlockNumber(blockNumber);
272
+ return {
273
+ step,
274
+ block
314
275
  };
315
- totalTransfers.push(transferPayload);
276
+ }).filter((stepIdentity) => RewardableSteps2.includes(stepIdentity.step));
277
+ for (const stepIdentity of stepIdentities) {
278
+ const result = await this.claimStepIdentity(stepIdentity);
279
+ if (isDefined4(result)) response3.push(...flattenHydratedTransaction(result));
316
280
  }
317
- if (totalTransfers.length > 0) {
318
- const chainId = await viewer2.chainId();
319
- const tx = await buildTransaction(chainId, totalTransfers, [], account2, currentBlock, currentBlock + 1e3);
320
- res.json(tx);
321
- return;
281
+ }
282
+ return response3;
283
+ });
284
+ }
285
+ calculateAddressDistributions(rewardsByStaker, balance) {
286
+ const addressClaims = {};
287
+ const totalRewards = Object.values(rewardsByStaker).reduce((acc, val) => acc + val, 0n);
288
+ for (const [staker, amount] of Object.entries(rewardsByStaker)) {
289
+ if (amount <= 0n) continue;
290
+ const reward = balance * amount / totalRewards;
291
+ if (reward <= 0n) continue;
292
+ const receiveAddress = derivedReceiveAddress(toAddress(staker), scope);
293
+ addressClaims[receiveAddress] = reward;
294
+ }
295
+ const totalClaimed = Object.values(addressClaims).reduce((acc, val) => acc + val, 0n);
296
+ assertEx(totalClaimed <= balance, () => "Total claimed exceeds claimable balance");
297
+ const unclaimed = balance - totalClaimed;
298
+ if (unclaimed > 0n) {
299
+ addressClaims[XYO_STEP_REWARD_ADDRESS] = unclaimed;
300
+ }
301
+ return addressClaims;
302
+ }
303
+ async claimAllSteps() {
304
+ const results = [];
305
+ const connection = await this.gateway.connection();
306
+ const signer = await this.gateway.signer();
307
+ const { viewer: viewer2, runner } = connection;
308
+ if (isDefined4(viewer2) && isDefined4(runner) && isDefined4(signer)) {
309
+ for (const step of RewardableSteps2) {
310
+ const from = 0;
311
+ const to = await viewer2.currentBlockNumber();
312
+ const range = [
313
+ asXL1BlockNumber(from),
314
+ asXL1BlockNumber(to)
315
+ ];
316
+ const stepIdentities = blockRangeSteps(range, [
317
+ step
318
+ ]);
319
+ for (const stepIdentity of stepIdentities) {
320
+ const result = await this.claimStepIdentity(stepIdentity);
321
+ if (isDefined4(result)) results.push(result);
322
322
  }
323
323
  }
324
324
  }
325
- res.status(204);
326
- })
325
+ return flattenHydratedTransactions(results);
326
+ }
327
+ async claimStepIdentity(stepIdentity) {
328
+ const connection = await this.gateway.connection();
329
+ const signer = await this.gateway.signer();
330
+ const { viewer: viewer2, runner } = connection;
331
+ if (isDefined4(viewer2) && isDefined4(runner) && isDefined4(signer)) {
332
+ const stepRewardsAddress = completedStepRewardAddress(stepIdentity);
333
+ const balance = await viewer2.accountBalance(stepRewardsAddress);
334
+ if (balance > 0n) {
335
+ const rewardsByStaker = await viewer2.networkStakeStepRewardPoolRewards(stepIdentity);
336
+ const addressDistributions = this.calculateAddressDistributions(rewardsByStaker, balance);
337
+ const tx = await this.submitRewardDistributionTransaction(stepRewardsAddress, addressDistributions, stepIdentity, this.gateway);
338
+ return tx;
339
+ }
340
+ }
341
+ }
342
+ async submitRewardDistributionTransaction(stepRewardsAddress, addressDistributions, step, gateway) {
343
+ const transferPayload = createTransferPayload(stepRewardsAddress, addressDistributions);
344
+ transferPayload.context = {
345
+ step
346
+ };
347
+ const connection = await gateway.connection();
348
+ const viewer2 = assertEx(connection.viewer, () => "Viewer is not defined in gateway connection");
349
+ const chainId = await viewer2.chainId();
350
+ const currentBlock = await viewer2.currentBlockNumber();
351
+ const result = await gateway.addPayloadsToChain?.([
352
+ transferPayload
353
+ ], [], {
354
+ chain: chainId,
355
+ nbf: currentBlock,
356
+ exp: currentBlock + 1e3
357
+ });
358
+ if (isDefined4(result)) return result[1];
359
+ }
327
360
  };
328
361
 
329
362
  // src/server/routes/rewardRedemption/routeDefinitions/routes/claimRange.ts
330
- import { assertEx as assertEx2 } from "@xylabs/assert";
331
- import { toAddress } from "@xylabs/hex";
332
- import { isDefined as isDefined5 } from "@xylabs/typeof";
333
- import { blockRangeSteps, createTransferPayload as createTransferPayload2 } from "@xyo-network/chain-protocol";
334
- import { asXL1BlockNumber, XYO_STEP_REWARD_ADDRESS } from "@xyo-network/xl1-protocol";
335
- import { buildTransaction as buildTransaction2, completedStepRewardAddress as completedStepRewardAddress2, derivedReceiveAddress as derivedReceiveAddress2 } from "@xyo-network/xl1-protocol-sdk";
336
- import { SignedHydratedTransactionZod as SignedHydratedTransactionZod2 } from "@xyo-network/xl1-rpc";
337
- import { z as z3 } from "zod";
338
- var scope2 = "reward-escrow";
339
- var query = z3.object({
340
- fromBlock: z3.coerce.number().int().optional(),
341
- toBlock: z3.coerce.number().int().optional()
363
+ var query = z2.object({
364
+ fromBlock: z2.coerce.number().int().min(0).optional(),
365
+ toBlock: z2.coerce.number().int().min(0).optional(),
366
+ step: z2.coerce.number().min(Math.min(...RewardableSteps)).max(Math.max(...RewardableSteps)).int().optional().default(3)
342
367
  });
343
- var response2 = SignedHydratedTransactionZod2.optional();
344
- var validateRequest2 = requestHandlerValidator({
368
+ var response = z2.array(PayloadZodLoose);
369
+ var validateRequest = requestHandlerValidator({
345
370
  query,
346
- response: response2
371
+ response
347
372
  });
348
- var calculateAddressDistributions = /* @__PURE__ */ __name((stakers, balance) => {
349
- const addressClaims = {};
350
- const totalRewards = Object.values(stakers).reduce((acc, val) => acc + val, 0n);
351
- for (const [staker, amount] of Object.entries(stakers)) {
352
- const reward = balance * amount / totalRewards;
353
- const stakerAddress = toAddress(staker);
354
- const receiveAddress = derivedReceiveAddress2(stakerAddress, scope2);
355
- addressClaims[receiveAddress] = reward;
356
- }
357
- const totalClaimed = Object.values(addressClaims).reduce((acc, val) => acc + val, 0n);
358
- assertEx2(totalClaimed <= balance, () => "Total claimed exceeds claimable balance");
359
- const unclaimed = balance - totalClaimed;
360
- if (unclaimed > 0n) {
361
- addressClaims[XYO_STEP_REWARD_ADDRESS] = unclaimed;
362
- }
363
- return addressClaims;
364
- }, "calculateAddressDistributions");
365
- var createRewardDistributionTransaction = /* @__PURE__ */ __name(async (stepRewardsAddress, addressDistributions, viewer2, config) => {
366
- const transferPayload = createTransferPayload2(stepRewardsAddress, addressDistributions);
367
- const chainId = await viewer2.chainId();
368
- const account2 = await getAccountFromConfig(config);
369
- const currentBlock = await viewer2.currentBlockNumber();
370
- const tx = await buildTransaction2(chainId, [
371
- transferPayload
372
- ], [], account2, currentBlock, currentBlock + 1e3);
373
- return tx;
374
- }, "createRewardDistributionTransaction");
373
+ var getChainRewardsClaimSentinel = /* @__PURE__ */ __name(async (node) => {
374
+ const mod = await node.resolve("XYORewardRedemptionNode:ChainRewardsClaimSentinel");
375
+ const sentinel = asSentinelInstance(mod);
376
+ return assertEx2(sentinel, () => "ChainRewardsClaimSentinel not found on node");
377
+ }, "getChainRewardsClaimSentinel");
375
378
  var postClaimRange = {
376
379
  method: "post",
377
380
  path: "/rewards/claimRange",
378
- handlers: validateRequest2(async (req, res) => {
379
- const { config } = req.app;
380
- const { fromBlock, toBlock } = req.query;
381
+ handlers: validateRequest(async (req, res) => {
382
+ const { config, node } = req.app;
383
+ const mod = await getChainRewardsClaimSentinel(node);
384
+ const { fromBlock, toBlock, step } = z2.parse(query, req.query);
381
385
  const viewer2 = getViewerFromConfig(config);
382
- const from = isDefined5(fromBlock) ? Number(fromBlock) : 0;
383
- const to = isDefined5(toBlock) ? Number(toBlock) : await viewer2.currentBlockNumber();
386
+ const from = isDefined5(fromBlock) ? fromBlock : 0;
387
+ const currentBlock = await viewer2.currentBlockNumber();
388
+ const to = isDefined5(toBlock) ? Math.min(toBlock, currentBlock) : currentBlock;
389
+ if (to <= from) {
390
+ res.status(400);
391
+ res.json([]);
392
+ return;
393
+ }
384
394
  const range = [
385
- asXL1BlockNumber(from),
386
- asXL1BlockNumber(to)
395
+ asXL1BlockNumber2(from),
396
+ asXL1BlockNumber2(to)
387
397
  ];
388
- const stepIdentities = blockRangeSteps(range, RewardableSteps);
398
+ const stepIdentities = blockRangeSteps2(range, [
399
+ step
400
+ ]);
401
+ const results = [];
389
402
  for (const stepIdentity of stepIdentities) {
390
- const stepRewardsAddress = completedStepRewardAddress2(stepIdentity);
391
- const balance = await viewer2.accountBalance(stepRewardsAddress);
392
- if (balance > 0n) {
393
- const stakers = await viewer2.networkStakeStepRewardPoolRewards(stepIdentity);
394
- const addressDistributions = calculateAddressDistributions(stakers, balance);
395
- const tx = await createRewardDistributionTransaction(stepRewardsAddress, addressDistributions, viewer2, config);
396
- res.status(200);
397
- res.json(tx);
398
- }
403
+ const stepIdentityPayload = new PayloadBuilder2({
404
+ schema: StepIdentitySchema
405
+ }).fields(stepIdentity).build();
406
+ const result = await mod.report([
407
+ stepIdentityPayload
408
+ ]);
409
+ results.push(...result);
399
410
  }
400
- res.status(204);
401
- res.json();
411
+ res.status(200);
412
+ res.json(results);
402
413
  })
403
414
  };
404
415
 
405
416
  // src/server/routes/rewardRedemption/routeDefinitions/routes/redeem.ts
406
- import { PayloadZodLoose as PayloadZodLoose2 } from "@xyo-network/payload-model";
407
- import { z as z4 } from "zod";
408
- var params2 = z4.object({
409
- address: EthAddressFromStringZod
410
- });
411
- var body2 = PayloadZodLoose2;
412
- var response3 = PayloadZodLoose2;
413
- var validateRequest3 = requestHandlerValidator({
414
- params: params2,
415
- body: body2,
416
- response: response3
417
+ import { assertEx as assertEx3 } from "@xylabs/assert";
418
+ import { hexToBigInt, toAddress as toAddress2, toHex } from "@xylabs/hex";
419
+ import { isDefined as isDefined6 } from "@xylabs/typeof";
420
+ import { createTransferPayload as createTransferPayload2 } from "@xyo-network/chain-protocol";
421
+ import { HDWallet } from "@xyo-network/wallet";
422
+ import { verifyEIP712Message } from "@xyo-network/xl1-protocol-sdk";
423
+ import { HttpRpcXyoConnection, MemoryXyoGateway, MemoryXyoSigner, SignedHydratedTransactionZod } from "@xyo-network/xl1-rpc";
424
+ import { z as z3 } from "zod";
425
+ var body = z3.any();
426
+ var response2 = SignedHydratedTransactionZod;
427
+ var validateRequest2 = requestHandlerValidator({
428
+ body,
429
+ response: response2
417
430
  });
431
+ var getGateway = /* @__PURE__ */ __name(async (config) => {
432
+ const { mnemonic, chainRpcApiUrl: endpoint } = config.rewardRedemptionApi;
433
+ const account = await HDWallet.fromPhrase(assertEx3(mnemonic, () => ""));
434
+ const signer = new MemoryXyoSigner(account);
435
+ const connection = new HttpRpcXyoConnection({
436
+ endpoint,
437
+ account
438
+ });
439
+ const gateway = new MemoryXyoGateway(signer, connection);
440
+ return gateway;
441
+ }, "getGateway");
442
+ var submitRewardDistributionTransaction = /* @__PURE__ */ __name(async (to, amount, nbf, exp, gateway) => {
443
+ const signer = assertEx3(await gateway.signer(), () => "Signer is not defined in gateway");
444
+ const from = await signer.address();
445
+ const transferPayload = createTransferPayload2(from, {
446
+ [to]: hexToBigInt(toHex(amount))
447
+ });
448
+ const connection = await gateway.connection();
449
+ const viewer2 = assertEx3(connection.viewer, () => "Viewer is not defined in gateway connection");
450
+ const chain = await viewer2.chainId();
451
+ const result = await gateway.addPayloadsToChain?.([
452
+ transferPayload
453
+ ], [], {
454
+ chain,
455
+ nbf,
456
+ exp
457
+ });
458
+ if (isDefined6(result)) return result[1];
459
+ }, "submitRewardDistributionTransaction");
460
+ var parseConfirmedClaimValues = /* @__PURE__ */ __name((values) => {
461
+ return {
462
+ from: toAddress2(values.from),
463
+ to: values["To XL1 Address"],
464
+ amount: values["XL1 Amount (Hex)"],
465
+ nbf: values["XL1 Not before block"],
466
+ exp: values["XL1 Not after block"]
467
+ };
468
+ }, "parseConfirmedClaimValues");
418
469
  var postRedeem = {
419
470
  method: "post",
420
- path: "/rewards/redeem/:address",
421
- handlers: validateRequest3(async (req, res) => {
422
- const { body: body3 } = req;
423
- await Promise.resolve();
424
- const bridgeObservation = {
425
- schema: "network.xyo.test"
426
- };
427
- res.json(bridgeObservation);
471
+ path: "/rewards/redeem",
472
+ handlers: validateRequest2(async (req, res) => {
473
+ const { config } = req.app;
474
+ const { body: body2 } = req;
475
+ const [payload, signature] = body2;
476
+ const valid = await verifyEIP712Message(payload, signature);
477
+ if (valid) {
478
+ const values = payload.values;
479
+ const { from, to, amount, nbf, exp } = parseConfirmedClaimValues(values);
480
+ assertEx3(toAddress2(signature.address) === toAddress2(from), () => "Signature does not match from address");
481
+ const gateway = await getGateway(config);
482
+ const receiver = toAddress2(to);
483
+ const tx = await submitRewardDistributionTransaction(receiver, amount, nbf, exp, gateway);
484
+ if (isDefined6(tx)) {
485
+ res.status(200);
486
+ res.json(tx);
487
+ } else {
488
+ res.status(500);
489
+ res.json();
490
+ }
491
+ } else {
492
+ res.status(404);
493
+ res.json();
494
+ }
428
495
  })
429
496
  };
430
497
 
@@ -432,7 +499,7 @@ var postRedeem = {
432
499
  var getRouteDefinitions = /* @__PURE__ */ __name(() => {
433
500
  return [
434
501
  postClaimRange,
435
- postClaim,
502
+ // postClaim,
436
503
  postRedeem
437
504
  ];
438
505
  }, "getRouteDefinitions");
@@ -474,22 +541,23 @@ var getApp = /* @__PURE__ */ __name((node, config) => {
474
541
  }, "getApp");
475
542
 
476
543
  // src/server/server.ts
477
- import { assertEx as assertEx3 } from "@xylabs/assert";
478
- import { isDefined as isDefined7, isString } from "@xylabs/typeof";
544
+ import { assertEx as assertEx4 } from "@xylabs/assert";
545
+ import { isDefined as isDefined8, isString } from "@xylabs/typeof";
479
546
  import { boot } from "@xyo-network/bios";
480
- import { HDWallet as HDWallet2 } from "@xyo-network/wallet";
547
+ import { HDWallet as HDWallet3 } from "@xyo-network/wallet";
481
548
 
482
549
  // src/manifest/getLocator.ts
483
- import { isDefined as isDefined6 } from "@xylabs/typeof";
550
+ import { isDefined as isDefined7 } from "@xylabs/typeof";
484
551
  import { MemoryArchivist } from "@xyo-network/archivist-memory";
485
552
  import { MongoDBArchivistV2 } from "@xyo-network/archivist-mongodb";
486
553
  import { ViewArchivist } from "@xyo-network/archivist-view";
487
- import { ArchivistSyncDiviner } from "@xyo-network/chain-modules";
488
554
  import { initTelemetry } from "@xyo-network/chain-telemetry";
489
555
  import { AbstractModule, LoggerModuleStatusReporter } from "@xyo-network/module-abstract";
490
556
  import { ModuleFactoryLocator } from "@xyo-network/module-factory-locator";
491
557
  import { MemorySentinel } from "@xyo-network/sentinel-memory";
558
+ import { HDWallet as HDWallet2 } from "@xyo-network/wallet";
492
559
  import { hasMongoConfig } from "@xyo-network/xl1-protocol-sdk";
560
+ import { HttpRpcXyoConnection as HttpRpcXyoConnection2, MemoryXyoGateway as MemoryXyoGateway2, MemoryXyoSigner as MemoryXyoSigner2 } from "@xyo-network/xl1-rpc";
493
561
  var getLocator = /* @__PURE__ */ __name(async (context) => {
494
562
  const { config, logger } = context;
495
563
  const { otlpEndpoint } = config.telemetry?.otel ?? {};
@@ -504,7 +572,7 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
504
572
  port: 9465
505
573
  }
506
574
  });
507
- if (isDefined6(logger)) AbstractModule.defaultLogger = logger;
575
+ if (isDefined7(logger)) AbstractModule.defaultLogger = logger;
508
576
  const statusReporter = logger ? new LoggerModuleStatusReporter(logger) : void 0;
509
577
  const locator = new ModuleFactoryLocator();
510
578
  const mongoConfig = config.storage?.mongo;
@@ -517,13 +585,13 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
517
585
  dbPassword,
518
586
  dbUserName
519
587
  };
520
- const params3 = {
588
+ const params = {
521
589
  meterProvider,
522
590
  payloadSdkConfig,
523
591
  statusReporter,
524
592
  traceProvider
525
593
  };
526
- locator.register(MongoDBArchivistV2.factory(params3), void 0, true);
594
+ locator.register(MongoDBArchivistV2.factory(params), void 0, true);
527
595
  }
528
596
  locator.register(MemoryArchivist.factory({
529
597
  traceProvider,
@@ -540,13 +608,27 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
540
608
  meterProvider,
541
609
  statusReporter
542
610
  }));
543
- locator.register(ArchivistSyncDiviner.factory({
611
+ await registerChainRewardsClaimSentinel(locator, config, traceProvider, meterProvider, statusReporter);
612
+ return locator;
613
+ }, "getLocator");
614
+ var registerChainRewardsClaimSentinel = /* @__PURE__ */ __name(async (locator, config, traceProvider, meterProvider, statusReporter) => {
615
+ const { mnemonic, chainRpcApiUrl: endpoint } = config.rewardRedemptionApi;
616
+ const walletPromise = isDefined7(mnemonic) ? HDWallet2.fromPhrase(mnemonic) : HDWallet2.random();
617
+ const account = await walletPromise;
618
+ const signer = new MemoryXyoSigner2(account);
619
+ const connection = new HttpRpcXyoConnection2({
620
+ endpoint,
621
+ account
622
+ });
623
+ const gateway = new MemoryXyoGateway2(signer, connection);
624
+ const chainRewardsClaimSentinelParams = {
625
+ gateway,
544
626
  traceProvider,
545
627
  meterProvider,
546
628
  statusReporter
547
- }));
548
- return locator;
549
- }, "getLocator");
629
+ };
630
+ locator.register(ChainRewardsClaimSentinel.factory(chainRewardsClaimSentinelParams));
631
+ }, "registerChainRewardsClaimSentinel");
550
632
 
551
633
  // src/manifest/getNode.ts
552
634
  import { ManifestWrapper } from "@xyo-network/manifest-wrapper";
@@ -576,6 +658,13 @@ var node_default = {
576
658
  },
577
659
  schema: "network.xyo.archivist.config"
578
660
  }
661
+ },
662
+ {
663
+ config: {
664
+ accountPath: "1/1'/2'",
665
+ name: "ChainRewardsClaimSentinel",
666
+ schema: "network.xyo.sentinel.chain.rewards.claim.config"
667
+ }
579
668
  }
580
669
  ],
581
670
  public: [
@@ -638,20 +727,20 @@ var getSeedPhrase = /* @__PURE__ */ __name(async (bios, config, logger) => {
638
727
  if (isString(mnemonic)) {
639
728
  seedPhrase = mnemonic;
640
729
  } else {
641
- seedPhrase = HDWallet2.generateMnemonic();
730
+ seedPhrase = HDWallet3.generateMnemonic();
642
731
  logger?.log("[Bridge] No mnemonic provided, using random mnemonic. This is not recommended for production use.");
643
732
  logger?.log(`[Bridge] Mnemonic: ${seedPhrase}`);
644
733
  }
645
734
  await bios.seedPhraseStore.set("os", seedPhrase);
646
735
  }
647
- return assertEx3(await bios.seedPhraseStore.get("os"), () => "Unable to acquire mnemonic from bios");
736
+ return assertEx4(await bios.seedPhraseStore.get("os"), () => "Unable to acquire mnemonic from bios");
648
737
  }, "getSeedPhrase");
649
738
  var getServer = /* @__PURE__ */ __name(async (context) => {
650
739
  const { logger, config } = context;
651
740
  const { port, mnemonic } = config.rewardRedemptionApi;
652
741
  const bios = await boot();
653
- const seedPhrase = isDefined7(mnemonic) ? mnemonic : await getSeedPhrase(bios, config, logger);
654
- const wallet = await HDWallet2.fromPhrase(seedPhrase);
742
+ const seedPhrase = isDefined8(mnemonic) ? mnemonic : await getSeedPhrase(bios, config, logger);
743
+ const wallet = await HDWallet3.fromPhrase(seedPhrase);
655
744
  const nodeContext = {
656
745
  wallet,
657
746
  logger,