@instadapp/avocado-base 0.0.0-dev.39c2fcc → 0.0.0-dev.3b3ffe1

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 (83) hide show
  1. package/abi/forwarder.json +8 -8
  2. package/abi/multisigForwarder.json +697 -0
  3. package/app.vue +7 -0
  4. package/assets/images/icons/arrow-left.svg +5 -0
  5. package/assets/images/icons/arrow-right.svg +5 -0
  6. package/assets/images/icons/avocado.svg +4 -0
  7. package/assets/images/icons/bridge-2.svg +3 -0
  8. package/assets/images/icons/bridge.svg +7 -0
  9. package/assets/images/icons/calendar.svg +8 -0
  10. package/assets/images/icons/change-threshold.svg +4 -0
  11. package/assets/images/icons/check-circle.svg +4 -0
  12. package/assets/images/icons/chevron-down.svg +4 -0
  13. package/assets/images/icons/clipboard.svg +7 -0
  14. package/assets/images/icons/clock-circle.svg +5 -0
  15. package/assets/images/icons/copy.svg +5 -0
  16. package/assets/images/icons/cross-transfer.svg +7 -0
  17. package/assets/images/icons/dapp.svg +4 -0
  18. package/assets/images/icons/deploy.svg +12 -0
  19. package/assets/images/icons/error-circle.svg +6 -0
  20. package/assets/images/icons/exclamation-circle.svg +13 -0
  21. package/assets/images/icons/exclamation-octagon.svg +13 -0
  22. package/assets/images/icons/exclamation-triangle.svg +5 -0
  23. package/assets/images/icons/external-link.svg +6 -0
  24. package/assets/images/icons/eye.svg +4 -0
  25. package/assets/images/icons/flowers.svg +8 -0
  26. package/assets/images/icons/gas-emoji.svg +193 -0
  27. package/assets/images/icons/gas.svg +14 -0
  28. package/assets/images/icons/gift.svg +153 -0
  29. package/assets/images/icons/globe.svg +110 -0
  30. package/assets/images/icons/hamburger.svg +6 -0
  31. package/assets/images/icons/info-2.svg +12 -0
  32. package/assets/images/icons/instadapp-pro.svg +4 -0
  33. package/assets/images/icons/logout.svg +3 -0
  34. package/assets/images/icons/moon.svg +3 -0
  35. package/assets/images/icons/multi-send.svg +7 -0
  36. package/assets/images/icons/network.svg +13 -0
  37. package/assets/images/icons/options.svg +5 -0
  38. package/assets/images/icons/permit-sign.svg +11 -0
  39. package/assets/images/icons/plus-circle.svg +6 -0
  40. package/assets/images/icons/plus.svg +5 -0
  41. package/assets/images/icons/power-off-bg.svg +24 -0
  42. package/assets/images/icons/power-off.svg +19 -0
  43. package/assets/images/icons/power-on.svg +19 -0
  44. package/assets/images/icons/qr.svg +20 -0
  45. package/assets/images/icons/question-circle.svg +14 -0
  46. package/assets/images/icons/refresh.svg +6 -0
  47. package/assets/images/icons/reject-proposal.svg +6 -0
  48. package/assets/images/icons/search.svg +12 -0
  49. package/assets/images/icons/sun.svg +3 -0
  50. package/assets/images/icons/transfer.svg +5 -0
  51. package/assets/images/icons/trash-2.svg +8 -0
  52. package/assets/images/icons/upgrade.svg +4 -0
  53. package/assets/images/icons/wave.svg +214 -0
  54. package/assets/images/icons/x.svg +5 -0
  55. package/components/ActionLogo.vue +38 -0
  56. package/components/ActionMetadata.vue +76 -0
  57. package/components/AuthorityAvatar.vue +38 -0
  58. package/components/ChainLogo.vue +14 -556
  59. package/components/CopyClipboard.vue +64 -0
  60. package/components/metadata/Bridge.vue +59 -0
  61. package/components/metadata/CrossTransfer.vue +71 -0
  62. package/components/metadata/GasTopup.vue +39 -0
  63. package/components/metadata/Permit2.vue +42 -0
  64. package/components/metadata/Signers.vue +63 -0
  65. package/components/metadata/Swap.vue +74 -0
  66. package/components/metadata/Transfer.vue +50 -0
  67. package/components.d.ts +13 -0
  68. package/contracts/Forwarder.ts +4 -4
  69. package/contracts/MultisigForwarder.ts +859 -0
  70. package/contracts/factories/Forwarder__factory.ts +8 -8
  71. package/contracts/factories/MultisigForwarder__factory.ts +721 -0
  72. package/contracts/factories/index.ts +1 -0
  73. package/contracts/index.ts +2 -0
  74. package/nuxt.config.ts +17 -1
  75. package/package.json +9 -4
  76. package/utils/avocado.ts +2 -0
  77. package/utils/bignumber.ts +20 -0
  78. package/utils/formatter.ts +1 -1
  79. package/utils/helper.ts +8 -0
  80. package/utils/metadata.ts +314 -177
  81. package/utils/network.ts +139 -80
  82. package/utils/services.ts +21 -0
  83. package/utils/utils.d.ts +129 -114
package/utils/metadata.ts CHANGED
@@ -1,11 +1,31 @@
1
1
  import { ethers, utils } from "ethers";
2
- import { Forwarder__factory } from "../contracts";
2
+ import { Forwarder__factory, MultisigForwarder__factory } from "../contracts";
3
+ import { toBN } from "./bignumber";
4
+
5
+ export const MetadataEnums = {
6
+ "transfer": "transfer",
7
+ "bridge": "bridge",
8
+ "swap": "swap",
9
+ "gas-topup": "gas-topup",
10
+ "upgrade": "upgrade",
11
+ "dapp": "dapp",
12
+ "deploy": "deploy",
13
+ "permit2": "permit2",
14
+ "cross-transfer": "cross-transfer",
15
+ "auth": "auth",
16
+ "rejection": "rejection",
17
+ "instadapp-pro": "instadapp-pro",
18
+ "add-signers": "add-signers",
19
+ "remove-signers": "remove-signers",
20
+ "change-threshold": "change-threshold",
21
+ "import": "import",
22
+ } as const;
3
23
 
4
24
  const multiMetadataTypes = ["bytes[]"];
5
25
 
6
26
  const metadataTypes = ["bytes32 type", "uint8 version", "bytes data"];
7
27
 
8
- const actionMetadataTypes = {
28
+ const actionMetadataTypes: Record<MetadataTypes, string[]> = {
9
29
  transfer: ["address token", "uint256 amount", "address receiver"],
10
30
  "cross-transfer": [
11
31
  "address fromToken",
@@ -34,6 +54,7 @@ const actionMetadataTypes = {
34
54
  "gas-topup": ["uint256 amount", "address token", "address onBehalf"],
35
55
  upgrade: ["bytes32 version", "address walletImpl"],
36
56
  dapp: ["string name", "string url"],
57
+ "import": ["bytes32 protocol", "uint256 valueInUsd"],
37
58
  auth: ["address address", "uint256 chainId", "bool remove"],
38
59
  deploy: [],
39
60
  permit2: [
@@ -43,6 +64,10 @@ const actionMetadataTypes = {
43
64
  "uint48 expiration",
44
65
  ],
45
66
  "instadapp-pro": ["string castDetails"],
67
+ 'add-signers': ['address[] signers'],
68
+ 'remove-signers': ['address[] signers'],
69
+ 'change-threshold': ['uint8 count'],
70
+ 'rejection': ['bytes32 id'],
46
71
  };
47
72
 
48
73
  const encodeMetadata = (props: MetadataProps) => {
@@ -63,7 +88,7 @@ export const encodeDappMetadata = (
63
88
  );
64
89
 
65
90
  const data = encodeMetadata({
66
- type: "dapp",
91
+ type: MetadataEnums.dapp,
67
92
  encodedData,
68
93
  });
69
94
 
@@ -80,7 +105,21 @@ export const encodeTransferMetadata = (
80
105
  );
81
106
 
82
107
  const data = encodeMetadata({
83
- type: "transfer",
108
+ type: MetadataEnums.transfer,
109
+ encodedData,
110
+ });
111
+
112
+ return single ? encodeMultipleActions(data) : data;
113
+ };
114
+
115
+ export const encodeRejectionMetadata = (id: string, single = true) => {
116
+ const encodedData = ethers.utils.defaultAbiCoder.encode(
117
+ actionMetadataTypes.rejection,
118
+ [id]
119
+ );
120
+
121
+ const data = encodeMetadata({
122
+ type: MetadataEnums.rejection,
84
123
  encodedData,
85
124
  });
86
125
 
@@ -103,7 +142,7 @@ export const encodeCrossTransferMetadata = (
103
142
  );
104
143
 
105
144
  const data = encodeMetadata({
106
- type: "cross-transfer",
145
+ type: MetadataEnums["cross-transfer"],
107
146
  encodedData,
108
147
  });
109
148
 
@@ -120,7 +159,7 @@ export const encodeAuthMetadata = (
120
159
  );
121
160
 
122
161
  const data = encodeMetadata({
123
- type: "auth",
162
+ type: MetadataEnums.auth,
124
163
  encodedData,
125
164
  });
126
165
 
@@ -129,7 +168,7 @@ export const encodeAuthMetadata = (
129
168
 
130
169
  export const encodeDeployMetadata = (single = true) => {
131
170
  const data = encodeMetadata({
132
- type: "deploy",
171
+ type: MetadataEnums.deploy,
133
172
  encodedData: "0x",
134
173
  });
135
174
 
@@ -146,7 +185,7 @@ export const encodeWCSignMetadata = (
146
185
  );
147
186
 
148
187
  const data = encodeMetadata({
149
- type: "permit2",
188
+ type: MetadataEnums.permit2,
150
189
  encodedData,
151
190
  });
152
191
 
@@ -163,7 +202,7 @@ export const encodeUpgradeMetadata = (
163
202
  );
164
203
 
165
204
  const data = encodeMetadata({
166
- type: "upgrade",
205
+ type: MetadataEnums.upgrade,
167
206
  encodedData,
168
207
  });
169
208
 
@@ -187,7 +226,7 @@ export const encodeSwapMetadata = (
187
226
  );
188
227
 
189
228
  const data = encodeMetadata({
190
- type: "swap",
229
+ type: MetadataEnums.swap,
191
230
  encodedData,
192
231
  });
193
232
 
@@ -203,10 +242,8 @@ export const encodeTopupMetadata = (
203
242
  [params.amount, params.token, params.onBehalf]
204
243
  );
205
244
 
206
- console.log(params);
207
-
208
245
  const data = encodeMetadata({
209
- type: "gas-topup",
246
+ type: MetadataEnums["gas-topup"],
210
247
  encodedData,
211
248
  });
212
249
 
@@ -231,7 +268,76 @@ export const encodeBridgeMetadata = (
231
268
  );
232
269
 
233
270
  const data = encodeMetadata({
234
- type: "bridge",
271
+ type: MetadataEnums.bridge,
272
+ encodedData,
273
+ });
274
+
275
+ return single ? encodeMultipleActions(data) : data;
276
+ };
277
+
278
+ export const encodeChangeThresholdMetadata = (
279
+ threshold: string | number,
280
+ single = true
281
+ ) => {
282
+ const encodedData = ethers.utils.defaultAbiCoder.encode(
283
+ actionMetadataTypes["change-threshold"],
284
+ [toBN(threshold).toNumber()]
285
+ );
286
+
287
+ const data = encodeMetadata({
288
+ type: MetadataEnums["change-threshold"],
289
+ encodedData,
290
+ });
291
+
292
+ return single ? encodeMultipleActions(data) : data;
293
+ };
294
+
295
+ export const encodeRemoveSignersMetadata = (
296
+ addresses: string[],
297
+ single = true
298
+ ) => {
299
+ const encodedData = ethers.utils.defaultAbiCoder.encode(
300
+ actionMetadataTypes["remove-signers"],
301
+ [addresses]
302
+ );
303
+
304
+ const data = encodeMetadata({
305
+ type: MetadataEnums["remove-signers"],
306
+ encodedData,
307
+ });
308
+
309
+ return single ? encodeMultipleActions(data) : data;
310
+ };
311
+
312
+ export const encodeImportMetadata = (
313
+ protocol: string,
314
+ valueInUsd: string,
315
+ single = true
316
+ ) => {
317
+ const encodedData = ethers.utils.defaultAbiCoder.encode(
318
+ actionMetadataTypes["import"],
319
+ [protocol, valueInUsd]
320
+ );
321
+
322
+ const data = encodeMetadata({
323
+ type: MetadataEnums["import"],
324
+ encodedData,
325
+ });
326
+
327
+ return single ? encodeMultipleActions(data) : data;
328
+ };
329
+
330
+ export const encodeAddSignersMetadata = (
331
+ addresses: string[],
332
+ single = true
333
+ ) => {
334
+ const encodedData = ethers.utils.defaultAbiCoder.encode(
335
+ actionMetadataTypes["add-signers"],
336
+ [addresses]
337
+ );
338
+
339
+ const data = encodeMetadata({
340
+ type: MetadataEnums["add-signers"],
235
341
  encodedData,
236
342
  });
237
343
 
@@ -242,176 +348,207 @@ export const encodeMultipleActions = (...actionData: string[]) => {
242
348
  return ethers.utils.defaultAbiCoder.encode(multiMetadataTypes, [actionData]);
243
349
  };
244
350
 
245
- export const decodeMetadata = (data: string) => {
351
+ export const decodeData = (data: string) => {
246
352
  try {
247
- const iface = Forwarder__factory.createInterface();
248
- let metadata = "0x";
249
- let payload = {};
250
-
251
- if (!data) return payload;
252
-
253
- if (data.startsWith("0x18e7f485")) {
254
- const executeData = iface.decodeFunctionData("execute", data);
255
- if (executeData.metadata_ === "0x" || !executeData.metadata_) {
256
- return null;
257
- } else {
258
- metadata = executeData.metadata_;
259
- }
260
- } else if (data.startsWith("0x14f80a8d")) {
261
- const executeDataV2 = iface.decodeFunctionData("executeV2", data);
262
- if (
263
- executeDataV2.params_.metadata === "0x" ||
264
- !executeDataV2.params_.metadata
265
- ) {
266
- return null;
267
- } else {
268
- metadata = executeDataV2.params_.metadata;
269
- }
353
+ const metadata = getMetadataFromData(data) || "0x";
354
+
355
+ return parseMetadata(metadata);
356
+ } catch (e) {
357
+ // console.log(e);
358
+ return null;
359
+ }
360
+ };
361
+
362
+ export const decodeMetadata = (metadata: string) => {
363
+ try {
364
+ return parseMetadata(metadata);
365
+ } catch (e) {
366
+ return null;
367
+ }
368
+ };
369
+
370
+ const iface = Forwarder__factory.createInterface();
371
+ const ifaceMultisig = MultisigForwarder__factory.createInterface();
372
+
373
+ const getMetadataFromData = (data: string) => {
374
+ let metadata = "0x";
375
+
376
+ if (data.startsWith("0x18e7f485")) {
377
+ const executeData = iface.decodeFunctionData("execute", data);
378
+ if (executeData.metadata_ === "0x" || !executeData.metadata_) {
379
+ return null;
270
380
  } else {
271
- const executeDataV3 = iface.decodeFunctionData("executeV3", data);
272
- if (
273
- executeDataV3.params_.metadata === "0x" ||
274
- !executeDataV3.params_.metadata
275
- ) {
276
- return null;
277
- } else {
278
- metadata = executeDataV3.params_.metadata;
279
- }
381
+ metadata = executeData.metadata_;
280
382
  }
383
+ } else if (data.startsWith("0x14f80a8d")) {
384
+ const executeDataV2 = iface.decodeFunctionData("executeV2", data);
385
+ if (
386
+ executeDataV2.params_.metadata === "0x" ||
387
+ !executeDataV2.params_.metadata
388
+ ) {
389
+ return null;
390
+ } else {
391
+ metadata = executeDataV2.params_.metadata;
392
+ }
393
+ } else {
394
+ const executeDataMultisig = ifaceMultisig.decodeFunctionData(
395
+ "executeV1",
396
+ data
397
+ );
398
+ if (
399
+ executeDataMultisig.params_.metadata === "0x" ||
400
+ !executeDataMultisig.params_.metadata
401
+ ) {
402
+ return null;
403
+ } else {
404
+ metadata = executeDataMultisig.params_.metadata;
405
+ }
406
+ }
407
+
408
+ return metadata;
409
+ };
410
+
281
411
 
282
- const metadataArr = [];
283
-
284
- const [decodedMultiMetadata = []] =
285
- (ethers.utils.defaultAbiCoder.decode(
286
- multiMetadataTypes,
287
- metadata
288
- ) as string[]) || [];
289
-
290
- for (let metadata of decodedMultiMetadata) {
291
- const decodedMetadata = ethers.utils.defaultAbiCoder.decode(
292
- metadataTypes,
293
- metadata
294
- );
295
-
296
- const type = ethers.utils.parseBytes32String(
297
- decodedMetadata.type
298
- ) as keyof typeof actionMetadataTypes;
299
-
300
- const decodedData = ethers.utils.defaultAbiCoder.decode(
301
- actionMetadataTypes[type],
302
- decodedMetadata.data
303
- );
304
-
305
- switch (type) {
306
- case "transfer":
307
- payload = {
308
- type,
309
- token: decodedData.token,
310
- amount: toBN(decodedData.amount).toFixed(),
311
- receiver: decodedData.receiver,
312
- };
313
- break;
314
- case "bridge":
315
- payload = {
316
- type,
317
- amount: toBN(decodedData.amount).toFixed(),
318
- receiver: decodedData.receiver,
319
- toToken: decodedData.toToken,
320
- fromToken: decodedData.fromToken,
321
- toChainId: decodedData.toChainId
322
- ? decodedData.toChainId.toString()
323
- : null,
324
- bridgeFee: toBN(decodedData.bridgeFee).toFixed(),
325
- };
326
- break;
327
- case "swap":
328
- payload = {
329
- type,
330
- buyAmount: toBN(decodedData.buyAmount).toFixed(),
331
- sellAmount: toBN(decodedData.sellAmount).toFixed(),
332
- buyToken: decodedData.buyToken,
333
- sellToken: decodedData.sellToken,
334
- receiver: decodedData.receiver,
335
- protocol: utils.parseBytes32String(decodedData?.protocol || ""),
336
- };
337
- break;
338
- case "upgrade":
339
- payload = {
340
- type,
341
- version: utils.parseBytes32String(decodedData?.version || ""),
342
- walletImpl: decodedData?.walletImpl,
343
- };
344
- break;
345
- case "gas-topup":
346
- payload = {
347
- type,
348
- amount: toBN(decodedData.amount).toFixed(),
349
- token: decodedData.token,
350
- onBehalf: decodedData.onBehalf,
351
- };
352
- break;
353
- case "dapp":
354
- payload = {
355
- type,
356
- name: decodedData?.name,
357
- url: decodedData?.url,
358
- };
359
- break;
360
- case "deploy":
361
- payload = {
362
- type,
363
- };
364
- break;
365
-
366
- case "permit2":
367
- payload = {
368
- type,
369
- token: decodedData.token,
370
- spender: decodedData.spender,
371
- amount: toBN(decodedData.amount).toFixed(),
372
- expiration: decodedData.expiration,
373
- };
374
- break;
375
-
376
- case "cross-transfer":
377
- payload = {
378
- type,
379
- fromToken: decodedData.fromToken,
380
- toToken: decodedData.toToken,
381
- toChainId: decodedData.toChainId
382
- ? decodedData.toChainId.toString()
383
- : null,
384
- amount: toBN(decodedData.amount).toFixed(),
385
- receiver: decodedData.receiver,
386
- };
387
-
388
- break;
389
- case "auth":
390
- payload = {
391
- type: decodedData.remove ? "remove-authority" : "add-authority",
392
- address: decodedData.address,
393
- chainId: decodedData.chainId
394
- ? decodedData.chainId.toString()
395
- : null,
396
- remove: decodedData.remove,
397
- };
398
-
399
- break;
400
- case "instadapp-pro":
401
- payload = {
402
- type,
403
- castDetails: decodedData.castDetails,
404
- };
405
-
406
- break;
407
- }
412
+ const typesPayload: IPayload = {
413
+ import: (data, type) => ({
414
+ type,
415
+ protocol: utils.parseBytes32String(data.protocol || ""),
416
+ valueInUsd: toBN(data.valueInUsd).toFixed(),
417
+ }),
418
+ transfer: (data, type) => ({
419
+ type,
420
+ token: data.token,
421
+ amount: toBN(data.amount).toFixed(),
422
+ receiver: data.receiver,
423
+ }),
424
+ bridge: (data, type) => ({
425
+ type,
426
+ amount: toBN(data.amount).toFixed(),
427
+ receiver: data.receiver,
428
+ toToken: data.toToken,
429
+ fromToken: data.fromToken,
430
+ toChainId: data.toChainId ? data.toChainId.toString() : null,
431
+ bridgeFee: toBN(data.bridgeFee).toFixed(),
432
+ }),
433
+ swap: (data, type) => ({
434
+ type,
435
+ buyAmount: toBN(data.buyAmount).toFixed(),
436
+ sellAmount: toBN(data.sellAmount).toFixed(),
437
+ buyToken: data.buyToken,
438
+ sellToken: data.sellToken,
439
+ receiver: data.receiver,
440
+ protocol: utils.parseBytes32String(data.protocol || ""),
441
+ }),
442
+ upgrade: (data, type) => ({
443
+ type,
444
+ version: utils.parseBytes32String(data.version || ""),
445
+ walletImpl: data.walletImpl,
446
+ }),
447
+ "gas-topup": (data, type) => ({
448
+ type,
449
+ amount: toBN(data.amount).toFixed(),
450
+ token: data.token,
451
+ onBehalf: data.onBehalf,
452
+ }),
453
+ "dapp": (data, type) => ({
454
+ type,
455
+ name: data.name,
456
+ url: data.url,
457
+ }),
458
+ "deploy": (data, type) => ({
459
+ type,
460
+ }),
461
+ "permit2": (data, type) => ({
462
+ type,
463
+ token: data.token,
464
+ spender: data.spender,
465
+ amount: toBN(data.amount).toFixed(),
466
+ expiration: data.expiration,
467
+ }),
468
+ "cross-transfer": (data, type) => ({
469
+ type,
470
+ fromToken: data.fromToken,
471
+ toToken: data.toToken,
472
+ toChainId: data.toChainId ? data.toChainId.toString() : null,
473
+ amount: toBN(data.amount).toFixed(),
474
+ receiver: data.receiver,
475
+ }),
476
+ "auth": (data) => ({
477
+ type: data.remove ? "remove-authority" : "add-authority",
478
+ address: data.address,
479
+ chainId: data.chainId ? data.chainId.toString() : null,
480
+ remove: data.remove,
481
+ }),
482
+ "instadapp-pro": (data, type) => ({
483
+ type,
484
+ castDetails: data.castDetails,
485
+ }),
486
+ "rejection": (data, type) => ({
487
+ type,
488
+ id: data.id,
489
+ }),
490
+ "add-signers": (data, type) => ({
491
+ type,
492
+ addresses: data.signers,
493
+ }),
494
+ "remove-signers": (data, type) => ({
495
+ type,
496
+ addresses: data.signers,
497
+ }),
498
+ "change-threshold": (data, type) => ({
499
+ type,
500
+ count: data.count,
501
+ }),
502
+ };
408
503
 
504
+ const parseMetadata = (metadata: string) => {
505
+ const metadataArr = [];
506
+
507
+ const [decodedMultiMetadata = []] =
508
+ (ethers.utils.defaultAbiCoder.decode(
509
+ multiMetadataTypes,
510
+ metadata
511
+ ) as string[]) || [];
512
+
513
+ for (let metadata of decodedMultiMetadata) {
514
+ const decodedMetadata = ethers.utils.defaultAbiCoder.decode(
515
+ metadataTypes,
516
+ metadata
517
+ );
518
+
519
+ const type = ethers.utils.parseBytes32String(
520
+ decodedMetadata.type
521
+ ) as keyof typeof actionMetadataTypes;
522
+
523
+ const decodedData = ethers.utils.defaultAbiCoder.decode(
524
+ actionMetadataTypes[type],
525
+ decodedMetadata.data
526
+ );
527
+
528
+ const payloadFunc = typesPayload[type]
529
+
530
+ if (payloadFunc) {
531
+ const payload = payloadFunc(decodedData, type)
409
532
  metadataArr.push(payload);
410
533
  }
411
534
 
412
- return metadataArr;
413
- } catch (e) {
414
- console.log(e);
415
- return null;
416
535
  }
536
+
537
+ return metadataArr;
538
+ };
539
+
540
+
541
+
542
+ /**
543
+ * Replaces hyphens with spaces and capitalizes the first letter of each word in a sentence.
544
+ * @param {string} txType - The input sentence to modify
545
+ *
546
+ * @returns {string} - The modified sentence with hyphens replaced with spaces and the first letter of each word capitalized.
547
+ */
548
+ export const formatTxType = (txType: string) => {
549
+ const finalSentence = txType
550
+ .replace("-", " ")
551
+ .replace(/(^\w{1})|(\s+\w{1})/g, (letter) => letter.toUpperCase());
552
+
553
+ return finalSentence;
417
554
  };