n8n-nodes-dominusnode 1.0.0

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 (42) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +99 -0
  4. package/dist/credentials/DominusNodeApi.credentials.d.ts +7 -0
  5. package/dist/credentials/DominusNodeApi.credentials.js +42 -0
  6. package/dist/credentials/DominusNodeApi.credentials.js.map +1 -0
  7. package/dist/index.d.ts +4 -0
  8. package/dist/index.js +12 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/nodes/DominusNodeProxy/DominusNodeProxy.node.d.ts +24 -0
  11. package/dist/nodes/DominusNodeProxy/DominusNodeProxy.node.js +436 -0
  12. package/dist/nodes/DominusNodeProxy/DominusNodeProxy.node.js.map +1 -0
  13. package/dist/nodes/DominusNodeUsage/DominusNodeUsage.node.d.ts +13 -0
  14. package/dist/nodes/DominusNodeUsage/DominusNodeUsage.node.js +105 -0
  15. package/dist/nodes/DominusNodeUsage/DominusNodeUsage.node.js.map +1 -0
  16. package/dist/nodes/DominusNodeWallet/DominusNodeWallet.node.d.ts +33 -0
  17. package/dist/nodes/DominusNodeWallet/DominusNodeWallet.node.js +656 -0
  18. package/dist/nodes/DominusNodeWallet/DominusNodeWallet.node.js.map +1 -0
  19. package/dist/shared/auth.d.ts +74 -0
  20. package/dist/shared/auth.js +264 -0
  21. package/dist/shared/auth.js.map +1 -0
  22. package/dist/shared/constants.d.ts +9 -0
  23. package/dist/shared/constants.js +13 -0
  24. package/dist/shared/constants.js.map +1 -0
  25. package/dist/shared/ssrf.d.ts +42 -0
  26. package/dist/shared/ssrf.js +252 -0
  27. package/dist/shared/ssrf.js.map +1 -0
  28. package/package.json +41 -0
  29. package/src/credentials/DominusNodeApi.credentials.ts +39 -0
  30. package/src/index.ts +4 -0
  31. package/src/nodes/DominusNodeProxy/DominusNodeProxy.node.ts +459 -0
  32. package/src/nodes/DominusNodeUsage/DominusNodeUsage.node.ts +130 -0
  33. package/src/nodes/DominusNodeWallet/DominusNodeWallet.node.ts +898 -0
  34. package/src/shared/auth.ts +272 -0
  35. package/src/shared/constants.ts +11 -0
  36. package/src/shared/ssrf.ts +257 -0
  37. package/tests/DominusNodeProxy.test.ts +281 -0
  38. package/tests/DominusNodeUsage.test.ts +250 -0
  39. package/tests/DominusNodeWallet.test.ts +591 -0
  40. package/tests/ssrf.test.ts +238 -0
  41. package/tsconfig.json +18 -0
  42. package/vitest.config.ts +8 -0
@@ -0,0 +1,656 @@
1
+ "use strict";
2
+ /**
3
+ * DomiNode Wallet n8n community node.
4
+ *
5
+ * Operations:
6
+ * - Check Balance: Get current wallet balance
7
+ * - Top Up (Stripe): Create a Stripe checkout session
8
+ * - Top Up (Crypto): Create a crypto payment invoice
9
+ * - Top Up (PayPal): Create a PayPal checkout session via Stripe
10
+ * - Create Agentic Wallet: Create a sub-wallet with spending limits
11
+ * - Fund Agentic Wallet: Transfer funds to an agentic wallet
12
+ * - Get Agentic Wallet Balance: Check an agentic wallet's balance
13
+ * - List Agentic Wallets: List all agentic wallets
14
+ * - Get Agentic Transactions: Get transaction history for an agentic wallet
15
+ * - Freeze Agentic Wallet: Freeze an agentic wallet
16
+ * - Unfreeze Agentic Wallet: Unfreeze an agentic wallet
17
+ * - Delete Agentic Wallet: Delete an agentic wallet
18
+ * - Update Wallet Policy: Update agentic wallet spending policy
19
+ * - Create Team: Create a new team
20
+ * - List Teams: List all teams
21
+ * - Team Details: Get team details
22
+ * - Fund Team: Fund a team wallet
23
+ * - Create Team Key: Create an API key for a team
24
+ * - Team Usage: Get team wallet transaction history
25
+ * - Update Team: Update team name/max members
26
+ * - Update Team Member Role: Update a team member's role
27
+ *
28
+ * @module
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.DominusNodeWallet = void 0;
32
+ const n8n_workflow_1 = require("n8n-workflow");
33
+ const auth_1 = require("../../shared/auth");
34
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
35
+ const CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/;
36
+ const DOMAIN_RE = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
37
+ const VALID_CRYPTO_CURRENCIES = new Set([
38
+ "btc", "eth", "ltc", "xmr", "zec", "usdc", "sol", "usdt", "dai", "bnb",
39
+ ]);
40
+ class DominusNodeWallet {
41
+ description = {
42
+ displayName: "DomiNode Wallet",
43
+ name: "dominusNodeWallet",
44
+ icon: "file:dominusnode.svg",
45
+ group: ["transform"],
46
+ version: 1,
47
+ subtitle: '={{$parameter["operation"]}}',
48
+ description: "Manage DomiNode wallet, agentic wallets, and teams",
49
+ defaults: { name: "DomiNode Wallet" },
50
+ inputs: ["main"],
51
+ outputs: ["main"],
52
+ credentials: [{ name: "dominusNodeApi", required: true }],
53
+ properties: [
54
+ {
55
+ displayName: "Operation",
56
+ name: "operation",
57
+ type: "options",
58
+ noDataExpression: true,
59
+ options: [
60
+ // Wallet
61
+ { name: "Check Balance", value: "checkBalance", description: "Get current wallet balance", action: "Check balance" },
62
+ { name: "Top Up (Stripe)", value: "topUpStripe", description: "Create a Stripe checkout session", action: "Top up stripe" },
63
+ { name: "Top Up (Crypto)", value: "topUpCrypto", description: "Create a crypto payment invoice", action: "Top up crypto" },
64
+ { name: "Top Up (PayPal)", value: "topUpPaypal", description: "Create a PayPal checkout session", action: "Top up paypal" },
65
+ // Agentic Wallets
66
+ { name: "Create Agentic Wallet", value: "createAgenticWallet", description: "Create a sub-wallet with spending limits", action: "Create agentic wallet" },
67
+ { name: "Fund Agentic Wallet", value: "fundAgenticWallet", description: "Transfer funds to an agentic wallet", action: "Fund agentic wallet" },
68
+ { name: "Get Agentic Wallet Balance", value: "getAgenticBalance", description: "Get agentic wallet balance", action: "Get agentic wallet balance" },
69
+ { name: "List Agentic Wallets", value: "listAgenticWallets", description: "List all agentic wallets", action: "List agentic wallets" },
70
+ { name: "Get Agentic Transactions", value: "getAgenticTransactions", description: "Get agentic wallet transactions", action: "Get agentic transactions" },
71
+ { name: "Freeze Agentic Wallet", value: "freezeAgenticWallet", description: "Freeze an agentic wallet", action: "Freeze agentic wallet" },
72
+ { name: "Unfreeze Agentic Wallet", value: "unfreezeAgenticWallet", description: "Unfreeze an agentic wallet", action: "Unfreeze agentic wallet" },
73
+ { name: "Delete Agentic Wallet", value: "deleteAgenticWallet", description: "Delete an agentic wallet", action: "Delete agentic wallet" },
74
+ { name: "Update Wallet Policy", value: "updateWalletPolicy", description: "Update agentic wallet spending policy", action: "Update wallet policy" },
75
+ // Teams
76
+ { name: "Create Team", value: "createTeam", description: "Create a new team", action: "Create team" },
77
+ { name: "List Teams", value: "listTeams", description: "List all teams", action: "List teams" },
78
+ { name: "Team Details", value: "teamDetails", description: "Get team details", action: "Team details" },
79
+ { name: "Fund Team", value: "fundTeam", description: "Fund a team wallet", action: "Fund team" },
80
+ { name: "Create Team Key", value: "createTeamKey", description: "Create an API key for a team", action: "Create team key" },
81
+ { name: "Team Usage", value: "teamUsage", description: "Get team wallet transactions", action: "Team usage" },
82
+ { name: "Update Team", value: "updateTeam", description: "Update team settings", action: "Update team" },
83
+ { name: "Update Team Member Role", value: "updateTeamMemberRole", description: "Update a team member role", action: "Update team member role" },
84
+ // x402
85
+ { name: "x402 Info", value: "x402Info", description: "Get x402 micropayment protocol information", action: "Get x402 info" },
86
+ ],
87
+ default: "checkBalance",
88
+ },
89
+ // --- Stripe top-up ---
90
+ {
91
+ displayName: "Amount (Cents)",
92
+ name: "amountCents",
93
+ type: "number",
94
+ default: 500,
95
+ required: true,
96
+ description: "Amount in cents (e.g., 500 = $5.00). Minimum 500 ($5).",
97
+ displayOptions: { show: { operation: ["topUpStripe", "topUpPaypal"] } },
98
+ },
99
+ // --- Crypto top-up ---
100
+ {
101
+ displayName: "Amount (USD)",
102
+ name: "amountUsd",
103
+ type: "number",
104
+ default: 10,
105
+ required: true,
106
+ description: "Amount in USD. Minimum $5.",
107
+ displayOptions: { show: { operation: ["topUpCrypto"] } },
108
+ },
109
+ {
110
+ displayName: "Currency",
111
+ name: "currency",
112
+ type: "options",
113
+ options: [
114
+ { name: "Bitcoin (BTC)", value: "btc" },
115
+ { name: "Ethereum (ETH)", value: "eth" },
116
+ { name: "Litecoin (LTC)", value: "ltc" },
117
+ { name: "Monero (XMR)", value: "xmr" },
118
+ { name: "Zcash (ZEC)", value: "zec" },
119
+ { name: "USDC", value: "usdc" },
120
+ { name: "Solana (SOL)", value: "sol" },
121
+ { name: "Tether (USDT)", value: "usdt" },
122
+ { name: "DAI", value: "dai" },
123
+ { name: "BNB", value: "bnb" },
124
+ ],
125
+ default: "btc",
126
+ description: "Cryptocurrency to pay with",
127
+ displayOptions: { show: { operation: ["topUpCrypto"] } },
128
+ },
129
+ // --- Agentic wallet params ---
130
+ {
131
+ displayName: "Label",
132
+ name: "agenticLabel",
133
+ type: "string",
134
+ default: "",
135
+ required: true,
136
+ description: "Label for the agentic wallet (max 100 chars)",
137
+ displayOptions: { show: { operation: ["createAgenticWallet"] } },
138
+ },
139
+ {
140
+ displayName: "Spending Limit (Cents)",
141
+ name: "spendingLimitCents",
142
+ type: "number",
143
+ default: 1000,
144
+ required: true,
145
+ description: "Per-transaction spending limit in cents",
146
+ displayOptions: { show: { operation: ["createAgenticWallet"] } },
147
+ },
148
+ {
149
+ displayName: "Daily Limit (Cents)",
150
+ name: "dailyLimitCents",
151
+ type: "number",
152
+ default: 0,
153
+ description: "Optional daily budget cap in cents (0 = no limit, max 1,000,000)",
154
+ displayOptions: { show: { operation: ["createAgenticWallet"] } },
155
+ },
156
+ {
157
+ displayName: "Allowed Domains",
158
+ name: "allowedDomains",
159
+ type: "string",
160
+ default: "",
161
+ description: "Comma-separated domain allowlist (e.g., \"example.com,api.example.org\"). Leave empty for no restriction.",
162
+ displayOptions: { show: { operation: ["createAgenticWallet"] } },
163
+ },
164
+ {
165
+ displayName: "Wallet ID",
166
+ name: "policyWalletId",
167
+ type: "string",
168
+ default: "",
169
+ required: true,
170
+ description: "Agentic wallet UUID to update policy for",
171
+ displayOptions: { show: { operation: ["updateWalletPolicy"] } },
172
+ },
173
+ {
174
+ displayName: "Daily Limit (Cents)",
175
+ name: "policyDailyLimitCents",
176
+ type: "number",
177
+ default: 0,
178
+ description: "Daily budget cap in cents (0 = no limit, max 1,000,000). Set to -1 to remove.",
179
+ displayOptions: { show: { operation: ["updateWalletPolicy"] } },
180
+ },
181
+ {
182
+ displayName: "Allowed Domains",
183
+ name: "policyAllowedDomains",
184
+ type: "string",
185
+ default: "",
186
+ description: "Comma-separated domain allowlist. Leave empty to skip, set to \"*\" to remove restriction.",
187
+ displayOptions: { show: { operation: ["updateWalletPolicy"] } },
188
+ },
189
+ {
190
+ displayName: "Wallet ID",
191
+ name: "walletId",
192
+ type: "string",
193
+ default: "",
194
+ required: true,
195
+ description: "Agentic wallet UUID",
196
+ displayOptions: {
197
+ show: {
198
+ operation: [
199
+ "fundAgenticWallet",
200
+ "getAgenticBalance",
201
+ "getAgenticTransactions",
202
+ "freezeAgenticWallet",
203
+ "unfreezeAgenticWallet",
204
+ "deleteAgenticWallet",
205
+ ],
206
+ },
207
+ },
208
+ },
209
+ {
210
+ displayName: "Amount (Cents)",
211
+ name: "fundAmountCents",
212
+ type: "number",
213
+ default: 100,
214
+ required: true,
215
+ description: "Amount in cents to transfer to the agentic wallet",
216
+ displayOptions: { show: { operation: ["fundAgenticWallet"] } },
217
+ },
218
+ {
219
+ displayName: "Limit",
220
+ name: "transactionLimit",
221
+ type: "number",
222
+ default: 20,
223
+ description: "Number of transactions to return (1-100)",
224
+ displayOptions: { show: { operation: ["getAgenticTransactions", "teamUsage"] } },
225
+ },
226
+ // --- Team params ---
227
+ {
228
+ displayName: "Team Name",
229
+ name: "teamName",
230
+ type: "string",
231
+ default: "",
232
+ required: true,
233
+ description: "Name for the team (max 100 chars)",
234
+ displayOptions: { show: { operation: ["createTeam"] } },
235
+ },
236
+ {
237
+ displayName: "Max Members",
238
+ name: "maxMembers",
239
+ type: "number",
240
+ default: 10,
241
+ description: "Maximum team members (1-100)",
242
+ displayOptions: { show: { operation: ["createTeam"] } },
243
+ },
244
+ {
245
+ displayName: "Team ID",
246
+ name: "teamId",
247
+ type: "string",
248
+ default: "",
249
+ required: true,
250
+ description: "Team UUID",
251
+ displayOptions: {
252
+ show: {
253
+ operation: [
254
+ "teamDetails",
255
+ "fundTeam",
256
+ "createTeamKey",
257
+ "teamUsage",
258
+ "updateTeam",
259
+ "updateTeamMemberRole",
260
+ ],
261
+ },
262
+ },
263
+ },
264
+ {
265
+ displayName: "Amount (Cents)",
266
+ name: "teamFundAmountCents",
267
+ type: "number",
268
+ default: 500,
269
+ required: true,
270
+ description: "Amount in cents to fund the team wallet. Min 100 ($1), max 1,000,000 ($10,000).",
271
+ displayOptions: { show: { operation: ["fundTeam"] } },
272
+ },
273
+ {
274
+ displayName: "Key Label",
275
+ name: "keyLabel",
276
+ type: "string",
277
+ default: "",
278
+ required: true,
279
+ description: "Label for the team API key (max 100 chars)",
280
+ displayOptions: { show: { operation: ["createTeamKey"] } },
281
+ },
282
+ {
283
+ displayName: "New Team Name",
284
+ name: "updateTeamName",
285
+ type: "string",
286
+ default: "",
287
+ description: "New name for the team",
288
+ displayOptions: { show: { operation: ["updateTeam"] } },
289
+ },
290
+ {
291
+ displayName: "New Max Members",
292
+ name: "updateMaxMembers",
293
+ type: "number",
294
+ default: 0,
295
+ description: "New max members (1-100). Set to 0 to skip.",
296
+ displayOptions: { show: { operation: ["updateTeam"] } },
297
+ },
298
+ {
299
+ displayName: "User ID",
300
+ name: "userId",
301
+ type: "string",
302
+ default: "",
303
+ required: true,
304
+ description: "User UUID whose role to update",
305
+ displayOptions: { show: { operation: ["updateTeamMemberRole"] } },
306
+ },
307
+ {
308
+ displayName: "Role",
309
+ name: "role",
310
+ type: "options",
311
+ options: [
312
+ { name: "Admin", value: "admin" },
313
+ { name: "Member", value: "member" },
314
+ ],
315
+ default: "member",
316
+ description: "New role for the team member",
317
+ displayOptions: { show: { operation: ["updateTeamMemberRole"] } },
318
+ },
319
+ ],
320
+ };
321
+ async execute() {
322
+ const items = this.getInputData();
323
+ const returnData = [];
324
+ const credentials = await this.getCredentials("dominusNodeApi");
325
+ const apiKey = credentials.apiKey;
326
+ const baseUrl = credentials.baseUrl || "https://api.dominusnode.com";
327
+ if (!apiKey) {
328
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "API Key is required");
329
+ }
330
+ const auth = new auth_1.DominusNodeAuth(apiKey, baseUrl);
331
+ const operation = this.getNodeParameter("operation", 0);
332
+ for (let i = 0; i < items.length; i++) {
333
+ try {
334
+ let result;
335
+ switch (operation) {
336
+ // ----- Wallet -----
337
+ case "checkBalance": {
338
+ result = await auth.apiRequest("GET", "/api/wallet");
339
+ break;
340
+ }
341
+ case "topUpStripe": {
342
+ const amountCents = this.getNodeParameter("amountCents", i);
343
+ if (!Number.isInteger(amountCents) || amountCents < 500 || amountCents > 1_000_000) {
344
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "amountCents must be an integer between 500 ($5) and 1,000,000 ($10,000)", { itemIndex: i });
345
+ }
346
+ result = await auth.apiRequest("POST", "/api/wallet/topup/stripe", { amountCents });
347
+ break;
348
+ }
349
+ case "topUpCrypto": {
350
+ const amountUsd = this.getNodeParameter("amountUsd", i);
351
+ const currency = this.getNodeParameter("currency", i);
352
+ if (typeof amountUsd !== "number" || amountUsd < 5 || amountUsd > 10_000) {
353
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "amountUsd must be between $5 and $10,000", { itemIndex: i });
354
+ }
355
+ if (!VALID_CRYPTO_CURRENCIES.has(currency)) {
356
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid currency. Valid options: ${[...VALID_CRYPTO_CURRENCIES].join(", ")}`, { itemIndex: i });
357
+ }
358
+ result = await auth.apiRequest("POST", "/api/wallet/topup/crypto", {
359
+ amountUsd,
360
+ currency,
361
+ });
362
+ break;
363
+ }
364
+ case "topUpPaypal": {
365
+ const amountCents = this.getNodeParameter("amountCents", i);
366
+ if (!Number.isInteger(amountCents) || amountCents < 500 || amountCents > 1_000_000) {
367
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "amountCents must be an integer between 500 ($5) and 1,000,000 ($10,000)", { itemIndex: i });
368
+ }
369
+ result = await auth.apiRequest("POST", "/api/wallet/topup/stripe", {
370
+ amountCents,
371
+ paymentMethod: "paypal",
372
+ });
373
+ break;
374
+ }
375
+ // ----- Agentic Wallets -----
376
+ case "createAgenticWallet": {
377
+ const label = this.getNodeParameter("agenticLabel", i);
378
+ const spendingLimitCents = this.getNodeParameter("spendingLimitCents", i);
379
+ const dailyLimitCents = this.getNodeParameter("dailyLimitCents", i, 0);
380
+ const allowedDomainsRaw = this.getNodeParameter("allowedDomains", i, "");
381
+ if (!label || typeof label !== "string") {
382
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Label is required", { itemIndex: i });
383
+ }
384
+ if (label.length > 100) {
385
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Label must be 100 characters or fewer", { itemIndex: i });
386
+ }
387
+ if (CONTROL_CHAR_RE.test(label)) {
388
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Label contains invalid control characters", { itemIndex: i });
389
+ }
390
+ if (!Number.isInteger(spendingLimitCents) ||
391
+ spendingLimitCents <= 0 ||
392
+ spendingLimitCents > 2_147_483_647) {
393
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Spending limit must be a positive integer", { itemIndex: i });
394
+ }
395
+ const body = { label, spendingLimitCents };
396
+ if (dailyLimitCents > 0) {
397
+ if (!Number.isInteger(dailyLimitCents) || dailyLimitCents > 1_000_000) {
398
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "dailyLimitCents must be an integer between 1 and 1,000,000", { itemIndex: i });
399
+ }
400
+ body.dailyLimitCents = dailyLimitCents;
401
+ }
402
+ if (allowedDomainsRaw && allowedDomainsRaw.trim().length > 0) {
403
+ const domains = allowedDomainsRaw.split(",").map((d) => d.trim()).filter(Boolean);
404
+ if (domains.length > 100) {
405
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "allowedDomains may contain at most 100 entries", { itemIndex: i });
406
+ }
407
+ for (const d of domains) {
408
+ if (d.length > 253 || !DOMAIN_RE.test(d)) {
409
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid domain: "${d}". Must be a valid domain name (max 253 chars).`, { itemIndex: i });
410
+ }
411
+ }
412
+ body.allowedDomains = domains;
413
+ }
414
+ result = await auth.apiRequest("POST", "/api/agent-wallet", body);
415
+ break;
416
+ }
417
+ case "fundAgenticWallet": {
418
+ const walletId = this.getNodeParameter("walletId", i);
419
+ const amountCents = this.getNodeParameter("fundAmountCents", i);
420
+ validateUuid(this, walletId, "walletId", i);
421
+ if (!Number.isInteger(amountCents) ||
422
+ amountCents <= 0 ||
423
+ amountCents > 2_147_483_647) {
424
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Amount must be a positive integer", { itemIndex: i });
425
+ }
426
+ result = await auth.apiRequest("POST", `/api/agent-wallet/${encodeURIComponent(walletId)}/fund`, { amountCents });
427
+ break;
428
+ }
429
+ case "getAgenticBalance": {
430
+ const walletId = this.getNodeParameter("walletId", i);
431
+ validateUuid(this, walletId, "walletId", i);
432
+ result = await auth.apiRequest("GET", `/api/agent-wallet/${encodeURIComponent(walletId)}`);
433
+ break;
434
+ }
435
+ case "listAgenticWallets": {
436
+ result = await auth.apiRequest("GET", "/api/agent-wallet");
437
+ break;
438
+ }
439
+ case "getAgenticTransactions": {
440
+ const walletId = this.getNodeParameter("walletId", i);
441
+ const limit = this.getNodeParameter("transactionLimit", i, 20);
442
+ validateUuid(this, walletId, "walletId", i);
443
+ validateLimit(this, limit, i);
444
+ const params = new URLSearchParams();
445
+ params.set("limit", String(limit));
446
+ result = await auth.apiRequest("GET", `/api/agent-wallet/${encodeURIComponent(walletId)}/transactions?${params.toString()}`);
447
+ break;
448
+ }
449
+ case "freezeAgenticWallet": {
450
+ const walletId = this.getNodeParameter("walletId", i);
451
+ validateUuid(this, walletId, "walletId", i);
452
+ result = await auth.apiRequest("POST", `/api/agent-wallet/${encodeURIComponent(walletId)}/freeze`);
453
+ break;
454
+ }
455
+ case "unfreezeAgenticWallet": {
456
+ const walletId = this.getNodeParameter("walletId", i);
457
+ validateUuid(this, walletId, "walletId", i);
458
+ result = await auth.apiRequest("POST", `/api/agent-wallet/${encodeURIComponent(walletId)}/unfreeze`);
459
+ break;
460
+ }
461
+ case "deleteAgenticWallet": {
462
+ const walletId = this.getNodeParameter("walletId", i);
463
+ validateUuid(this, walletId, "walletId", i);
464
+ result = await auth.apiRequest("DELETE", `/api/agent-wallet/${encodeURIComponent(walletId)}`);
465
+ break;
466
+ }
467
+ case "updateWalletPolicy": {
468
+ const walletId = this.getNodeParameter("policyWalletId", i);
469
+ const dailyLimitCents = this.getNodeParameter("policyDailyLimitCents", i, 0);
470
+ const allowedDomainsRaw = this.getNodeParameter("policyAllowedDomains", i, "");
471
+ validateUuid(this, walletId, "policyWalletId", i);
472
+ const body = {};
473
+ if (dailyLimitCents === -1) {
474
+ body.dailyLimitCents = null;
475
+ }
476
+ else if (dailyLimitCents > 0) {
477
+ if (!Number.isInteger(dailyLimitCents) || dailyLimitCents > 1_000_000) {
478
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "dailyLimitCents must be an integer between 1 and 1,000,000 (or -1 to remove)", { itemIndex: i });
479
+ }
480
+ body.dailyLimitCents = dailyLimitCents;
481
+ }
482
+ if (allowedDomainsRaw === "*") {
483
+ body.allowedDomains = null;
484
+ }
485
+ else if (allowedDomainsRaw && allowedDomainsRaw.trim().length > 0) {
486
+ const domains = allowedDomainsRaw.split(",").map((d) => d.trim()).filter(Boolean);
487
+ if (domains.length > 100) {
488
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "allowedDomains may contain at most 100 entries", { itemIndex: i });
489
+ }
490
+ for (const d of domains) {
491
+ if (d.length > 253 || !DOMAIN_RE.test(d)) {
492
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid domain: "${d}". Must be a valid domain name (max 253 chars).`, { itemIndex: i });
493
+ }
494
+ }
495
+ body.allowedDomains = domains;
496
+ }
497
+ if (Object.keys(body).length === 0) {
498
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "At least one of dailyLimitCents or allowedDomains must be provided", { itemIndex: i });
499
+ }
500
+ result = await auth.apiRequest("PATCH", `/api/agent-wallet/${encodeURIComponent(walletId)}/policy`, body);
501
+ break;
502
+ }
503
+ // ----- Teams -----
504
+ case "createTeam": {
505
+ const name = this.getNodeParameter("teamName", i);
506
+ const maxMembers = this.getNodeParameter("maxMembers", i, 10);
507
+ if (!name || typeof name !== "string") {
508
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Team name is required", { itemIndex: i });
509
+ }
510
+ if (name.length > 100) {
511
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Team name must be 100 characters or fewer", { itemIndex: i });
512
+ }
513
+ if (CONTROL_CHAR_RE.test(name)) {
514
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Team name contains invalid control characters", { itemIndex: i });
515
+ }
516
+ const body = { name };
517
+ if (maxMembers) {
518
+ if (!Number.isInteger(maxMembers) || maxMembers < 1 || maxMembers > 100) {
519
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "maxMembers must be an integer between 1 and 100", { itemIndex: i });
520
+ }
521
+ body.maxMembers = maxMembers;
522
+ }
523
+ result = await auth.apiRequest("POST", "/api/teams", body);
524
+ break;
525
+ }
526
+ case "listTeams": {
527
+ result = await auth.apiRequest("GET", "/api/teams");
528
+ break;
529
+ }
530
+ case "teamDetails": {
531
+ const teamId = this.getNodeParameter("teamId", i);
532
+ validateUuid(this, teamId, "teamId", i);
533
+ result = await auth.apiRequest("GET", `/api/teams/${encodeURIComponent(teamId)}`);
534
+ break;
535
+ }
536
+ case "fundTeam": {
537
+ const teamId = this.getNodeParameter("teamId", i);
538
+ const amountCents = this.getNodeParameter("teamFundAmountCents", i);
539
+ validateUuid(this, teamId, "teamId", i);
540
+ if (!Number.isInteger(amountCents) ||
541
+ amountCents < 100 ||
542
+ amountCents > 1_000_000) {
543
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "amountCents must be between 100 ($1) and 1,000,000 ($10,000)", { itemIndex: i });
544
+ }
545
+ result = await auth.apiRequest("POST", `/api/teams/${encodeURIComponent(teamId)}/wallet/fund`, { amountCents });
546
+ break;
547
+ }
548
+ case "createTeamKey": {
549
+ const teamId = this.getNodeParameter("teamId", i);
550
+ const label = this.getNodeParameter("keyLabel", i);
551
+ validateUuid(this, teamId, "teamId", i);
552
+ if (!label || typeof label !== "string") {
553
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Key label is required", { itemIndex: i });
554
+ }
555
+ if (label.length > 100) {
556
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Key label must be 100 characters or fewer", { itemIndex: i });
557
+ }
558
+ if (CONTROL_CHAR_RE.test(label)) {
559
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Key label contains invalid control characters", { itemIndex: i });
560
+ }
561
+ result = await auth.apiRequest("POST", `/api/teams/${encodeURIComponent(teamId)}/keys`, { label });
562
+ break;
563
+ }
564
+ case "teamUsage": {
565
+ const teamId = this.getNodeParameter("teamId", i);
566
+ const limit = this.getNodeParameter("transactionLimit", i, 20);
567
+ validateUuid(this, teamId, "teamId", i);
568
+ validateLimit(this, limit, i);
569
+ const params = new URLSearchParams();
570
+ params.set("limit", String(limit));
571
+ result = await auth.apiRequest("GET", `/api/teams/${encodeURIComponent(teamId)}/wallet/transactions?${params.toString()}`);
572
+ break;
573
+ }
574
+ case "updateTeam": {
575
+ const teamId = this.getNodeParameter("teamId", i);
576
+ validateUuid(this, teamId, "teamId", i);
577
+ const body = {};
578
+ const newName = this.getNodeParameter("updateTeamName", i, "");
579
+ const newMax = this.getNodeParameter("updateMaxMembers", i, 0);
580
+ if (newName) {
581
+ if (newName.length > 100) {
582
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Team name must be 100 characters or fewer", { itemIndex: i });
583
+ }
584
+ if (CONTROL_CHAR_RE.test(newName)) {
585
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Team name contains invalid control characters", { itemIndex: i });
586
+ }
587
+ body.name = newName;
588
+ }
589
+ if (newMax > 0) {
590
+ if (!Number.isInteger(newMax) || newMax < 1 || newMax > 100) {
591
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "maxMembers must be an integer between 1 and 100", { itemIndex: i });
592
+ }
593
+ body.maxMembers = newMax;
594
+ }
595
+ if (Object.keys(body).length === 0) {
596
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "At least one of name or maxMembers must be provided", { itemIndex: i });
597
+ }
598
+ result = await auth.apiRequest("PATCH", `/api/teams/${encodeURIComponent(teamId)}`, body);
599
+ break;
600
+ }
601
+ case "updateTeamMemberRole": {
602
+ const teamId = this.getNodeParameter("teamId", i);
603
+ const userId = this.getNodeParameter("userId", i);
604
+ const role = this.getNodeParameter("role", i);
605
+ validateUuid(this, teamId, "teamId", i);
606
+ validateUuid(this, userId, "userId", i);
607
+ if (role !== "member" && role !== "admin") {
608
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Role must be 'member' or 'admin'", { itemIndex: i });
609
+ }
610
+ result = await auth.apiRequest("PATCH", `/api/teams/${encodeURIComponent(teamId)}/members/${encodeURIComponent(userId)}`, { role });
611
+ break;
612
+ }
613
+ case "x402Info": {
614
+ result = await auth.apiRequest("GET", "/api/x402/info");
615
+ break;
616
+ }
617
+ default:
618
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, { itemIndex: i });
619
+ }
620
+ returnData.push({ json: (result ?? {}) });
621
+ }
622
+ catch (err) {
623
+ if (this.continueOnFail()) {
624
+ returnData.push({
625
+ json: {
626
+ error: (0, auth_1.sanitizeError)(err instanceof Error ? err.message : String(err)),
627
+ },
628
+ });
629
+ continue;
630
+ }
631
+ if (err instanceof n8n_workflow_1.NodeOperationError)
632
+ throw err;
633
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), (0, auth_1.sanitizeError)(err instanceof Error ? err.message : String(err)), { itemIndex: i });
634
+ }
635
+ }
636
+ return [returnData];
637
+ }
638
+ }
639
+ exports.DominusNodeWallet = DominusNodeWallet;
640
+ // ---------------------------------------------------------------------------
641
+ // Validation helpers
642
+ // ---------------------------------------------------------------------------
643
+ function validateUuid(ctx, value, fieldName, itemIndex) {
644
+ if (!value || typeof value !== "string") {
645
+ throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), `${fieldName} is required`, { itemIndex });
646
+ }
647
+ if (!UUID_RE.test(value)) {
648
+ throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), `${fieldName} must be a valid UUID`, { itemIndex });
649
+ }
650
+ }
651
+ function validateLimit(ctx, limit, itemIndex) {
652
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
653
+ throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), "Limit must be an integer between 1 and 100", { itemIndex });
654
+ }
655
+ }
656
+ //# sourceMappingURL=DominusNodeWallet.node.js.map