@railbeam/stardorm-api-contract 0.0.1 → 0.0.2

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.
package/src/chat-api.ts CHANGED
@@ -1,6 +1,24 @@
1
1
  import { z } from "zod";
2
2
  import { handlerActionIdSchema } from "./handlers.js";
3
3
 
4
+ /**
5
+ * Recursively convert JSON `null` to `undefined` so optional Zod fields accept
6
+ * model output and Mongo payloads (`intro: null` otherwise fails chat parse).
7
+ */
8
+ export function stripJsonNulls(value: unknown): unknown {
9
+ if (value === null) return undefined;
10
+ if (Array.isArray(value)) return value.map(stripJsonNulls);
11
+ if (typeof value === "object") {
12
+ const out: Record<string, unknown> = {};
13
+ for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
14
+ const stripped = stripJsonNulls(v);
15
+ if (stripped !== undefined) out[k] = stripped;
16
+ }
17
+ return out;
18
+ }
19
+ return value;
20
+ }
21
+
4
22
  export const stardormChatRichRowSchema = z.object({
5
23
  label: z.string(),
6
24
  value: z.string(),
@@ -80,6 +98,56 @@ export const stardormChatRichBlockSchema = z.discriminatedUnion("type", [
80
98
  title: z.string().min(1),
81
99
  rows: stardormChatRichRows,
82
100
  }),
101
+ z.object({
102
+ type: z.literal("swap_checkout_form"),
103
+ title: z.string().min(1).max(200),
104
+ intro: z.string().max(2000).optional(),
105
+ supportedAssets: z.array(x402SupportedAssetSchema).min(1).max(24),
106
+ networks: z
107
+ .array(
108
+ z.object({
109
+ id: z.string().min(1).max(64),
110
+ label: z.string().min(1).max(120),
111
+ }),
112
+ )
113
+ .max(16)
114
+ .optional(),
115
+ /** Default V3 fee tier when the form does not override (500, 3000, 10000). */
116
+ defaultPoolFee: z.union([z.literal(500), z.literal(3000), z.literal(10000)]).optional(),
117
+ }),
118
+ z.object({
119
+ type: z.literal("marketplace_hire"),
120
+ title: z.string().min(1).max(200),
121
+ intro: z.string().max(2000).optional(),
122
+ specialistName: z.string().min(1).max(80),
123
+ specialistAgentKey: z.string().min(1).max(64),
124
+ category: z
125
+ .enum(["Payments", "Taxes", "Reports", "DeFi", "Compliance", "General"])
126
+ .optional(),
127
+ capability: z.string().min(1).max(400).optional(),
128
+ userTask: z.string().max(500).optional(),
129
+ /** App path to open the marketplace (default `/marketplace`). */
130
+ marketplacePath: z.string().min(1).max(256).default("/marketplace"),
131
+ /** App path to the specialist profile when known (e.g. `/agents/chain-2`). */
132
+ agentProfilePath: z.string().min(1).max(256).optional(),
133
+ requiredHandler: z.string().min(1).max(64).optional(),
134
+ }),
135
+ z.object({
136
+ type: z.literal("transfer_checkout_form"),
137
+ title: z.string().min(1).max(200),
138
+ intro: z.string().max(2000).optional(),
139
+ supportedAssets: z.array(x402SupportedAssetSchema).min(1).max(24),
140
+ networks: z
141
+ .array(
142
+ z.object({
143
+ id: z.string().min(1).max(64),
144
+ label: z.string().min(1).max(120),
145
+ }),
146
+ )
147
+ .max(16)
148
+ .optional(),
149
+ defaultTo: z.string().max(66).optional(),
150
+ }),
83
151
  ]);
84
152
 
85
153
  export type StardormChatRichBlock = z.infer<typeof stardormChatRichBlockSchema>;
@@ -114,18 +182,30 @@ export const stardormChatAttachmentSchema = z.object({
114
182
 
115
183
  export type StardormChatAttachment = z.infer<typeof stardormChatAttachmentSchema>;
116
184
 
117
- export const stardormChatSuccessSchema = z.object({
185
+ /** JSON APIs sometimes emit `null` for omitted optional fields. */
186
+ function nullishOptional<T extends z.ZodTypeAny>(schema: T) {
187
+ return z.preprocess((v) => (v === null ? undefined : v), schema);
188
+ }
189
+
190
+ const stardormChatSuccessObjectSchema = z.object({
118
191
  agentKey: z.string().min(1),
119
192
  reply: z.string(),
120
- structured: stardormChatStructuredSchema.optional(),
193
+ structured: nullishOptional(stardormChatStructuredSchema.optional()),
121
194
  /** Structured card rows for the client (model or server-generated). */
122
- rich: stardormChatRichBlockSchema.optional(),
195
+ rich: nullishOptional(stardormChatRichBlockSchema.optional()),
123
196
  /** Files the server uploaded to 0G Storage from the user's chat turn (echoed for immediate render). */
124
- attachments: z.array(stardormChatAttachmentSchema).optional(),
197
+ attachments: nullishOptional(
198
+ z.array(stardormChatAttachmentSchema).optional(),
199
+ ),
125
200
  compute: stardormChatComputeSchema,
126
201
  });
127
202
 
128
- export type StardormChatSuccess = z.infer<typeof stardormChatSuccessSchema>;
203
+ export const stardormChatSuccessSchema = z.preprocess(
204
+ (v) => (v != null && typeof v === "object" ? stripJsonNulls(v) : v),
205
+ stardormChatSuccessObjectSchema,
206
+ );
207
+
208
+ export type StardormChatSuccess = z.infer<typeof stardormChatSuccessObjectSchema>;
129
209
 
130
210
  export const stardormChatClientErrorSchema = z.object({
131
211
  error: z.string().min(1),
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import { chatHistoryMessageSchema } from "./conversation.js";
3
+
4
+ /** Lightweight invalidation hint (legacy clients refetch the thread). */
5
+ export const conversationSyncThreadSchema = z.object({
6
+ v: z.literal(1),
7
+ op: z.literal("thread"),
8
+ conversationId: z.string().min(1),
9
+ });
10
+
11
+ /** Full message rows for in-place TanStack cache updates (no refetch). */
12
+ export const conversationSyncThreadMessagesSchema = z.object({
13
+ v: z.literal(1),
14
+ op: z.literal("thread_messages"),
15
+ conversationId: z.string().min(1),
16
+ messages: z.array(chatHistoryMessageSchema).min(1),
17
+ });
18
+
19
+ export const conversationSyncConversationsSchema = z.object({
20
+ v: z.literal(1),
21
+ op: z.literal("conversations"),
22
+ });
23
+
24
+ export const conversationSyncConversationDeletedSchema = z.object({
25
+ v: z.literal(1),
26
+ op: z.literal("conversation_deleted"),
27
+ conversationId: z.string().min(1),
28
+ });
29
+
30
+ export const conversationSyncPayloadSchema = z.discriminatedUnion("op", [
31
+ conversationSyncThreadSchema,
32
+ conversationSyncThreadMessagesSchema,
33
+ conversationSyncConversationsSchema,
34
+ conversationSyncConversationDeletedSchema,
35
+ ]);
36
+
37
+ export type ConversationSyncThreadPayload = z.infer<typeof conversationSyncThreadSchema>;
38
+ export type ConversationSyncThreadMessagesPayload = z.infer<
39
+ typeof conversationSyncThreadMessagesSchema
40
+ >;
41
+ export type ConversationSyncPayload = z.infer<typeof conversationSyncPayloadSchema>;
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { handlerActionIdSchema } from "./handlers.js";
3
- import { stardormChatRichBlockSchema } from "./chat-api.js";
3
+ import { stripJsonNulls, stardormChatRichBlockSchema } from "./chat-api.js";
4
+ import { chatHandlerResultSchema } from "./handler-result.js";
4
5
 
5
6
  export const chatHistoryQuerySchema = z.object({
6
7
  limit: z.coerce.number().int().min(1).max(100).default(40),
@@ -66,8 +67,15 @@ export const chatHistoryMessageSchema = z.object({
66
67
  content: z.string(),
67
68
  createdAt: z.number(),
68
69
  attachments: z.array(chatHistoryAttachmentSchema).optional(),
69
- rich: stardormChatRichBlockSchema.optional(),
70
+ rich: z
71
+ .preprocess(
72
+ (v) => (v != null && typeof v === "object" ? stripJsonNulls(v) : v),
73
+ stardormChatRichBlockSchema.optional(),
74
+ )
75
+ .optional(),
70
76
  handlerCta: chatHistoryHandlerCtaSchema.optional(),
77
+ /** Wallet or server outcome for this bubble (tx hash, checkout ids, …). */
78
+ result: chatHandlerResultSchema.optional(),
71
79
  followUp: chatFollowUpSchema.optional(),
72
80
  model: z.string().optional(),
73
81
  verified: z.boolean().optional(),
@@ -90,28 +90,6 @@ export const creditCardsListResponseSchema = z.object({
90
90
 
91
91
  export type CreditCardsListResponse = z.infer<typeof creditCardsListResponseSchema>;
92
92
 
93
- export const creditCardFundBodySchema = z
94
- .object({
95
- amountCents: z.coerce.number().int().min(1).max(100_000_000),
96
- fundingTxHash: z
97
- .string()
98
- .regex(/^0x[a-fA-F0-9]{64}$/)
99
- .optional(),
100
- fundingChainId: z.coerce.number().int().positive().optional(),
101
- })
102
- .refine(
103
- (d) =>
104
- (d.fundingTxHash == null && d.fundingChainId == null) ||
105
- (d.fundingTxHash != null && d.fundingChainId != null),
106
- {
107
- message:
108
- "fundingTxHash and fundingChainId must both be provided or both omitted",
109
- path: ["fundingTxHash"],
110
- },
111
- );
112
-
113
- export type CreditCardFundBody = z.infer<typeof creditCardFundBodySchema>;
114
-
115
93
  export const creditCardFundQuoteQuerySchema = z.object({
116
94
  amountCents: z.coerce.number().int().min(1).max(100_000_000),
117
95
  });
@@ -120,11 +98,18 @@ export type CreditCardFundQuoteQuery = z.infer<
120
98
  typeof creditCardFundQuoteQuerySchema
121
99
  >;
122
100
 
123
- export const creditCardFundQuoteOffChainSchema = z.object({
101
+ /** USDC.e x402 fund on 0G mainnet (1 USD cent = 10_000 base units). */
102
+ export const creditCardFundQuoteX402Schema = z.object({
124
103
  onchainFundingRequired: z.literal(false),
104
+ chainId: z.number().int(),
105
+ recipient: z.string().min(1),
106
+ usdcAsset: z.string().min(1),
107
+ usdcAmountBaseUnits: z.string().regex(/^\d+$/),
108
+ usdcDecimals: z.number().int().min(0).max(18),
125
109
  });
126
110
 
127
- export const creditCardFundQuoteOnChainSchema = z.object({
111
+ /** Native 0G transfer to treasury (used when x402 is not configured). */
112
+ export const creditCardFundQuoteNativeSchema = z.object({
128
113
  onchainFundingRequired: z.literal(true),
129
114
  chainId: z.number().int(),
130
115
  recipient: z.string().min(1),
@@ -134,14 +119,20 @@ export const creditCardFundQuoteOnChainSchema = z.object({
134
119
  nativeDecimals: z.number().int().min(0).max(18),
135
120
  });
136
121
 
137
- export const creditCardFundQuoteResponseSchema = z.discriminatedUnion(
122
+ export const creditCardFundQuoteSchema = z.discriminatedUnion(
138
123
  "onchainFundingRequired",
139
- [creditCardFundQuoteOffChainSchema, creditCardFundQuoteOnChainSchema],
124
+ [creditCardFundQuoteX402Schema, creditCardFundQuoteNativeSchema],
140
125
  );
141
126
 
142
- export type CreditCardFundQuoteResponse = z.infer<
143
- typeof creditCardFundQuoteResponseSchema
144
- >;
127
+ export type CreditCardFundQuote = z.infer<typeof creditCardFundQuoteSchema>;
128
+ export type CreditCardFundQuoteX402 = z.infer<typeof creditCardFundQuoteX402Schema>;
129
+ export type CreditCardFundQuoteNative = z.infer<typeof creditCardFundQuoteNativeSchema>;
130
+
131
+ /** @deprecated Use {@link CreditCardFundQuote} */
132
+ export type CreditCardFundQuoteResponse = CreditCardFundQuote;
133
+
134
+ /** @deprecated Use {@link creditCardFundQuoteSchema} */
135
+ export const creditCardFundQuoteResponseSchema = creditCardFundQuoteSchema;
145
136
 
146
137
  export const creditCardWithdrawBodySchema = z.object({
147
138
  amountCents: z.coerce.number().int().min(1).max(100_000_000),
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+
3
+ /** One UTC daily rollup row (Mongo `FinancialSnapshot` → chat / dashboard). */
4
+ export const financialSnapshotDailyRowSchema = z.object({
5
+ bucketStart: z.string(),
6
+ bucket: z.string(),
7
+ revenueUsd: z.number().optional(),
8
+ walletBalance0g: z.number().optional(),
9
+ monthlySpend0g: z.number().optional(),
10
+ spendByCategory: z.record(z.number()).default({}),
11
+ });
12
+
13
+ export type FinancialSnapshotDailyRow = z.infer<typeof financialSnapshotDailyRowSchema>;
14
+
15
+ /** Query for GET `/users/me/financial-snapshots`. */
16
+ export const meFinancialSnapshotsQuerySchema = z.object({
17
+ days: z.coerce.number().int().min(7).max(90).default(30),
18
+ });
19
+
20
+ export type MeFinancialSnapshotsQuery = z.infer<typeof meFinancialSnapshotsQuerySchema>;
21
+
22
+ export const financialSnapshotsListResponseSchema = z.object({
23
+ items: z.array(financialSnapshotDailyRowSchema),
24
+ });
25
+
26
+ export type FinancialSnapshotsListResponse = z.infer<
27
+ typeof financialSnapshotsListResponseSchema
28
+ >;
@@ -0,0 +1,65 @@
1
+ import { z } from "zod";
2
+
3
+ /** Outcome after a wallet-signed handler CTA (transfer, swap, …). */
4
+ export const chatHandlerWalletTxResultSchema = z.object({
5
+ kind: z.literal("wallet_tx"),
6
+ status: z.enum(["submitted", "confirmed", "failed"]),
7
+ txHash: z
8
+ .string()
9
+ .regex(/^0x[a-fA-F0-9]{64}$/)
10
+ .optional(),
11
+ error: z.string().max(2000).optional(),
12
+ network: z.string().min(1).max(64).optional(),
13
+ chainId: z.number().int().positive().optional(),
14
+ handler: z.string().min(1).max(64).optional(),
15
+ updatedAt: z.number().int().positive(),
16
+ });
17
+
18
+ export type ChatHandlerWalletTxResult = z.infer<typeof chatHandlerWalletTxResultSchema>;
19
+
20
+ /** Outcome after `execute-handler` (server job, checkout created, draft recorded, …). */
21
+ export const chatHandlerServerResultSchema = z.object({
22
+ kind: z.literal("server"),
23
+ status: z.enum(["completed", "failed"]).default("completed"),
24
+ data: z.record(z.string(), z.unknown()).optional(),
25
+ updatedAt: z.number().int().positive(),
26
+ });
27
+
28
+ export type ChatHandlerServerResult = z.infer<typeof chatHandlerServerResultSchema>;
29
+
30
+ export const chatHandlerResultSchema = z.discriminatedUnion("kind", [
31
+ chatHandlerWalletTxResultSchema,
32
+ chatHandlerServerResultSchema,
33
+ ]);
34
+
35
+ export type ChatHandlerResult = z.infer<typeof chatHandlerResultSchema>;
36
+
37
+ export const patchChatMessageResultBodySchema = z.object({
38
+ result: chatHandlerResultSchema,
39
+ });
40
+
41
+ export type PatchChatMessageResultBody = z.infer<typeof patchChatMessageResultBodySchema>;
42
+
43
+ export const patchChatMessageResultResponseSchema = z.object({
44
+ ok: z.literal(true),
45
+ messageId: z.string().min(1),
46
+ result: chatHandlerResultSchema,
47
+ rich: z
48
+ .object({
49
+ type: z.literal("tx"),
50
+ title: z.string(),
51
+ rows: z
52
+ .array(
53
+ z.object({
54
+ label: z.string(),
55
+ value: z.string(),
56
+ }),
57
+ )
58
+ .optional(),
59
+ })
60
+ .optional(),
61
+ });
62
+
63
+ export type PatchChatMessageResultResponse = z.infer<
64
+ typeof patchChatMessageResultResponseSchema
65
+ >;
package/src/handlers.ts CHANGED
@@ -23,6 +23,10 @@ export const HANDLER_ACTION_IDS = [
23
23
  "draft_erc20_transfer",
24
24
  /** Confirms an NFT (ERC-721 / ERC-1155) transfer draft; user signs in their wallet / Beam Send. */
25
25
  "draft_nft_transfer",
26
+ /** Confirms a Uniswap V3 single-hop swap on 0G mainnet; user signs approve + router in wallet. */
27
+ "draft_token_swap",
28
+ /** Direct the user to hire a marketplace specialist for a task this agent cannot run. */
29
+ "suggest_marketplace_hire",
26
30
  ] as const;
27
31
 
28
32
  export type HandlerActionId = (typeof HANDLER_ACTION_IDS)[number];
package/src/index.ts CHANGED
@@ -60,6 +60,7 @@ export {
60
60
  stardormChatStructuredSchema,
61
61
  stardormChatComputeSchema,
62
62
  stardormChatRichRowSchema,
63
+ stripJsonNulls,
63
64
  stardormChatRichBlockSchema,
64
65
  x402SupportedAssetSchema,
65
66
  stardormChatSuccessSchema,
@@ -98,6 +99,16 @@ export {
98
99
  type CreateConversationBody,
99
100
  type DeleteConversationResponse,
100
101
  } from "./conversation.js";
102
+ export {
103
+ conversationSyncPayloadSchema,
104
+ conversationSyncThreadSchema,
105
+ conversationSyncThreadMessagesSchema,
106
+ conversationSyncConversationsSchema,
107
+ conversationSyncConversationDeletedSchema,
108
+ type ConversationSyncPayload,
109
+ type ConversationSyncThreadPayload,
110
+ type ConversationSyncThreadMessagesPayload,
111
+ } from "./conversation-sync.js";
101
112
  export {
102
113
  agentOnchainFeedbackItemSchema,
103
114
  agentFeedbacksQuerySchema,
@@ -118,6 +129,14 @@ export {
118
129
  type MePaymentRequestsQuery,
119
130
  type PaymentRequestsListResponse,
120
131
  } from "./payment-request.js";
132
+ export {
133
+ financialSnapshotDailyRowSchema,
134
+ meFinancialSnapshotsQuerySchema,
135
+ financialSnapshotsListResponseSchema,
136
+ type FinancialSnapshotDailyRow,
137
+ type MeFinancialSnapshotsQuery,
138
+ type FinancialSnapshotsListResponse,
139
+ } from "./financial-snapshot.js";
121
140
  export {
122
141
  onRampFormCtaParamsSchema,
123
142
  onRampFormNetworkOptionSchema,
@@ -149,10 +168,10 @@ export {
149
168
  creditCardPublicSchema,
150
169
  creditCardSensitiveDetailsSchema,
151
170
  creditCardsListResponseSchema,
152
- creditCardFundBodySchema,
153
171
  creditCardFundQuoteQuerySchema,
154
- creditCardFundQuoteOffChainSchema,
155
- creditCardFundQuoteOnChainSchema,
172
+ creditCardFundQuoteSchema,
173
+ creditCardFundQuoteX402Schema,
174
+ creditCardFundQuoteNativeSchema,
156
175
  creditCardFundQuoteResponseSchema,
157
176
  creditCardWithdrawBodySchema,
158
177
  type CreateCreditCardInput,
@@ -160,7 +179,9 @@ export {
160
179
  type CreditCardPublic,
161
180
  type CreditCardSensitiveDetails,
162
181
  type CreditCardsListResponse,
163
- type CreditCardFundBody,
182
+ type CreditCardFundQuote,
183
+ type CreditCardFundQuoteX402,
184
+ type CreditCardFundQuoteNative,
164
185
  type CreditCardFundQuoteQuery,
165
186
  type CreditCardFundQuoteResponse,
166
187
  type CreditCardWithdrawBody,
@@ -190,3 +211,34 @@ export {
190
211
  type DraftErc20TransferInput,
191
212
  type DraftNftTransferInput,
192
213
  } from "./transfer-drafts.js";
214
+ export {
215
+ swapFormCtaParamsSchema,
216
+ swapFormNetworkOptionSchema,
217
+ draftTokenSwapInputSchema,
218
+ isSwapFormCtaParams,
219
+ type SwapFormCtaParams,
220
+ type DraftTokenSwapInput,
221
+ } from "./swap.js";
222
+ export {
223
+ transferFormCtaParamsSchema,
224
+ transferFormNetworkOptionSchema,
225
+ isTransferFormCtaParams,
226
+ type TransferFormCtaParams,
227
+ } from "./transfer-form.js";
228
+ export {
229
+ suggestMarketplaceHireInputSchema,
230
+ marketplaceSpecialistAgentKeySchema,
231
+ type SuggestMarketplaceHireInput,
232
+ } from "./marketplace-hire.js";
233
+ export {
234
+ chatHandlerResultSchema,
235
+ chatHandlerWalletTxResultSchema,
236
+ chatHandlerServerResultSchema,
237
+ patchChatMessageResultBodySchema,
238
+ patchChatMessageResultResponseSchema,
239
+ type ChatHandlerResult,
240
+ type ChatHandlerWalletTxResult,
241
+ type ChatHandlerServerResult,
242
+ type PatchChatMessageResultBody,
243
+ type PatchChatMessageResultResponse,
244
+ } from "./handler-result.js";
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+ import { handlerActionIdSchema } from "./handlers.js";
3
+
4
+ /** Known Beam catalog specialist keys (subgraph / marketplace). */
5
+ export const marketplaceSpecialistAgentKeySchema = z
6
+ .string()
7
+ .min(1)
8
+ .max(64)
9
+ .regex(/^[a-z0-9][a-z0-9-]*$/i);
10
+
11
+ export const suggestMarketplaceHireInputSchema = z.object({
12
+ specialistAgentKey: marketplaceSpecialistAgentKeySchema,
13
+ specialistName: z.string().min(1).max(80).optional(),
14
+ category: z
15
+ .enum(["Payments", "Taxes", "Reports", "DeFi", "Compliance", "General"])
16
+ .optional(),
17
+ /** One line: what the specialist runs for the user (handler names ok). */
18
+ capability: z.string().min(1).max(400).optional(),
19
+ /** Short description of what the user was trying to do. */
20
+ userTask: z.string().min(1).max(500).optional(),
21
+ intro: z.string().max(2000).optional(),
22
+ /** Optional handler the user needs after hiring (for display only). */
23
+ requiredHandler: handlerActionIdSchema.optional(),
24
+ });
25
+
26
+ export type SuggestMarketplaceHireInput = z.infer<typeof suggestMarketplaceHireInputSchema>;
@@ -67,6 +67,8 @@ export const publicPaymentRequestSchema = z.object({
67
67
  /** Set when status is `paid` (on-chain settlement recorded). */
68
68
  txHash: z.string().optional(),
69
69
  paidByWallet: z.string().optional(),
70
+ /** When true, checkout can settle via x402 facilitator + wallet-signed payload. */
71
+ facilitatorSettlement: z.boolean().optional(),
70
72
  });
71
73
 
72
74
  export type PublicPaymentRequest = z.infer<typeof publicPaymentRequestSchema>;
@@ -74,12 +76,16 @@ export type PublicPaymentRequest = z.infer<typeof publicPaymentRequestSchema>;
74
76
  /** Query for GET `/users/me/payment-requests`. */
75
77
  export const mePaymentRequestsQuerySchema = z.object({
76
78
  limit: z.coerce.number().int().min(1).max(50).default(20),
79
+ /** 1-based page index (sorted by `updatedAt` descending). */
80
+ page: z.coerce.number().int().min(1).default(1),
77
81
  });
78
82
 
79
83
  export type MePaymentRequestsQuery = z.infer<typeof mePaymentRequestsQuerySchema>;
80
84
 
81
85
  export const paymentRequestsListResponseSchema = z.object({
82
86
  items: z.array(publicPaymentRequestSchema),
87
+ /** Total rows matching the wallet filter (ignores pagination). */
88
+ total: z.number().int().min(0),
83
89
  });
84
90
 
85
91
  export type PaymentRequestsListResponse = z.infer<
package/src/swap.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { z } from "zod";
2
+ import { x402SupportedAssetSchema } from "./chat-api.js";
3
+
4
+ export const swapFormNetworkOptionSchema = z.object({
5
+ id: z.string().min(1).max(64),
6
+ label: z.string().min(1).max(120),
7
+ });
8
+
9
+ /** Persisted on the chat CTA row until the user submits the swap form. */
10
+ export const swapFormCtaParamsSchema = z.object({
11
+ _swapForm: z.literal(true),
12
+ supportedAssets: z.array(x402SupportedAssetSchema).min(1).max(24),
13
+ networks: z.array(swapFormNetworkOptionSchema).max(16).optional(),
14
+ intro: z.string().max(2000).optional(),
15
+ /** Default Uniswap V3 pool fee tier (500, 3000, or 10000). */
16
+ defaultPoolFee: z.union([z.literal(500), z.literal(3000), z.literal(10000)]).optional(),
17
+ });
18
+
19
+ export type SwapFormCtaParams = z.infer<typeof swapFormCtaParamsSchema>;
20
+
21
+ export function isSwapFormCtaParams(v: unknown): v is SwapFormCtaParams {
22
+ return swapFormCtaParamsSchema.safeParse(v).success;
23
+ }
24
+
25
+ const caip2Eip155 = z
26
+ .string()
27
+ .min(8)
28
+ .max(64)
29
+ .regex(/^eip155:\d+$/, "network must be CAIP-2 form eip155:<chainId>");
30
+
31
+ const evmAddress20 = z
32
+ .string()
33
+ .trim()
34
+ .refine((s) => /^0x[a-fA-F0-9]{40}$/.test(s), "must be a 0x-prefixed 20-byte EVM address")
35
+ .transform((s) => s.trim().toLowerCase());
36
+
37
+ const positiveWeiString = z
38
+ .string()
39
+ .trim()
40
+ .regex(/^[1-9]\d*$/, "must be a positive integer decimal string (base units)");
41
+
42
+ const nonNegativeWeiString = z
43
+ .string()
44
+ .trim()
45
+ .regex(/^\d+$/, "must be a non-negative integer decimal string (base units)");
46
+
47
+ const poolFeeSchema = z.union([
48
+ z.literal(500),
49
+ z.literal(3000),
50
+ z.literal(10000),
51
+ ]);
52
+
53
+ /** Confirmed swap draft — user signs approve (if needed) + router `exactInputSingle` in wallet. */
54
+ export const draftTokenSwapInputSchema = z.object({
55
+ network: caip2Eip155,
56
+ tokenIn: evmAddress20,
57
+ tokenInSymbol: z.string().min(1).max(32).optional(),
58
+ tokenInDecimals: z.number().int().min(0).max(36),
59
+ tokenOut: evmAddress20,
60
+ tokenOutSymbol: z.string().min(1).max(32).optional(),
61
+ tokenOutDecimals: z.number().int().min(0).max(36),
62
+ amountInWei: positiveWeiString,
63
+ /** Slippage floor in `tokenOut` base units; `0` accepts any output. */
64
+ amountOutMinimumWei: nonNegativeWeiString.default("0"),
65
+ poolFee: poolFeeSchema.default(3000),
66
+ /** Filled server-side from deployment when omitted. */
67
+ router: evmAddress20.optional(),
68
+ /** Unix seconds; wallet may refresh if expired. */
69
+ deadlineUnix: z.number().int().positive().optional(),
70
+ note: z.string().max(500).optional(),
71
+ });
72
+
73
+ export type DraftTokenSwapInput = z.infer<typeof draftTokenSwapInputSchema>;
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { x402SupportedAssetSchema } from "./chat-api.js";
3
+
4
+ export const transferFormNetworkOptionSchema = z.object({
5
+ id: z.string().min(1).max(64),
6
+ label: z.string().min(1).max(120),
7
+ });
8
+
9
+ /** Persisted on the chat CTA row until the user submits the transfer form. */
10
+ export const transferFormCtaParamsSchema = z.object({
11
+ _transferForm: z.literal(true),
12
+ supportedAssets: z.array(x402SupportedAssetSchema).min(1).max(24),
13
+ networks: z.array(transferFormNetworkOptionSchema).max(16).optional(),
14
+ intro: z.string().max(2000).optional(),
15
+ /** When set, pre-fill recipient in the form. */
16
+ defaultTo: z
17
+ .string()
18
+ .trim()
19
+ .refine((s) => /^0x[a-fA-F0-9]{40}$/.test(s), "defaultTo must be 0x…40")
20
+ .transform((s) => s.toLowerCase())
21
+ .optional(),
22
+ });
23
+
24
+ export type TransferFormCtaParams = z.infer<typeof transferFormCtaParamsSchema>;
25
+
26
+ export function isTransferFormCtaParams(v: unknown): v is TransferFormCtaParams {
27
+ return transferFormCtaParamsSchema.safeParse(v).success;
28
+ }