@dipansrimany/mlink-sdk 0.3.1 → 0.4.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/dist/index.js CHANGED
@@ -12,18 +12,113 @@ var ActionButtonSchema = zod.z.object({
12
12
  placeholder: zod.z.string().optional(),
13
13
  disabled: zod.z.boolean().optional()
14
14
  });
15
+ zod.z.enum([
16
+ "text",
17
+ "number",
18
+ "email",
19
+ "url",
20
+ "date",
21
+ "datetime-local",
22
+ "textarea",
23
+ "select",
24
+ "radio",
25
+ "checkbox",
26
+ "address",
27
+ "token",
28
+ "amount"
29
+ ]);
30
+ var ActionParameterOptionSchema = zod.z.object({
31
+ label: zod.z.string().min(1),
32
+ value: zod.z.string(),
33
+ selected: zod.z.boolean().optional()
34
+ });
35
+ var ActionParameterBaseSchema = zod.z.object({
36
+ name: zod.z.string().min(1).max(50),
37
+ label: zod.z.string().max(100).optional(),
38
+ required: zod.z.boolean().optional(),
39
+ pattern: zod.z.string().optional(),
40
+ patternDescription: zod.z.string().optional(),
41
+ min: zod.z.union([zod.z.string(), zod.z.number()]).optional(),
42
+ max: zod.z.union([zod.z.string(), zod.z.number()]).optional()
43
+ });
44
+ var ActionParameterSchema = ActionParameterBaseSchema.extend({
45
+ type: zod.z.enum([
46
+ "text",
47
+ "number",
48
+ "email",
49
+ "url",
50
+ "date",
51
+ "datetime-local",
52
+ "textarea",
53
+ "address",
54
+ "token",
55
+ "amount"
56
+ ]).optional()
57
+ });
58
+ var ActionParameterSelectableSchema = ActionParameterBaseSchema.extend({
59
+ type: zod.z.enum(["select", "radio", "checkbox"]),
60
+ options: zod.z.array(ActionParameterOptionSchema).min(1)
61
+ });
62
+ var TypedActionParameterSchema = zod.z.union([
63
+ ActionParameterSelectableSchema,
64
+ ActionParameterSchema
65
+ ]);
66
+ var LinkedActionTypeSchema = zod.z.enum(["transaction", "post", "external-link"]);
67
+ var LinkedActionSchema = zod.z.object({
68
+ type: LinkedActionTypeSchema.optional(),
69
+ href: zod.z.string().min(1),
70
+ label: zod.z.string().min(1).max(50),
71
+ disabled: zod.z.boolean().optional(),
72
+ parameters: zod.z.array(TypedActionParameterSchema).optional()
73
+ });
74
+ var ActionLinksSchema = zod.z.object({
75
+ actions: zod.z.array(LinkedActionSchema).min(1)
76
+ });
77
+ var PostNextActionLinkSchema = zod.z.object({
78
+ type: zod.z.literal("post"),
79
+ href: zod.z.string().min(1)
80
+ });
81
+ var InlineNextActionLinkSchema = zod.z.object({
82
+ type: zod.z.literal("inline"),
83
+ action: zod.z.lazy(() => ActionMetadataSchema)
84
+ });
85
+ var NextActionLinkSchema = zod.z.union([
86
+ PostNextActionLinkSchema,
87
+ InlineNextActionLinkSchema
88
+ ]);
89
+ var iconSchema = zod.z.string().refine(
90
+ (val) => {
91
+ if (val.startsWith("http://") || val.startsWith("https://")) return true;
92
+ if (val.startsWith("data:image/")) return true;
93
+ if (val.startsWith("/")) return true;
94
+ return false;
95
+ },
96
+ { message: "Icon must be a valid URL, base64 data URI, or relative path" }
97
+ );
15
98
  var ActionMetadataSchema = zod.z.object({
16
- title: zod.z.string().min(1).max(100),
17
- icon: zod.z.string().url(),
18
- description: zod.z.string().min(1).max(500),
19
- actions: zod.z.array(ActionButtonSchema).min(1),
99
+ type: zod.z.enum(["action", "completed"]).optional(),
100
+ title: zod.z.string().min(1).max(200),
101
+ icon: iconSchema,
102
+ description: zod.z.string().min(1).max(1e3),
103
+ label: zod.z.string().max(50).optional(),
104
+ // Legacy actions (optional)
105
+ actions: zod.z.array(ActionButtonSchema).optional(),
106
+ // Solana-style linked actions (optional)
107
+ links: ActionLinksSchema.optional(),
20
108
  disabled: zod.z.boolean().optional(),
21
109
  error: zod.z.object({ message: zod.z.string() }).optional()
22
- });
110
+ }).refine(
111
+ (data) => {
112
+ return data.actions && data.actions.length > 0 || data.links?.actions && data.links.actions.length > 0;
113
+ },
114
+ { message: "Must have at least one action or linked action" }
115
+ );
23
116
  var TransactionRequestSchema = zod.z.object({
24
117
  account: zod.z.string().regex(addressRegex, "Invalid Ethereum address"),
25
118
  action: zod.z.string().min(1),
26
- input: zod.z.string().optional()
119
+ input: zod.z.string().optional(),
120
+ // Solana-style parameter data
121
+ data: zod.z.record(zod.z.union([zod.z.string(), zod.z.array(zod.z.string())])).optional()
27
122
  });
28
123
  var EVMTransactionSchema = zod.z.object({
29
124
  to: zod.z.string().regex(addressRegex, "Invalid to address"),
@@ -32,9 +127,21 @@ var EVMTransactionSchema = zod.z.object({
32
127
  chainId: zod.z.number().positive()
33
128
  });
34
129
  var TransactionResponseSchema = zod.z.object({
35
- transaction: EVMTransactionSchema,
36
- message: zod.z.string().optional()
37
- });
130
+ // Single transaction (legacy)
131
+ transaction: EVMTransactionSchema.optional(),
132
+ // Multiple transactions (batch)
133
+ transactions: zod.z.array(EVMTransactionSchema).optional(),
134
+ message: zod.z.string().optional(),
135
+ // Action chaining
136
+ links: zod.z.object({
137
+ next: NextActionLinkSchema.optional()
138
+ }).optional()
139
+ }).refine(
140
+ (data) => {
141
+ return data.transaction !== void 0 || data.transactions && data.transactions.length > 0;
142
+ },
143
+ { message: "Must have either transaction or transactions" }
144
+ );
38
145
  function validateActionMetadata(data) {
39
146
  const result = ActionMetadataSchema.safeParse(data);
40
147
  if (result.success) {
@@ -62,6 +169,58 @@ function isValidAddress(address) {
62
169
  function isValidHex(hex) {
63
170
  return hexRegex.test(hex);
64
171
  }
172
+ function validateLinkedAction(data) {
173
+ const result = LinkedActionSchema.safeParse(data);
174
+ if (result.success) {
175
+ return { success: true, data: result.data };
176
+ }
177
+ return { success: false, error: result.error.message };
178
+ }
179
+ function validateParameter(data) {
180
+ const result = TypedActionParameterSchema.safeParse(data);
181
+ if (result.success) {
182
+ return { success: true, data: result.data };
183
+ }
184
+ return { success: false, error: result.error.message };
185
+ }
186
+ function validateParameterValues(parameters, values) {
187
+ const errors = [];
188
+ for (const param of parameters) {
189
+ const value = values[param.name];
190
+ if (param.required && (value === void 0 || value === "" || Array.isArray(value) && value.length === 0)) {
191
+ errors.push(`${param.label || param.name} is required`);
192
+ continue;
193
+ }
194
+ if (value === void 0 || value === "") continue;
195
+ const strValue = Array.isArray(value) ? value[0] : value;
196
+ if (param.pattern && strValue) {
197
+ const regex = new RegExp(param.pattern);
198
+ if (!regex.test(strValue)) {
199
+ errors.push(param.patternDescription || `${param.label || param.name} has invalid format`);
200
+ }
201
+ }
202
+ if ((param.type === "number" || param.type === "amount") && strValue) {
203
+ const numValue = parseFloat(strValue);
204
+ if (isNaN(numValue)) {
205
+ errors.push(`${param.label || param.name} must be a number`);
206
+ } else {
207
+ if (param.min !== void 0 && numValue < Number(param.min)) {
208
+ errors.push(`${param.label || param.name} must be at least ${param.min}`);
209
+ }
210
+ if (param.max !== void 0 && numValue > Number(param.max)) {
211
+ errors.push(`${param.label || param.name} must be at most ${param.max}`);
212
+ }
213
+ }
214
+ }
215
+ if (param.type === "address" && strValue && !isValidAddress(strValue)) {
216
+ errors.push(`${param.label || param.name} must be a valid Ethereum address`);
217
+ }
218
+ }
219
+ if (errors.length > 0) {
220
+ return { success: false, error: errors.join(", ") };
221
+ }
222
+ return { success: true, data: values };
223
+ }
65
224
 
66
225
  // src/builders.ts
67
226
  function button(config) {
@@ -81,12 +240,142 @@ function input(config) {
81
240
  disabled: config.disabled
82
241
  };
83
242
  }
243
+ function linkedAction(config) {
244
+ return {
245
+ type: "transaction",
246
+ href: config.href,
247
+ label: config.label,
248
+ disabled: config.disabled,
249
+ parameters: config.parameters
250
+ };
251
+ }
252
+ function actionButton(config) {
253
+ return {
254
+ type: "transaction",
255
+ href: config.href,
256
+ label: config.label,
257
+ disabled: config.disabled
258
+ };
259
+ }
260
+ function textParam(config) {
261
+ return {
262
+ type: "text",
263
+ name: config.name,
264
+ label: config.label,
265
+ required: config.required,
266
+ pattern: config.pattern,
267
+ patternDescription: config.patternDescription
268
+ };
269
+ }
270
+ function numberParam(config) {
271
+ return {
272
+ type: "number",
273
+ name: config.name,
274
+ label: config.label,
275
+ required: config.required,
276
+ min: config.min,
277
+ max: config.max
278
+ };
279
+ }
280
+ function amountParam(config) {
281
+ return {
282
+ type: "amount",
283
+ name: config.name,
284
+ label: config.label || "Amount",
285
+ required: config.required,
286
+ min: config.min,
287
+ max: config.max
288
+ };
289
+ }
290
+ function addressParam(config) {
291
+ return {
292
+ type: "address",
293
+ name: config.name,
294
+ label: config.label || "Address",
295
+ required: config.required,
296
+ pattern: "^0x[a-fA-F0-9]{40}$",
297
+ patternDescription: "Valid Ethereum address (0x...)"
298
+ };
299
+ }
300
+ function selectParam(config) {
301
+ return {
302
+ type: "select",
303
+ name: config.name,
304
+ label: config.label,
305
+ required: config.required,
306
+ options: config.options
307
+ };
308
+ }
309
+ function radioParam(config) {
310
+ return {
311
+ type: "radio",
312
+ name: config.name,
313
+ label: config.label,
314
+ required: config.required,
315
+ options: config.options
316
+ };
317
+ }
318
+ function checkboxParam(config) {
319
+ return {
320
+ type: "checkbox",
321
+ name: config.name,
322
+ label: config.label,
323
+ required: config.required,
324
+ options: config.options
325
+ };
326
+ }
327
+ function dateParam(config) {
328
+ return {
329
+ type: "date",
330
+ name: config.name,
331
+ label: config.label,
332
+ required: config.required,
333
+ min: config.min,
334
+ max: config.max
335
+ };
336
+ }
337
+ function textareaParam(config) {
338
+ return {
339
+ type: "textarea",
340
+ name: config.name,
341
+ label: config.label,
342
+ required: config.required
343
+ };
344
+ }
345
+ function option(label, value, selected) {
346
+ return { label, value, selected };
347
+ }
348
+ function createLinks(actions) {
349
+ return { actions };
350
+ }
351
+ function buildHref(template, params) {
352
+ let result = template;
353
+ for (const [key, value] of Object.entries(params)) {
354
+ const placeholder = `{${key}}`;
355
+ const replacement = Array.isArray(value) ? value.join(",") : value;
356
+ result = result.replace(new RegExp(placeholder, "g"), encodeURIComponent(replacement));
357
+ }
358
+ return result;
359
+ }
360
+ function extractParams(template) {
361
+ const matches = template.match(/\{([^}]+)\}/g);
362
+ if (!matches) return [];
363
+ return matches.map((m) => m.slice(1, -1));
364
+ }
365
+ function hasParameters(action) {
366
+ return Boolean(action.parameters && action.parameters.length > 0);
367
+ }
368
+ function isSelectableParam(param) {
369
+ return param.type === "select" || param.type === "radio" || param.type === "checkbox";
370
+ }
84
371
  function createAction(definition) {
85
372
  if (!definition.title) throw new Error("Action title is required");
86
373
  if (!definition.icon) throw new Error("Action icon is required");
87
374
  if (!definition.description) throw new Error("Action description is required");
88
- if (!definition.actions || definition.actions.length === 0) {
89
- throw new Error("At least one action is required");
375
+ const hasLegacyActions = definition.actions && definition.actions.length > 0;
376
+ const hasLinkedActions = definition.links?.actions && definition.links.actions.length > 0;
377
+ if (!hasLegacyActions && !hasLinkedActions) {
378
+ throw new Error("At least one action or linked action is required");
90
379
  }
91
380
  if (typeof definition.handler !== "function") {
92
381
  throw new Error("Handler must be a function");
@@ -94,10 +383,13 @@ function createAction(definition) {
94
383
  return {
95
384
  getMetadata() {
96
385
  return {
386
+ type: "action",
97
387
  title: definition.title,
98
388
  icon: definition.icon,
99
389
  description: definition.description,
390
+ label: definition.label,
100
391
  actions: definition.actions,
392
+ links: definition.links,
101
393
  disabled: definition.disabled
102
394
  };
103
395
  },
@@ -106,19 +398,21 @@ function createAction(definition) {
106
398
  if (!validation.success) {
107
399
  throw new Error(validation.error);
108
400
  }
109
- const selectedAction = definition.actions.find(
110
- (a) => a.value === request.action || a.type === "input" && request.action === "__input__"
111
- );
112
- if (!selectedAction) {
113
- throw new Error("Invalid action selected");
114
- }
115
- if (selectedAction.type === "input" && !request.input) {
116
- throw new Error("Input value is required");
401
+ if (definition.actions) {
402
+ const selectedAction = definition.actions.find(
403
+ (a) => a.value === request.action || a.type === "input" && request.action === "__input__"
404
+ );
405
+ if (selectedAction) {
406
+ if (selectedAction.type === "input" && !request.input) {
407
+ throw new Error("Input value is required");
408
+ }
409
+ }
117
410
  }
118
411
  const response = await definition.handler({
119
412
  account: request.account,
120
413
  action: request.action,
121
- input: request.input
414
+ input: request.input,
415
+ data: request.data
122
416
  });
123
417
  return response;
124
418
  }
@@ -152,6 +446,8 @@ var SUPPORTED_CHAINS = [MANTLE_MAINNET, MANTLE_SEPOLIA];
152
446
  var DEFAULT_CHAIN = MANTLE_SEPOLIA;
153
447
  var BLINK_BASE_URL = "https://blink.mantle.xyz";
154
448
  var ACTION_QUERY_PARAM = "action";
449
+ var REGISTRY_URL = "https://mlinks-fe.vercel.app";
450
+ var REGISTRY_VALIDATE_ENDPOINT = "/api/registry/validate";
155
451
 
156
452
  // src/utils.ts
157
453
  function createBlinkUrl(actionUrl, baseUrl = BLINK_BASE_URL) {
@@ -210,29 +506,59 @@ function getAddressExplorerUrl(chainId, address) {
210
506
  }
211
507
 
212
508
  exports.ACTION_QUERY_PARAM = ACTION_QUERY_PARAM;
509
+ exports.ActionButtonSchema = ActionButtonSchema;
510
+ exports.ActionLinksSchema = ActionLinksSchema;
213
511
  exports.ActionMetadataSchema = ActionMetadataSchema;
512
+ exports.ActionParameterOptionSchema = ActionParameterOptionSchema;
513
+ exports.ActionParameterSchema = ActionParameterSchema;
514
+ exports.ActionParameterSelectableSchema = ActionParameterSelectableSchema;
214
515
  exports.BLINK_BASE_URL = BLINK_BASE_URL;
215
516
  exports.DEFAULT_CHAIN = DEFAULT_CHAIN;
517
+ exports.LinkedActionSchema = LinkedActionSchema;
216
518
  exports.MANTLE_MAINNET = MANTLE_MAINNET;
217
519
  exports.MANTLE_SEPOLIA = MANTLE_SEPOLIA;
520
+ exports.NextActionLinkSchema = NextActionLinkSchema;
521
+ exports.REGISTRY_URL = REGISTRY_URL;
522
+ exports.REGISTRY_VALIDATE_ENDPOINT = REGISTRY_VALIDATE_ENDPOINT;
218
523
  exports.SUPPORTED_CHAINS = SUPPORTED_CHAINS;
219
524
  exports.TransactionRequestSchema = TransactionRequestSchema;
220
525
  exports.TransactionResponseSchema = TransactionResponseSchema;
526
+ exports.TypedActionParameterSchema = TypedActionParameterSchema;
527
+ exports.actionButton = actionButton;
528
+ exports.addressParam = addressParam;
529
+ exports.amountParam = amountParam;
530
+ exports.buildHref = buildHref;
221
531
  exports.button = button;
532
+ exports.checkboxParam = checkboxParam;
222
533
  exports.createAction = createAction;
223
534
  exports.createBlinkUrl = createBlinkUrl;
535
+ exports.createLinks = createLinks;
536
+ exports.dateParam = dateParam;
537
+ exports.extractParams = extractParams;
224
538
  exports.formatEther = formatEther;
225
539
  exports.getAddressExplorerUrl = getAddressExplorerUrl;
226
540
  exports.getChainById = getChainById;
227
541
  exports.getExplorerUrl = getExplorerUrl;
542
+ exports.hasParameters = hasParameters;
228
543
  exports.input = input;
229
544
  exports.isBlinkUrl = isBlinkUrl;
545
+ exports.isSelectableParam = isSelectableParam;
230
546
  exports.isValidAddress = isValidAddress;
231
547
  exports.isValidHex = isValidHex;
548
+ exports.linkedAction = linkedAction;
549
+ exports.numberParam = numberParam;
550
+ exports.option = option;
232
551
  exports.parseBlinkUrl = parseBlinkUrl;
233
552
  exports.parseEther = parseEther;
553
+ exports.radioParam = radioParam;
554
+ exports.selectParam = selectParam;
234
555
  exports.shortenAddress = shortenAddress;
556
+ exports.textParam = textParam;
557
+ exports.textareaParam = textareaParam;
235
558
  exports.validateActionMetadata = validateActionMetadata;
559
+ exports.validateLinkedAction = validateLinkedAction;
560
+ exports.validateParameter = validateParameter;
561
+ exports.validateParameterValues = validateParameterValues;
236
562
  exports.validateTransactionRequest = validateTransactionRequest;
237
563
  exports.validateTransactionResponse = validateTransactionResponse;
238
564
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validators.ts","../src/builders.ts","../src/constants.ts","../src/utils.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\nimport type {\n ActionMetadata,\n TransactionRequest,\n TransactionResponse,\n ValidationResult,\n} from './types';\n\n// Ethereum address regex\nconst addressRegex = /^0x[a-fA-F0-9]{40}$/;\n\n// Hex string regex\nconst hexRegex = /^0x[a-fA-F0-9]*$/;\n\n// Zod Schemas\nexport const ActionButtonSchema = z.object({\n label: z.string().min(1).max(50),\n value: z.string().min(1),\n type: z.enum(['button', 'input']),\n placeholder: z.string().optional(),\n disabled: z.boolean().optional(),\n});\n\nexport const ActionMetadataSchema = z.object({\n title: z.string().min(1).max(100),\n icon: z.string().url(),\n description: z.string().min(1).max(500),\n actions: z.array(ActionButtonSchema).min(1),\n disabled: z.boolean().optional(),\n error: z.object({ message: z.string() }).optional(),\n});\n\nexport const TransactionRequestSchema = z.object({\n account: z.string().regex(addressRegex, 'Invalid Ethereum address'),\n action: z.string().min(1),\n input: z.string().optional(),\n});\n\nexport const EVMTransactionSchema = z.object({\n to: z.string().regex(addressRegex, 'Invalid to address'),\n value: z.string(),\n data: z.string().regex(hexRegex, 'Invalid hex data'),\n chainId: z.number().positive(),\n});\n\nexport const TransactionResponseSchema = z.object({\n transaction: EVMTransactionSchema,\n message: z.string().optional(),\n});\n\n// Validation functions\nexport function validateActionMetadata(\n data: unknown\n): ValidationResult<ActionMetadata> {\n const result = ActionMetadataSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data as ActionMetadata };\n }\n return { success: false, error: result.error.message };\n}\n\nexport function validateTransactionRequest(\n data: unknown\n): ValidationResult<TransactionRequest> {\n const result = TransactionRequestSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error.message };\n}\n\nexport function validateTransactionResponse(\n data: unknown\n): ValidationResult<TransactionResponse> {\n const result = TransactionResponseSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data as TransactionResponse };\n }\n return { success: false, error: result.error.message };\n}\n\nexport function isValidAddress(address: string): boolean {\n return addressRegex.test(address);\n}\n\nexport function isValidHex(hex: string): boolean {\n return hexRegex.test(hex);\n}\n","import type {\n ActionButton,\n ActionDefinition,\n ActionMetadata,\n TransactionRequest,\n TransactionResponse,\n} from './types';\nimport { validateTransactionRequest } from './validators';\n\n// Create a button action\nexport function button(config: {\n label: string;\n value: string;\n disabled?: boolean;\n}): ActionButton {\n return {\n label: config.label,\n value: config.value,\n type: 'button',\n disabled: config.disabled,\n };\n}\n\n// Create an input action\nexport function input(config: {\n label: string;\n placeholder?: string;\n disabled?: boolean;\n}): ActionButton {\n return {\n label: config.label,\n value: '__input__',\n type: 'input',\n placeholder: config.placeholder,\n disabled: config.disabled,\n };\n}\n\n// Action object returned by createAction\nexport interface Action {\n getMetadata(): ActionMetadata;\n handleRequest(request: TransactionRequest): Promise<TransactionResponse>;\n}\n\n// Create a complete action\nexport function createAction(definition: ActionDefinition): Action {\n // Validate definition\n if (!definition.title) throw new Error('Action title is required');\n if (!definition.icon) throw new Error('Action icon is required');\n if (!definition.description) throw new Error('Action description is required');\n if (!definition.actions || definition.actions.length === 0) {\n throw new Error('At least one action is required');\n }\n if (typeof definition.handler !== 'function') {\n throw new Error('Handler must be a function');\n }\n\n return {\n getMetadata(): ActionMetadata {\n return {\n title: definition.title,\n icon: definition.icon,\n description: definition.description,\n actions: definition.actions,\n disabled: definition.disabled,\n };\n },\n\n async handleRequest(\n request: TransactionRequest\n ): Promise<TransactionResponse> {\n // Validate request\n const validation = validateTransactionRequest(request);\n if (!validation.success) {\n throw new Error(validation.error);\n }\n\n // Find the selected action\n const selectedAction = definition.actions.find(\n (a) => a.value === request.action || (a.type === 'input' && request.action === '__input__')\n );\n\n if (!selectedAction) {\n throw new Error('Invalid action selected');\n }\n\n // If input type, require input value\n if (selectedAction.type === 'input' && !request.input) {\n throw new Error('Input value is required');\n }\n\n // Call handler\n const response = await definition.handler({\n account: request.account,\n action: request.action,\n input: request.input,\n });\n\n return response;\n },\n };\n}\n","import type { ChainConfig } from './types';\n\nexport const MANTLE_MAINNET: ChainConfig = {\n chainId: 5000,\n name: 'Mantle',\n rpcUrl: 'https://rpc.mantle.xyz',\n explorerUrl: 'https://mantlescan.xyz',\n nativeCurrency: {\n name: 'MNT',\n symbol: 'MNT',\n decimals: 18,\n },\n};\n\nexport const MANTLE_SEPOLIA: ChainConfig = {\n chainId: 5003,\n name: 'Mantle Sepolia',\n rpcUrl: 'https://rpc.sepolia.mantle.xyz',\n explorerUrl: 'https://sepolia.mantlescan.xyz',\n nativeCurrency: {\n name: 'MNT',\n symbol: 'MNT',\n decimals: 18,\n },\n};\n\nexport const SUPPORTED_CHAINS: ChainConfig[] = [MANTLE_MAINNET, MANTLE_SEPOLIA];\n\nexport const DEFAULT_CHAIN = MANTLE_SEPOLIA;\n\nexport const BLINK_BASE_URL = 'https://blink.mantle.xyz';\n\nexport const ACTION_QUERY_PARAM = 'action';\n","import {\n BLINK_BASE_URL,\n ACTION_QUERY_PARAM,\n SUPPORTED_CHAINS,\n} from './constants';\nimport type { ChainConfig } from './types';\n\n// Create Blink URL from Action URL\nexport function createBlinkUrl(\n actionUrl: string,\n baseUrl: string = BLINK_BASE_URL\n): string {\n // Validate actionUrl is a valid URL\n try {\n new URL(actionUrl);\n } catch {\n throw new Error('Invalid action URL');\n }\n\n const encodedAction = encodeURIComponent(actionUrl);\n return `${baseUrl}/mlink?${ACTION_QUERY_PARAM}=${encodedAction}`;\n}\n\n// Parse Blink URL to extract Action URL\nexport function parseBlinkUrl(blinkUrl: string): string | null {\n try {\n const url = new URL(blinkUrl);\n const actionParam = url.searchParams.get(ACTION_QUERY_PARAM);\n\n if (!actionParam) return null;\n\n const actionUrl = decodeURIComponent(actionParam);\n\n // Validate it's a valid URL\n new URL(actionUrl);\n\n return actionUrl;\n } catch {\n return null;\n }\n}\n\n// Check if URL is a valid Blink URL\nexport function isBlinkUrl(url: string): boolean {\n return parseBlinkUrl(url) !== null;\n}\n\n// Convert human readable amount to wei string\nexport function parseEther(amount: string | number): string {\n const value = typeof amount === 'string' ? parseFloat(amount) : amount;\n if (isNaN(value) || value < 0) {\n throw new Error('Invalid amount');\n }\n const wei = BigInt(Math.floor(value * 1e18));\n return wei.toString();\n}\n\n// Convert wei to human readable amount\nexport function formatEther(wei: string | bigint): string {\n const value = typeof wei === 'string' ? BigInt(wei) : wei;\n const ether = Number(value) / 1e18;\n return ether.toFixed(6).replace(/\\.?0+$/, '');\n}\n\n// Shorten address for display\nexport function shortenAddress(address: string): string {\n if (!address || address.length < 10) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n// Get explorer URL for transaction\nexport function getExplorerUrl(chainId: number, txHash: string): string {\n const chain = getChainById(chainId);\n if (!chain) return '';\n return `${chain.explorerUrl}/tx/${txHash}`;\n}\n\n// Get chain config by ID\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return SUPPORTED_CHAINS.find((c) => c.chainId === chainId);\n}\n\n// Get explorer URL for address\nexport function getAddressExplorerUrl(\n chainId: number,\n address: string\n): string {\n const chain = getChainById(chainId);\n if (!chain) return '';\n return `${chain.explorerUrl}/address/${address}`;\n}\n"]}
1
+ {"version":3,"sources":["../src/validators.ts","../src/builders.ts","../src/constants.ts","../src/utils.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\nimport type {\n ActionMetadata,\n TransactionRequest,\n TransactionResponse,\n LinkedAction,\n TypedActionParameter,\n ValidationResult,\n} from './types';\n\n// Ethereum address regex\nconst addressRegex = /^0x[a-fA-F0-9]{40}$/;\n\n// Hex string regex\nconst hexRegex = /^0x[a-fA-F0-9]*$/;\n\n// =============================================================================\n// LEGACY SCHEMAS (Backwards compatible)\n// =============================================================================\n\nexport const ActionButtonSchema = z.object({\n label: z.string().min(1).max(50),\n value: z.string().min(1),\n type: z.enum(['button', 'input']),\n placeholder: z.string().optional(),\n disabled: z.boolean().optional(),\n});\n\n// =============================================================================\n// SOLANA-STYLE PARAMETER SCHEMAS\n// =============================================================================\n\n/**\n * Parameter types enum\n */\nexport const ActionParameterTypeSchema = z.enum([\n 'text',\n 'number',\n 'email',\n 'url',\n 'date',\n 'datetime-local',\n 'textarea',\n 'select',\n 'radio',\n 'checkbox',\n 'address',\n 'token',\n 'amount',\n]);\n\n/**\n * Option for select/radio/checkbox\n */\nexport const ActionParameterOptionSchema = z.object({\n label: z.string().min(1),\n value: z.string(),\n selected: z.boolean().optional(),\n});\n\n/**\n * Base parameter fields\n */\nconst ActionParameterBaseSchema = z.object({\n name: z.string().min(1).max(50),\n label: z.string().max(100).optional(),\n required: z.boolean().optional(),\n pattern: z.string().optional(),\n patternDescription: z.string().optional(),\n min: z.union([z.string(), z.number()]).optional(),\n max: z.union([z.string(), z.number()]).optional(),\n});\n\n/**\n * Non-selectable parameter (text, number, etc.)\n */\nexport const ActionParameterSchema = ActionParameterBaseSchema.extend({\n type: z.enum([\n 'text', 'number', 'email', 'url', 'date', 'datetime-local',\n 'textarea', 'address', 'token', 'amount'\n ]).optional(),\n});\n\n/**\n * Selectable parameter (select, radio, checkbox)\n */\nexport const ActionParameterSelectableSchema = ActionParameterBaseSchema.extend({\n type: z.enum(['select', 'radio', 'checkbox']),\n options: z.array(ActionParameterOptionSchema).min(1),\n});\n\n/**\n * Union of all parameter types\n */\nexport const TypedActionParameterSchema = z.union([\n ActionParameterSelectableSchema,\n ActionParameterSchema,\n]);\n\n// =============================================================================\n// LINKED ACTION SCHEMAS\n// =============================================================================\n\n/**\n * Linked action type enum\n */\nexport const LinkedActionTypeSchema = z.enum(['transaction', 'post', 'external-link']);\n\n/**\n * Linked action with href template and parameters\n */\nexport const LinkedActionSchema = z.object({\n type: LinkedActionTypeSchema.optional(),\n href: z.string().min(1),\n label: z.string().min(1).max(50),\n disabled: z.boolean().optional(),\n parameters: z.array(TypedActionParameterSchema).optional(),\n});\n\n/**\n * Links section containing linked actions\n */\nexport const ActionLinksSchema = z.object({\n actions: z.array(LinkedActionSchema).min(1),\n});\n\n// =============================================================================\n// ACTION CHAINING SCHEMAS\n// =============================================================================\n\nexport const PostNextActionLinkSchema = z.object({\n type: z.literal('post'),\n href: z.string().min(1),\n});\n\nexport const InlineNextActionLinkSchema: z.ZodType<{ type: 'inline'; action: ActionMetadata }> = z.object({\n type: z.literal('inline'),\n action: z.lazy(() => ActionMetadataSchema),\n});\n\nexport const NextActionLinkSchema = z.union([\n PostNextActionLinkSchema,\n InlineNextActionLinkSchema,\n]);\n\n// =============================================================================\n// MAIN SCHEMAS (Enhanced)\n// =============================================================================\n\n/**\n * Icon can be URL or base64 data URI\n */\nconst iconSchema = z.string().refine(\n (val) => {\n // Allow URLs\n if (val.startsWith('http://') || val.startsWith('https://')) return true;\n // Allow base64 data URIs\n if (val.startsWith('data:image/')) return true;\n // Allow relative paths\n if (val.startsWith('/')) return true;\n return false;\n },\n { message: 'Icon must be a valid URL, base64 data URI, or relative path' }\n);\n\n/**\n * Enhanced ActionMetadata schema with links support\n */\nexport const ActionMetadataSchema = z.object({\n type: z.enum(['action', 'completed']).optional(),\n title: z.string().min(1).max(200),\n icon: iconSchema,\n description: z.string().min(1).max(1000),\n label: z.string().max(50).optional(),\n // Legacy actions (optional)\n actions: z.array(ActionButtonSchema).optional(),\n // Solana-style linked actions (optional)\n links: ActionLinksSchema.optional(),\n disabled: z.boolean().optional(),\n error: z.object({ message: z.string() }).optional(),\n}).refine(\n (data) => {\n // Must have either actions or links (or both)\n return (data.actions && data.actions.length > 0) ||\n (data.links?.actions && data.links.actions.length > 0);\n },\n { message: 'Must have at least one action or linked action' }\n);\n\n/**\n * Enhanced TransactionRequest with data support\n */\nexport const TransactionRequestSchema = z.object({\n account: z.string().regex(addressRegex, 'Invalid Ethereum address'),\n action: z.string().min(1),\n input: z.string().optional(),\n // Solana-style parameter data\n data: z.record(z.union([z.string(), z.array(z.string())])).optional(),\n});\n\nexport const EVMTransactionSchema = z.object({\n to: z.string().regex(addressRegex, 'Invalid to address'),\n value: z.string(),\n data: z.string().regex(hexRegex, 'Invalid hex data'),\n chainId: z.number().positive(),\n});\n\n/**\n * Enhanced TransactionResponse with multi-tx and chaining support\n */\nexport const TransactionResponseSchema = z.object({\n // Single transaction (legacy)\n transaction: EVMTransactionSchema.optional(),\n // Multiple transactions (batch)\n transactions: z.array(EVMTransactionSchema).optional(),\n message: z.string().optional(),\n // Action chaining\n links: z.object({\n next: NextActionLinkSchema.optional(),\n }).optional(),\n}).refine(\n (data) => {\n // Must have either transaction or transactions\n return data.transaction !== undefined || (data.transactions && data.transactions.length > 0);\n },\n { message: 'Must have either transaction or transactions' }\n);\n\n// Validation functions\nexport function validateActionMetadata(\n data: unknown\n): ValidationResult<ActionMetadata> {\n const result = ActionMetadataSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data as ActionMetadata };\n }\n return { success: false, error: result.error.message };\n}\n\nexport function validateTransactionRequest(\n data: unknown\n): ValidationResult<TransactionRequest> {\n const result = TransactionRequestSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error.message };\n}\n\nexport function validateTransactionResponse(\n data: unknown\n): ValidationResult<TransactionResponse> {\n const result = TransactionResponseSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data as TransactionResponse };\n }\n return { success: false, error: result.error.message };\n}\n\nexport function isValidAddress(address: string): boolean {\n return addressRegex.test(address);\n}\n\nexport function isValidHex(hex: string): boolean {\n return hexRegex.test(hex);\n}\n\n// =============================================================================\n// NEW VALIDATION FUNCTIONS\n// =============================================================================\n\n/**\n * Validate a linked action\n */\nexport function validateLinkedAction(\n data: unknown\n): ValidationResult<LinkedAction> {\n const result = LinkedActionSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data as LinkedAction };\n }\n return { success: false, error: result.error.message };\n}\n\n/**\n * Validate a parameter\n */\nexport function validateParameter(\n data: unknown\n): ValidationResult<TypedActionParameter> {\n const result = TypedActionParameterSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data as TypedActionParameter };\n }\n return { success: false, error: result.error.message };\n}\n\n/**\n * Validate parameter values against their definitions\n */\nexport function validateParameterValues(\n parameters: TypedActionParameter[],\n values: Record<string, string | string[]>\n): ValidationResult<Record<string, string | string[]>> {\n const errors: string[] = [];\n\n for (const param of parameters) {\n const value = values[param.name];\n\n // Check required\n if (param.required && (value === undefined || value === '' || (Array.isArray(value) && value.length === 0))) {\n errors.push(`${param.label || param.name} is required`);\n continue;\n }\n\n // Skip validation if no value and not required\n if (value === undefined || value === '') continue;\n\n const strValue = Array.isArray(value) ? value[0] : value;\n\n // Validate pattern\n if (param.pattern && strValue) {\n const regex = new RegExp(param.pattern);\n if (!regex.test(strValue)) {\n errors.push(param.patternDescription || `${param.label || param.name} has invalid format`);\n }\n }\n\n // Validate min/max for number types\n if ((param.type === 'number' || param.type === 'amount') && strValue) {\n const numValue = parseFloat(strValue);\n if (isNaN(numValue)) {\n errors.push(`${param.label || param.name} must be a number`);\n } else {\n if (param.min !== undefined && numValue < Number(param.min)) {\n errors.push(`${param.label || param.name} must be at least ${param.min}`);\n }\n if (param.max !== undefined && numValue > Number(param.max)) {\n errors.push(`${param.label || param.name} must be at most ${param.max}`);\n }\n }\n }\n\n // Validate address type\n if (param.type === 'address' && strValue && !isValidAddress(strValue)) {\n errors.push(`${param.label || param.name} must be a valid Ethereum address`);\n }\n }\n\n if (errors.length > 0) {\n return { success: false, error: errors.join(', ') };\n }\n\n return { success: true, data: values };\n}\n","import type {\n ActionButton,\n ActionDefinition,\n ActionMetadata,\n TransactionRequest,\n TransactionResponse,\n LinkedAction,\n TypedActionParameter,\n ActionParameter,\n ActionParameterSelectable,\n ActionParameterOption,\n ActionParameterType,\n SelectableParameterType,\n ActionLinks,\n} from './types';\nimport { validateTransactionRequest } from './validators';\n\n// Create a button action\nexport function button(config: {\n label: string;\n value: string;\n disabled?: boolean;\n}): ActionButton {\n return {\n label: config.label,\n value: config.value,\n type: 'button',\n disabled: config.disabled,\n };\n}\n\n// Create an input action\nexport function input(config: {\n label: string;\n placeholder?: string;\n disabled?: boolean;\n}): ActionButton {\n return {\n label: config.label,\n value: '__input__',\n type: 'input',\n placeholder: config.placeholder,\n disabled: config.disabled,\n };\n}\n\n// =============================================================================\n// SOLANA-STYLE LINKED ACTIONS & PARAMETERS BUILDERS\n// =============================================================================\n\n/**\n * Create a linked action with optional parameters\n * Uses Solana-style href templates with {parameter} placeholders\n *\n * @example\n * ```ts\n * linkedAction({\n * href: '/api/swap?amount={amount}&token={token}',\n * label: 'Swap Tokens',\n * parameters: [\n * textParam({ name: 'amount', label: 'Amount', required: true }),\n * selectParam({\n * name: 'token',\n * label: 'Token',\n * options: [\n * { label: 'USDC', value: '0x...' },\n * { label: 'USDT', value: '0x...' }\n * ]\n * })\n * ]\n * })\n * ```\n */\nexport function linkedAction(config: {\n href: string;\n label: string;\n disabled?: boolean;\n parameters?: TypedActionParameter[];\n}): LinkedAction {\n return {\n type: 'transaction',\n href: config.href,\n label: config.label,\n disabled: config.disabled,\n parameters: config.parameters,\n };\n}\n\n/**\n * Create a simple linked action button (no parameters, just a static href)\n *\n * @example\n * ```ts\n * actionButton({\n * href: '/api/tip?amount=1',\n * label: 'Tip 1 MNT'\n * })\n * ```\n */\nexport function actionButton(config: {\n href: string;\n label: string;\n disabled?: boolean;\n}): LinkedAction {\n return {\n type: 'transaction',\n href: config.href,\n label: config.label,\n disabled: config.disabled,\n };\n}\n\n/**\n * Create a text parameter\n */\nexport function textParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n pattern?: string;\n patternDescription?: string;\n}): ActionParameter {\n return {\n type: 'text',\n name: config.name,\n label: config.label,\n required: config.required,\n pattern: config.pattern,\n patternDescription: config.patternDescription,\n };\n}\n\n/**\n * Create a number parameter\n */\nexport function numberParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n min?: number | string;\n max?: number | string;\n}): ActionParameter {\n return {\n type: 'number',\n name: config.name,\n label: config.label,\n required: config.required,\n min: config.min,\n max: config.max,\n };\n}\n\n/**\n * Create an amount parameter (for token/ETH amounts)\n */\nexport function amountParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n min?: number | string;\n max?: number | string;\n}): ActionParameter {\n return {\n type: 'amount',\n name: config.name,\n label: config.label || 'Amount',\n required: config.required,\n min: config.min,\n max: config.max,\n };\n}\n\n/**\n * Create an address parameter (for wallet addresses)\n */\nexport function addressParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n}): ActionParameter {\n return {\n type: 'address',\n name: config.name,\n label: config.label || 'Address',\n required: config.required,\n pattern: '^0x[a-fA-F0-9]{40}$',\n patternDescription: 'Valid Ethereum address (0x...)',\n };\n}\n\n/**\n * Create a select dropdown parameter\n */\nexport function selectParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n options: ActionParameterOption[];\n}): ActionParameterSelectable {\n return {\n type: 'select',\n name: config.name,\n label: config.label,\n required: config.required,\n options: config.options,\n };\n}\n\n/**\n * Create a radio button group parameter\n */\nexport function radioParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n options: ActionParameterOption[];\n}): ActionParameterSelectable {\n return {\n type: 'radio',\n name: config.name,\n label: config.label,\n required: config.required,\n options: config.options,\n };\n}\n\n/**\n * Create a checkbox parameter (multiple selection)\n */\nexport function checkboxParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n options: ActionParameterOption[];\n}): ActionParameterSelectable {\n return {\n type: 'checkbox',\n name: config.name,\n label: config.label,\n required: config.required,\n options: config.options,\n };\n}\n\n/**\n * Create a date parameter\n */\nexport function dateParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n min?: string;\n max?: string;\n}): ActionParameter {\n return {\n type: 'date',\n name: config.name,\n label: config.label,\n required: config.required,\n min: config.min,\n max: config.max,\n };\n}\n\n/**\n * Create a textarea parameter (multi-line text)\n */\nexport function textareaParam(config: {\n name: string;\n label?: string;\n required?: boolean;\n}): ActionParameter {\n return {\n type: 'textarea',\n name: config.name,\n label: config.label,\n required: config.required,\n };\n}\n\n/**\n * Create an option for select/radio/checkbox parameters\n */\nexport function option(\n label: string,\n value: string,\n selected?: boolean\n): ActionParameterOption {\n return { label, value, selected };\n}\n\n/**\n * Create a links object with actions array\n *\n * @example\n * ```ts\n * createLinks([\n * actionButton({ href: '/api/tip?amount=1', label: 'Tip 1 MNT' }),\n * actionButton({ href: '/api/tip?amount=5', label: 'Tip 5 MNT' }),\n * linkedAction({\n * href: '/api/tip?amount={amount}',\n * label: 'Custom Amount',\n * parameters: [amountParam({ name: 'amount', required: true })]\n * })\n * ])\n * ```\n */\nexport function createLinks(actions: LinkedAction[]): ActionLinks {\n return { actions };\n}\n\n/**\n * Replace placeholders in href template with parameter values\n *\n * @example\n * ```ts\n * buildHref('/api/swap?amount={amount}&token={token}', { amount: '100', token: '0x...' })\n * // Returns: '/api/swap?amount=100&token=0x...'\n * ```\n */\nexport function buildHref(\n template: string,\n params: Record<string, string | string[]>\n): string {\n let result = template;\n for (const [key, value] of Object.entries(params)) {\n const placeholder = `{${key}}`;\n const replacement = Array.isArray(value) ? value.join(',') : value;\n result = result.replace(new RegExp(placeholder, 'g'), encodeURIComponent(replacement));\n }\n return result;\n}\n\n/**\n * Extract parameter names from href template\n *\n * @example\n * ```ts\n * extractParams('/api/swap?amount={amount}&token={token}')\n * // Returns: ['amount', 'token']\n * ```\n */\nexport function extractParams(template: string): string[] {\n const matches = template.match(/\\{([^}]+)\\}/g);\n if (!matches) return [];\n return matches.map((m) => m.slice(1, -1));\n}\n\n/**\n * Check if a linked action has parameters that need to be collected\n */\nexport function hasParameters(action: LinkedAction): boolean {\n return Boolean(action.parameters && action.parameters.length > 0);\n}\n\n/**\n * Check if a parameter is selectable (select/radio/checkbox)\n */\nexport function isSelectableParam(\n param: TypedActionParameter\n): param is ActionParameterSelectable {\n return param.type === 'select' || param.type === 'radio' || param.type === 'checkbox';\n}\n\n// Action object returned by createAction\nexport interface Action {\n getMetadata(): ActionMetadata;\n handleRequest(request: TransactionRequest): Promise<TransactionResponse>;\n}\n\n/**\n * Extended action definition that supports both legacy actions and linked actions\n */\nexport interface ExtendedActionDefinition extends Omit<ActionDefinition, 'actions'> {\n /** Primary button label */\n label?: string;\n /** Legacy actions array (backwards compatible) */\n actions?: ActionButton[];\n /** Solana-style linked actions */\n links?: ActionLinks;\n}\n\n/**\n * Create a complete action with support for both legacy and Solana-style linked actions\n *\n * @example Legacy style (backwards compatible):\n * ```ts\n * createAction({\n * title: 'Tip',\n * icon: 'https://...',\n * description: 'Send a tip',\n * actions: [\n * button({ label: '1 MNT', value: '1' }),\n * input({ label: 'Custom' })\n * ],\n * handler: async (ctx) => ({ transaction: {...} })\n * })\n * ```\n *\n * @example Solana-style linked actions:\n * ```ts\n * createAction({\n * title: 'Swap Tokens',\n * icon: 'https://...',\n * description: 'Swap tokens on DEX',\n * links: createLinks([\n * actionButton({ href: '/api/swap?amount=10', label: 'Swap 10' }),\n * linkedAction({\n * href: '/api/swap?amount={amount}&token={token}',\n * label: 'Custom Swap',\n * parameters: [\n * amountParam({ name: 'amount', required: true }),\n * selectParam({ name: 'token', options: [...] })\n * ]\n * })\n * ]),\n * handler: async (ctx) => ({ transaction: {...} })\n * })\n * ```\n */\nexport function createAction(definition: ExtendedActionDefinition): Action {\n // Validate definition\n if (!definition.title) throw new Error('Action title is required');\n if (!definition.icon) throw new Error('Action icon is required');\n if (!definition.description) throw new Error('Action description is required');\n\n // Must have either actions or links\n const hasLegacyActions = definition.actions && definition.actions.length > 0;\n const hasLinkedActions = definition.links?.actions && definition.links.actions.length > 0;\n\n if (!hasLegacyActions && !hasLinkedActions) {\n throw new Error('At least one action or linked action is required');\n }\n\n if (typeof definition.handler !== 'function') {\n throw new Error('Handler must be a function');\n }\n\n return {\n getMetadata(): ActionMetadata {\n return {\n type: 'action',\n title: definition.title,\n icon: definition.icon,\n description: definition.description,\n label: definition.label,\n actions: definition.actions,\n links: definition.links,\n disabled: definition.disabled,\n };\n },\n\n async handleRequest(\n request: TransactionRequest\n ): Promise<TransactionResponse> {\n // Validate request\n const validation = validateTransactionRequest(request);\n if (!validation.success) {\n throw new Error(validation.error);\n }\n\n // Handle legacy actions\n if (definition.actions) {\n const selectedAction = definition.actions.find(\n (a) => a.value === request.action || (a.type === 'input' && request.action === '__input__')\n );\n\n if (selectedAction) {\n // If input type, require input value\n if (selectedAction.type === 'input' && !request.input) {\n throw new Error('Input value is required');\n }\n }\n }\n\n // Call handler with full context including data\n const response = await definition.handler({\n account: request.account,\n action: request.action,\n input: request.input,\n data: request.data,\n });\n\n return response;\n },\n };\n}\n","import type { ChainConfig } from './types';\n\nexport const MANTLE_MAINNET: ChainConfig = {\n chainId: 5000,\n name: 'Mantle',\n rpcUrl: 'https://rpc.mantle.xyz',\n explorerUrl: 'https://mantlescan.xyz',\n nativeCurrency: {\n name: 'MNT',\n symbol: 'MNT',\n decimals: 18,\n },\n};\n\nexport const MANTLE_SEPOLIA: ChainConfig = {\n chainId: 5003,\n name: 'Mantle Sepolia',\n rpcUrl: 'https://rpc.sepolia.mantle.xyz',\n explorerUrl: 'https://sepolia.mantlescan.xyz',\n nativeCurrency: {\n name: 'MNT',\n symbol: 'MNT',\n decimals: 18,\n },\n};\n\nexport const SUPPORTED_CHAINS: ChainConfig[] = [MANTLE_MAINNET, MANTLE_SEPOLIA];\n\nexport const DEFAULT_CHAIN = MANTLE_SEPOLIA;\n\nexport const BLINK_BASE_URL = 'https://blink.mantle.xyz';\n\nexport const ACTION_QUERY_PARAM = 'action';\n\n// Registry URL for validation\nexport const REGISTRY_URL = 'https://mlinks-fe.vercel.app';\nexport const REGISTRY_VALIDATE_ENDPOINT = '/api/registry/validate';\n","import {\n BLINK_BASE_URL,\n ACTION_QUERY_PARAM,\n SUPPORTED_CHAINS,\n} from './constants';\nimport type { ChainConfig } from './types';\n\n// Create Blink URL from Action URL\nexport function createBlinkUrl(\n actionUrl: string,\n baseUrl: string = BLINK_BASE_URL\n): string {\n // Validate actionUrl is a valid URL\n try {\n new URL(actionUrl);\n } catch {\n throw new Error('Invalid action URL');\n }\n\n const encodedAction = encodeURIComponent(actionUrl);\n return `${baseUrl}/mlink?${ACTION_QUERY_PARAM}=${encodedAction}`;\n}\n\n// Parse Blink URL to extract Action URL\nexport function parseBlinkUrl(blinkUrl: string): string | null {\n try {\n const url = new URL(blinkUrl);\n const actionParam = url.searchParams.get(ACTION_QUERY_PARAM);\n\n if (!actionParam) return null;\n\n const actionUrl = decodeURIComponent(actionParam);\n\n // Validate it's a valid URL\n new URL(actionUrl);\n\n return actionUrl;\n } catch {\n return null;\n }\n}\n\n// Check if URL is a valid Blink URL\nexport function isBlinkUrl(url: string): boolean {\n return parseBlinkUrl(url) !== null;\n}\n\n// Convert human readable amount to wei string\nexport function parseEther(amount: string | number): string {\n const value = typeof amount === 'string' ? parseFloat(amount) : amount;\n if (isNaN(value) || value < 0) {\n throw new Error('Invalid amount');\n }\n const wei = BigInt(Math.floor(value * 1e18));\n return wei.toString();\n}\n\n// Convert wei to human readable amount\nexport function formatEther(wei: string | bigint): string {\n const value = typeof wei === 'string' ? BigInt(wei) : wei;\n const ether = Number(value) / 1e18;\n return ether.toFixed(6).replace(/\\.?0+$/, '');\n}\n\n// Shorten address for display\nexport function shortenAddress(address: string): string {\n if (!address || address.length < 10) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n// Get explorer URL for transaction\nexport function getExplorerUrl(chainId: number, txHash: string): string {\n const chain = getChainById(chainId);\n if (!chain) return '';\n return `${chain.explorerUrl}/tx/${txHash}`;\n}\n\n// Get chain config by ID\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return SUPPORTED_CHAINS.find((c) => c.chainId === chainId);\n}\n\n// Get explorer URL for address\nexport function getAddressExplorerUrl(\n chainId: number,\n address: string\n): string {\n const chain = getChainById(chainId);\n if (!chain) return '';\n return `${chain.explorerUrl}/address/${address}`;\n}\n"]}