@helium/blockchain-api 0.1.1 → 0.1.3

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 (52) hide show
  1. package/README.md +24 -2
  2. package/package.json +31 -31
  3. package/types/README.md +24 -2
  4. package/types/generated/index.d.mts +2481 -0
  5. package/types/generated/index.d.ts +2481 -0
  6. package/types/generated/index.js +723 -0
  7. package/types/generated/index.mjs +614 -0
  8. package/types/index.ts +11 -8
  9. package/src/server/api/errors.ts +0 -152
  10. package/src/server/api/index.ts +0 -40
  11. package/src/server/api/procedures.ts +0 -144
  12. package/src/server/api/routers/fiat/router.ts +0 -709
  13. package/src/server/api/routers/fiat/schemas.ts +0 -157
  14. package/src/server/api/routers/health/router.ts +0 -41
  15. package/src/server/api/routers/hotspots/procedures/claimRewards.ts +0 -258
  16. package/src/server/api/routers/hotspots/procedures/createSplit.ts +0 -253
  17. package/src/server/api/routers/hotspots/procedures/deleteSplit.ts +0 -156
  18. package/src/server/api/routers/hotspots/procedures/getHotspots.ts +0 -31
  19. package/src/server/api/routers/hotspots/procedures/getPendingRewards.ts +0 -44
  20. package/src/server/api/routers/hotspots/procedures/getSplit.ts +0 -88
  21. package/src/server/api/routers/hotspots/procedures/transferHotspot.ts +0 -204
  22. package/src/server/api/routers/hotspots/procedures/updateRewardsDestination.ts +0 -201
  23. package/src/server/api/routers/hotspots/router.ts +0 -30
  24. package/src/server/api/routers/hotspots/schemas.ts +0 -182
  25. package/src/server/api/routers/swap/procedures/getInstructions.ts +0 -152
  26. package/src/server/api/routers/swap/procedures/getQuote.ts +0 -53
  27. package/src/server/api/routers/swap/procedures/getTokens.ts +0 -88
  28. package/src/server/api/routers/swap/router.ts +0 -15
  29. package/src/server/api/routers/swap/schemas.ts +0 -96
  30. package/src/server/api/routers/tokens/procedures/createHntAccount.ts +0 -87
  31. package/src/server/api/routers/tokens/procedures/getBalances.ts +0 -27
  32. package/src/server/api/routers/tokens/procedures/transfer.ts +0 -159
  33. package/src/server/api/routers/tokens/router.ts +0 -15
  34. package/src/server/api/routers/tokens/schemas.ts +0 -80
  35. package/src/server/api/routers/transactions/procedures/get.ts +0 -46
  36. package/src/server/api/routers/transactions/procedures/getByPayer.ts +0 -111
  37. package/src/server/api/routers/transactions/procedures/getByPayerAndTag.ts +0 -119
  38. package/src/server/api/routers/transactions/procedures/resubmit.ts +0 -68
  39. package/src/server/api/routers/transactions/procedures/submit.ts +0 -216
  40. package/src/server/api/routers/transactions/router.ts +0 -21
  41. package/src/server/api/routers/transactions/schemas.ts +0 -119
  42. package/src/server/api/routers/webhooks/router.ts +0 -75
  43. package/src/server/api/routers/welcomePacks/procedures/claim.ts +0 -157
  44. package/src/server/api/routers/welcomePacks/procedures/create.ts +0 -247
  45. package/src/server/api/routers/welcomePacks/procedures/deletePack.ts +0 -118
  46. package/src/server/api/routers/welcomePacks/procedures/get.ts +0 -36
  47. package/src/server/api/routers/welcomePacks/procedures/getByAddress.ts +0 -26
  48. package/src/server/api/routers/welcomePacks/procedures/invite.ts +0 -44
  49. package/src/server/api/routers/welcomePacks/procedures/list.ts +0 -27
  50. package/src/server/api/routers/welcomePacks/router.ts +0 -27
  51. package/src/server/api/routers/welcomePacks/schemas.ts +0 -135
  52. package/src/server/api/schemas.ts +0 -281
@@ -1,15 +0,0 @@
1
- import { getTokens } from "./procedures/getTokens";
2
- import { getQuote } from "./procedures/getQuote";
3
- import { getInstructions } from "./procedures/getInstructions";
4
-
5
- /**
6
- * Swap router - handles token swap operations via Jupiter.
7
- */
8
- export const swapRouter = {
9
- /** Get list of verified tokens available for swapping */
10
- getTokens,
11
- /** Get a quote for swapping tokens */
12
- getQuote,
13
- /** Get swap transaction instructions */
14
- getInstructions,
15
- };
@@ -1,96 +0,0 @@
1
- import { z } from "zod";
2
-
3
- // ============================================================================
4
- // Input Schemas
5
- // ============================================================================
6
-
7
- export const GetTokensInputSchema = z.object({
8
- limit: z.coerce.number().int().min(1).max(100).default(50),
9
- });
10
-
11
- export const GetQuoteInputSchema = z.object({
12
- inputMint: z.string().min(1),
13
- outputMint: z.string().min(1),
14
- amount: z.string().min(1),
15
- swapMode: z.enum(["ExactIn", "ExactOut"]).default("ExactIn"),
16
- slippageBps: z.coerce.number().min(0).max(10000).default(50),
17
- });
18
-
19
- export const QuoteResponseSchema = z
20
- .object({
21
- inputMint: z.string(),
22
- inAmount: z.string(),
23
- outputMint: z.string(),
24
- outAmount: z.string(),
25
- otherAmountThreshold: z.string(),
26
- swapMode: z.string(),
27
- slippageBps: z.number(),
28
- platformFee: z.unknown().optional(),
29
- priceImpactPct: z.string(),
30
- routePlan: z.array(z.unknown()),
31
- contextSlot: z.number().optional(),
32
- timeTaken: z.number().optional(),
33
- })
34
- .passthrough(); // Allow additional fields from Jupiter that we don't explicitly define
35
-
36
- export const GetInstructionsInputSchema = z.object({
37
- quoteResponse: QuoteResponseSchema,
38
- userPublicKey: z.string().min(1),
39
- destinationTokenAccount: z.string().optional(),
40
- dynamicComputeUnitLimit: z.boolean().default(true),
41
- prioritizationFeeLamports: z
42
- .object({
43
- priorityLevelWithMaxLamports: z.object({
44
- maxLamports: z.number().default(1000000),
45
- priorityLevel: z.enum(["low", "medium", "high"]).default("medium"),
46
- }),
47
- })
48
- .optional(),
49
- });
50
-
51
- // ============================================================================
52
- // Output Schemas
53
- // ============================================================================
54
-
55
- export const TokenSchema = z.object({
56
- address: z.string(),
57
- symbol: z.string(),
58
- name: z.string(),
59
- decimals: z.number(),
60
- logoURI: z.string().optional(),
61
- tags: z.array(z.string()).optional(),
62
- });
63
-
64
- export const TokenListOutputSchema = z.object({
65
- tokens: z.array(TokenSchema),
66
- });
67
-
68
- export const TransactionMetadataSchema = z
69
- .object({
70
- type: z.string(),
71
- description: z.string(),
72
- })
73
- .catchall(z.unknown());
74
-
75
- export const TransactionItemSchema = z.object({
76
- serializedTransaction: z.string(),
77
- metadata: TransactionMetadataSchema.optional(),
78
- });
79
-
80
- export const TransactionDataSchema = z.object({
81
- transactions: z.array(TransactionItemSchema),
82
- parallel: z.boolean(),
83
- tag: z.string().optional(),
84
- });
85
-
86
- // ============================================================================
87
- // Type Exports
88
- // ============================================================================
89
-
90
- export type GetTokensInput = z.infer<typeof GetTokensInputSchema>;
91
- export type GetQuoteInput = z.infer<typeof GetQuoteInputSchema>;
92
- export type GetInstructionsInput = z.infer<typeof GetInstructionsInputSchema>;
93
- export type QuoteResponse = z.infer<typeof QuoteResponseSchema>;
94
- export type Token = z.infer<typeof TokenSchema>;
95
- export type TokenListOutput = z.infer<typeof TokenListOutputSchema>;
96
- export type TransactionData = z.infer<typeof TransactionDataSchema>;
@@ -1,87 +0,0 @@
1
- import { publicProcedure } from "../../../procedures";
2
- import {
3
- CreateHntAccountInputSchema,
4
- CreateHntAccountOutputSchema,
5
- } from "../schemas";
6
- import { ORPCError } from "@orpc/server";
7
- import { PublicKey, Connection } from "@solana/web3.js";
8
- import {
9
- createAssociatedTokenAccountIdempotentInstruction,
10
- getAssociatedTokenAddressSync,
11
- } from "@solana/spl-token";
12
- import {
13
- populateMissingDraftInfo,
14
- toVersionedTx,
15
- withPriorityFees,
16
- HNT_MINT,
17
- } from "@helium/spl-utils";
18
- import { env } from "@/lib/env";
19
-
20
- /**
21
- * Create an HNT token account for a wallet.
22
- */
23
- export const createHntAccount = publicProcedure
24
- .route({ method: "POST", path: "/tokens/{walletAddress}/hnt-account/create" })
25
- .input(CreateHntAccountInputSchema)
26
- .output(CreateHntAccountOutputSchema)
27
- .errors({
28
- BAD_REQUEST: { message: "Wallet address is required" },
29
- })
30
- .handler(async ({ input }) => {
31
- const { walletAddress } = input;
32
-
33
- if (!walletAddress) {
34
- throw new ORPCError("BAD_REQUEST", {
35
- message: "Wallet address is required",
36
- });
37
- }
38
-
39
- const wallet = new PublicKey(walletAddress);
40
-
41
- // Get the associated token account address for HNT
42
- const hntTokenAccount = getAssociatedTokenAddressSync(
43
- HNT_MINT,
44
- wallet,
45
- true, // allowOwnerOffCurve
46
- );
47
-
48
- // Create instruction to create the associated token account
49
- const createAccountInstruction =
50
- createAssociatedTokenAccountIdempotentInstruction(
51
- wallet, // payer
52
- hntTokenAccount, // associated token account
53
- wallet, // owner
54
- HNT_MINT, // mint
55
- );
56
-
57
- const draft = {
58
- instructions: [createAccountInstruction],
59
- feePayer: wallet,
60
- addressLookupTableAddresses: [] as PublicKey[],
61
- };
62
-
63
- const connection = new Connection(env.SOLANA_RPC_URL);
64
- const tx = toVersionedTx(
65
- await populateMissingDraftInfo(connection, {
66
- ...draft,
67
- instructions: await withPriorityFees({ ...draft, connection }),
68
- }),
69
- );
70
-
71
- return {
72
- transactionData: {
73
- transactions: [
74
- {
75
- serializedTransaction: Buffer.from(tx.serialize()).toString(
76
- "base64",
77
- ),
78
- metadata: {
79
- type: "hnt-token-account",
80
- description: "Create HNT token account",
81
- },
82
- },
83
- ],
84
- parallel: false,
85
- },
86
- };
87
- });
@@ -1,27 +0,0 @@
1
- import { publicProcedure } from "../../../procedures";
2
- import { GetBalancesInputSchema, TokenBalanceDataSchema } from "../schemas";
3
- import { getTokenBalances } from "@/lib/queries/tokens";
4
- import { ORPCError } from "@orpc/server";
5
-
6
- /**
7
- * Get token balances for a wallet address.
8
- */
9
- export const getBalances = publicProcedure
10
- .route({ method: "GET", path: "/tokens/{walletAddress}" })
11
- .input(GetBalancesInputSchema)
12
- .output(TokenBalanceDataSchema)
13
- .errors({
14
- BAD_REQUEST: { message: "Wallet address is required" },
15
- })
16
- .handler(async ({ input }) => {
17
- const { walletAddress } = input;
18
-
19
- if (!walletAddress) {
20
- throw new ORPCError("BAD_REQUEST", {
21
- message: "Wallet address is required",
22
- });
23
- }
24
-
25
- const tokenBalances = await getTokenBalances({ walletAddress });
26
- return tokenBalances;
27
- });
@@ -1,159 +0,0 @@
1
- import { publicProcedure } from "../../../procedures";
2
- import { TransferInputSchema, TransferOutputSchema } from "../schemas";
3
- import { ORPCError } from "@orpc/server";
4
- import { PublicKey, SystemProgram, Connection } from "@solana/web3.js";
5
- import {
6
- createAssociatedTokenAccountIdempotentInstruction,
7
- createTransferCheckedInstruction,
8
- getAssociatedTokenAddressSync,
9
- } from "@solana/spl-token";
10
- import {
11
- populateMissingDraftInfo,
12
- toVersionedTx,
13
- withPriorityFees,
14
- } from "@helium/spl-utils";
15
- import {
16
- generateTransactionTag,
17
- TRANSACTION_TYPES,
18
- } from "@/lib/utils/transaction-tags";
19
- import { TOKEN_MINTS } from "@/lib/constants/tokens";
20
-
21
- /**
22
- * Create a transaction to transfer tokens (SOL or SPL tokens).
23
- */
24
- export const transfer = publicProcedure
25
- .route({ method: "POST", path: "/tokens/{walletAddress}/transfer" })
26
- .input(TransferInputSchema)
27
- .output(TransferOutputSchema)
28
- .errors({
29
- BAD_REQUEST: { message: "Invalid request" },
30
- INSUFFICIENT_FUNDS: { message: "Insufficient balance" },
31
- })
32
- .handler(async ({ input, errors }) => {
33
- const { walletAddress, mint, destination, amount, decimals } = input;
34
-
35
- if (!destination || !amount) {
36
- throw errors.BAD_REQUEST({
37
- message: "Destination and amount are required",
38
- });
39
- }
40
-
41
- const feePayer = new PublicKey(walletAddress);
42
- const destKey = new PublicKey(destination);
43
- const connection = new Connection(process.env.SOLANA_RPC_URL!);
44
-
45
- const isSol = !mint || mint === "SOL" || mint === TOKEN_MINTS.WSOL;
46
-
47
- const instructions: (
48
- | ReturnType<typeof SystemProgram.transfer>
49
- | ReturnType<typeof createAssociatedTokenAccountIdempotentInstruction>
50
- | ReturnType<typeof createTransferCheckedInstruction>
51
- )[] = [];
52
-
53
- if (isSol) {
54
- // Native SOL transfer
55
- const normalized = (amount || "").trim();
56
- const lamports = Math.round(parseFloat(normalized) * 1e9);
57
- if (!Number.isFinite(lamports) || lamports <= 0) {
58
- throw errors.BAD_REQUEST({ message: "Amount must be greater than 0" });
59
- }
60
-
61
- // Ensure sender has sufficient SOL balance before creating tx
62
- const balance = await connection.getBalance(feePayer);
63
- if (balance < lamports) {
64
- throw errors.INSUFFICIENT_FUNDS({
65
- message: "Insufficient SOL balance",
66
- data: {
67
- balance,
68
- required: lamports,
69
- },
70
- });
71
- }
72
-
73
- instructions.push(
74
- SystemProgram.transfer({
75
- fromPubkey: feePayer,
76
- toPubkey: destKey,
77
- lamports,
78
- }),
79
- );
80
- } else {
81
- if (!decimals || decimals < 0) {
82
- throw errors.BAD_REQUEST({ message: "Token decimals are required" });
83
- }
84
-
85
- const mintKey = new PublicKey(mint!);
86
- const senderAta = getAssociatedTokenAddressSync(mintKey, feePayer, true);
87
- const destAta = getAssociatedTokenAddressSync(mintKey, destKey, true);
88
- const normalized = (amount || "").trim();
89
- const rawAmount = Math.round(
90
- parseFloat(normalized) * Math.pow(10, decimals),
91
- );
92
-
93
- if (!Number.isFinite(rawAmount) || rawAmount <= 0) {
94
- throw errors.BAD_REQUEST({ message: "Amount must be greater than 0" });
95
- }
96
-
97
- // Ensure destination ATA exists
98
- instructions.push(
99
- createAssociatedTokenAccountIdempotentInstruction(
100
- feePayer,
101
- destAta,
102
- destKey,
103
- mintKey,
104
- ),
105
- );
106
-
107
- instructions.push(
108
- createTransferCheckedInstruction(
109
- senderAta,
110
- mintKey,
111
- destAta,
112
- feePayer,
113
- rawAmount,
114
- decimals,
115
- ),
116
- );
117
- }
118
-
119
- const draft = {
120
- instructions,
121
- feePayer,
122
- addressLookupTableAddresses: [] as PublicKey[],
123
- };
124
-
125
- const tx = toVersionedTx(
126
- await populateMissingDraftInfo(connection, {
127
- ...draft,
128
- instructions: await withPriorityFees({ ...draft, connection }),
129
- }),
130
- );
131
-
132
- const tokenSymbol = isSol ? "SOL" : "Token";
133
-
134
- const tag = generateTransactionTag({
135
- type: TRANSACTION_TYPES.TOKEN_TRANSFER,
136
- walletAddress,
137
- destination,
138
- mint: mint || "SOL",
139
- amount,
140
- });
141
-
142
- return {
143
- transactionData: {
144
- transactions: [
145
- {
146
- serializedTransaction: Buffer.from(tx.serialize()).toString(
147
- "base64",
148
- ),
149
- metadata: {
150
- type: "token_transfer",
151
- description: `Transfer ${tokenSymbol}`,
152
- },
153
- },
154
- ],
155
- parallel: false,
156
- tag,
157
- },
158
- };
159
- });
@@ -1,15 +0,0 @@
1
- import { getBalances } from "./procedures/getBalances";
2
- import { transfer } from "./procedures/transfer";
3
- import { createHntAccount } from "./procedures/createHntAccount";
4
-
5
- /**
6
- * Tokens router - handles all token-related operations.
7
- */
8
- export const tokensRouter = {
9
- /** Get token balances for a wallet */
10
- getBalances,
11
- /** Create a transaction to transfer tokens */
12
- transfer,
13
- /** Create an HNT token account for a wallet */
14
- createHntAccount,
15
- };
@@ -1,80 +0,0 @@
1
- import { z } from "zod";
2
-
3
- // ============================================================================
4
- // Input Schemas
5
- // ============================================================================
6
-
7
- export const GetBalancesInputSchema = z.object({
8
- walletAddress: z.string().min(32),
9
- });
10
-
11
- export const TransferInputSchema = z.object({
12
- walletAddress: z.string().min(32),
13
- mint: z.string().nullable().optional(),
14
- destination: z.string().min(32),
15
- amount: z.string(),
16
- decimals: z.number().optional(),
17
- });
18
-
19
- export const CreateHntAccountInputSchema = z.object({
20
- walletAddress: z.string().min(32),
21
- });
22
-
23
- // ============================================================================
24
- // Output Schemas
25
- // ============================================================================
26
-
27
- export const TokenAccountSchema = z.object({
28
- mint: z.string(),
29
- address: z.string(),
30
- balance: z.string(),
31
- decimals: z.number(),
32
- uiAmount: z.number(),
33
- symbol: z.string().optional(),
34
- name: z.string().optional(),
35
- logoURI: z.string().optional(),
36
- priceUsd: z.number().optional(),
37
- balanceUsd: z.number().optional(),
38
- });
39
-
40
- export const TokenBalanceDataSchema = z.object({
41
- totalBalanceUsd: z.number(),
42
- solBalance: z.number(),
43
- solBalanceUsd: z.number(),
44
- tokens: z.array(TokenAccountSchema),
45
- });
46
-
47
- export const TransactionMetadataSchema = z
48
- .object({
49
- type: z.string(),
50
- description: z.string(),
51
- })
52
- .catchall(z.unknown());
53
-
54
- export const TransactionItemSchema = z.object({
55
- serializedTransaction: z.string(),
56
- metadata: TransactionMetadataSchema.optional(),
57
- });
58
-
59
- export const TransactionDataSchema = z.object({
60
- transactions: z.array(TransactionItemSchema),
61
- parallel: z.boolean(),
62
- tag: z.string().optional(),
63
- });
64
-
65
- export const TransferOutputSchema = z.object({
66
- transactionData: TransactionDataSchema,
67
- });
68
-
69
- export const CreateHntAccountOutputSchema = z.object({
70
- transactionData: TransactionDataSchema,
71
- });
72
-
73
- // ============================================================================
74
- // Type Exports
75
- // ============================================================================
76
-
77
- export type GetBalancesInput = z.infer<typeof GetBalancesInputSchema>;
78
- export type TransferInput = z.infer<typeof TransferInputSchema>;
79
- export type CreateHntAccountInput = z.infer<typeof CreateHntAccountInputSchema>;
80
- export type TokenBalanceData = z.infer<typeof TokenBalanceDataSchema>;
@@ -1,46 +0,0 @@
1
- import { publicProcedure } from "../../../procedures";
2
- import { GetInputSchema, BatchStatusOutputSchema } from "../schemas";
3
- import { ORPCError } from "@orpc/server";
4
- import PendingTransaction from "@/lib/models/pending-transaction";
5
- import TransactionBatch from "@/lib/models/transaction-batch";
6
- import { checkAndUpdateBatchStatus } from "@/lib/utils/transaction-status-checker";
7
-
8
- /**
9
- * Get transaction batch status by ID.
10
- */
11
- export const get = publicProcedure
12
- .route({ method: "GET", path: "/transactions/{id}" })
13
- .input(GetInputSchema)
14
- .output(BatchStatusOutputSchema)
15
- .errors({
16
- NOT_FOUND: { message: "Batch not found" },
17
- })
18
- .handler(async ({ input, errors }) => {
19
- const { id, commitment } = input;
20
-
21
- // First check if this is a batch ID
22
- const batch = await TransactionBatch.findByPk(id, {
23
- include: [
24
- {
25
- model: PendingTransaction,
26
- as: "transactions",
27
- },
28
- ],
29
- });
30
-
31
- if (!batch) {
32
- throw errors.NOT_FOUND({ message: "Batch not found" });
33
- }
34
-
35
- const result = await checkAndUpdateBatchStatus(batch, commitment);
36
-
37
- return {
38
- batchId: batch.id,
39
- status: result.batchStatus,
40
- submissionType: batch.submissionType,
41
- parallel: batch.parallel,
42
- transactions: result.transactionStatuses,
43
- jitoBundleId: batch.jitoBundleId,
44
- jitoBundleStatus: result.jitoBundleStatus,
45
- };
46
- });
@@ -1,111 +0,0 @@
1
- import { publicProcedure } from "../../../procedures";
2
- import { GetByPayerInputSchema, PayerBatchesOutputSchema } from "../schemas";
3
- import { ORPCError } from "@orpc/server";
4
- import PendingTransaction from "@/lib/models/pending-transaction";
5
- import TransactionBatch, { BatchStatus } from "@/lib/models/transaction-batch";
6
- import { connectToDb } from "@/lib/utils/db";
7
- import { Op } from "sequelize";
8
-
9
- /**
10
- * Get transaction batches by payer address.
11
- */
12
- export const getByPayer = publicProcedure
13
- .route({ method: "GET", path: "/transactions/payer/{payer}" })
14
- .input(GetByPayerInputSchema)
15
- .output(PayerBatchesOutputSchema)
16
- .errors({
17
- BAD_REQUEST: { message: "Invalid request" },
18
- })
19
- .handler(async ({ input, errors }) => {
20
- const { payer, page, limit, status } = input;
21
-
22
- await connectToDb();
23
-
24
- if (!payer) {
25
- throw errors.BAD_REQUEST({ message: "Payer is required" });
26
- }
27
-
28
- // Parse status filter
29
- let statusFilter: BatchStatus[] = ["pending"];
30
-
31
- if (status) {
32
- const requestedStatuses = status
33
- .split(",")
34
- .map((s) => s.trim()) as BatchStatus[];
35
- const validStatuses: BatchStatus[] = [
36
- "pending",
37
- "confirmed",
38
- "failed",
39
- "expired",
40
- "partial",
41
- ];
42
- statusFilter = requestedStatuses.filter((s) => validStatuses.includes(s));
43
-
44
- if (statusFilter.length === 0) {
45
- throw errors.BAD_REQUEST({
46
- message:
47
- "Invalid status filter. Valid values: pending, confirmed, failed, expired, partial",
48
- });
49
- }
50
- }
51
-
52
- const offset = (page - 1) * limit;
53
-
54
- // Build where clause
55
- const whereClause = {
56
- payer,
57
- status: {
58
- [Op.in]: statusFilter,
59
- },
60
- };
61
-
62
- // Get total count for pagination
63
- const total = await TransactionBatch.count({
64
- where: whereClause,
65
- });
66
-
67
- // Find paginated transaction batches for the payer
68
- const batches = await TransactionBatch.findAll({
69
- where: whereClause,
70
- include: [
71
- {
72
- model: PendingTransaction,
73
- as: "transactions",
74
- },
75
- ],
76
- order: [["createdAt", "DESC"]],
77
- limit,
78
- offset,
79
- });
80
-
81
- const batchSummaries = batches.map((batch) => ({
82
- batchId: batch.id,
83
- tag: batch.tag || undefined,
84
- status: batch.status,
85
- submissionType: batch.submissionType,
86
- parallel: batch.parallel,
87
- createdAt: batch.createdAt.toISOString(),
88
- updatedAt: batch.updatedAt.toISOString(),
89
- transactions:
90
- (
91
- batch as unknown as { transactions?: { metadata?: unknown }[] }
92
- ).transactions?.map((tx) => ({
93
- metadata: tx.metadata as
94
- | { type: string; description: string }
95
- | undefined,
96
- })) || [],
97
- }));
98
-
99
- const totalPages = Math.ceil(total / limit);
100
-
101
- return {
102
- payer,
103
- batches: batchSummaries,
104
- pagination: {
105
- page,
106
- limit,
107
- total,
108
- totalPages,
109
- },
110
- };
111
- });