@adminforth/dashboard 1.7.0 → 1.9.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.
- package/README.md +81 -55
- package/custom/model/dashboard.types.ts +17 -9
- package/custom/skills/adminforth-dashboard/SKILL.md +28 -12
- package/dist/custom/model/dashboard.types.d.ts +15 -8
- package/dist/custom/model/dashboard.types.ts +17 -9
- package/dist/custom/queries/useDashboardConfig.d.ts +222 -4
- package/dist/custom/queries/useWidgetData.d.ts +222 -4
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +28 -12
- package/dist/schema/api.d.ts +5440 -941
- package/dist/schema/api.js +2 -2
- package/dist/schema/widget.d.ts +432 -23
- package/dist/schema/widget.js +1 -1
- package/dist/schema/widgets/charts.d.ts +558 -28
- package/dist/schema/widgets/charts.js +2 -2
- package/dist/schema/widgets/common.d.ts +17 -6
- package/dist/schema/widgets/common.js +16 -7
- package/dist/schema/widgets/gauge-card.d.ts +38 -2
- package/dist/schema/widgets/kpi-card.d.ts +38 -2
- package/dist/schema/widgets/pivot-table.d.ts +38 -2
- package/dist/schema/widgets/table.d.ts +38 -2
- package/dist/services/calc-evaluator.d.ts +1 -0
- package/dist/services/calc-evaluator.js +28 -0
- package/dist/services/dashboardFilterService.d.ts +5 -0
- package/dist/services/dashboardFilterService.js +125 -0
- package/dist/services/widgetDataService.js +53 -201
- package/package.json +2 -1
- package/schema/api.ts +1 -2
- package/schema/widget.ts +0 -1
- package/schema/widgets/charts.ts +1 -2
- package/schema/widgets/common.ts +16 -7
- package/services/calc-evaluator.ts +33 -0
- package/services/dashboardFilterService.ts +162 -0
- package/services/widgetDataService.ts +88 -263
|
@@ -36,6 +36,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
36
36
|
page_size?: number | undefined;
|
|
37
37
|
} | undefined;
|
|
38
38
|
query: {
|
|
39
|
+
source?: "resource" | undefined;
|
|
39
40
|
resource: string;
|
|
40
41
|
select?: ({
|
|
41
42
|
field: string;
|
|
@@ -82,6 +83,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
82
83
|
as: string;
|
|
83
84
|
}[] | undefined;
|
|
84
85
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
86
|
+
} | {
|
|
87
|
+
source: "steps";
|
|
88
|
+
steps: {
|
|
89
|
+
name: string;
|
|
90
|
+
resource: string;
|
|
91
|
+
select: {
|
|
92
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
93
|
+
field?: string | undefined;
|
|
94
|
+
as: string;
|
|
95
|
+
filters?: any;
|
|
96
|
+
}[];
|
|
97
|
+
filters?: any;
|
|
98
|
+
}[];
|
|
99
|
+
calcs?: {
|
|
100
|
+
calc: string;
|
|
101
|
+
as: string;
|
|
102
|
+
}[] | undefined;
|
|
103
|
+
order_by?: {
|
|
104
|
+
field: string;
|
|
105
|
+
direction?: "asc" | "desc" | undefined;
|
|
106
|
+
}[] | undefined;
|
|
107
|
+
limit?: number | undefined;
|
|
108
|
+
offset?: number | undefined;
|
|
109
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
85
110
|
};
|
|
86
111
|
} | {
|
|
87
112
|
id: string;
|
|
@@ -136,6 +161,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
136
161
|
colors?: string[] | undefined;
|
|
137
162
|
};
|
|
138
163
|
query: {
|
|
164
|
+
source?: "resource" | undefined;
|
|
139
165
|
resource: string;
|
|
140
166
|
select?: ({
|
|
141
167
|
field: string;
|
|
@@ -183,21 +209,29 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
183
209
|
}[] | undefined;
|
|
184
210
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
185
211
|
} | {
|
|
212
|
+
source: "steps";
|
|
186
213
|
steps: {
|
|
187
214
|
name: string;
|
|
188
215
|
resource: string;
|
|
189
|
-
|
|
216
|
+
select: {
|
|
190
217
|
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
191
218
|
field?: string | undefined;
|
|
192
219
|
as: string;
|
|
193
220
|
filters?: any;
|
|
194
|
-
};
|
|
221
|
+
}[];
|
|
195
222
|
filters?: any;
|
|
196
223
|
}[];
|
|
197
224
|
calcs?: {
|
|
198
225
|
calc: string;
|
|
199
226
|
as: string;
|
|
200
227
|
}[] | undefined;
|
|
228
|
+
order_by?: {
|
|
229
|
+
field: string;
|
|
230
|
+
direction?: "asc" | "desc" | undefined;
|
|
231
|
+
}[] | undefined;
|
|
232
|
+
limit?: number | undefined;
|
|
233
|
+
offset?: number | undefined;
|
|
234
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
201
235
|
};
|
|
202
236
|
} | {
|
|
203
237
|
id: string;
|
|
@@ -248,6 +282,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
248
282
|
} | undefined;
|
|
249
283
|
};
|
|
250
284
|
query: {
|
|
285
|
+
source?: "resource" | undefined;
|
|
251
286
|
resource: string;
|
|
252
287
|
select?: ({
|
|
253
288
|
field: string;
|
|
@@ -294,6 +329,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
294
329
|
as: string;
|
|
295
330
|
}[] | undefined;
|
|
296
331
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
332
|
+
} | {
|
|
333
|
+
source: "steps";
|
|
334
|
+
steps: {
|
|
335
|
+
name: string;
|
|
336
|
+
resource: string;
|
|
337
|
+
select: {
|
|
338
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
339
|
+
field?: string | undefined;
|
|
340
|
+
as: string;
|
|
341
|
+
filters?: any;
|
|
342
|
+
}[];
|
|
343
|
+
filters?: any;
|
|
344
|
+
}[];
|
|
345
|
+
calcs?: {
|
|
346
|
+
calc: string;
|
|
347
|
+
as: string;
|
|
348
|
+
}[] | undefined;
|
|
349
|
+
order_by?: {
|
|
350
|
+
field: string;
|
|
351
|
+
direction?: "asc" | "desc" | undefined;
|
|
352
|
+
}[] | undefined;
|
|
353
|
+
limit?: number | undefined;
|
|
354
|
+
offset?: number | undefined;
|
|
355
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
297
356
|
};
|
|
298
357
|
} | {
|
|
299
358
|
id: string;
|
|
@@ -329,6 +388,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
329
388
|
color?: string | undefined;
|
|
330
389
|
};
|
|
331
390
|
query: {
|
|
391
|
+
source?: "resource" | undefined;
|
|
332
392
|
resource: string;
|
|
333
393
|
select?: ({
|
|
334
394
|
field: string;
|
|
@@ -375,6 +435,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
375
435
|
as: string;
|
|
376
436
|
}[] | undefined;
|
|
377
437
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
438
|
+
} | {
|
|
439
|
+
source: "steps";
|
|
440
|
+
steps: {
|
|
441
|
+
name: string;
|
|
442
|
+
resource: string;
|
|
443
|
+
select: {
|
|
444
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
445
|
+
field?: string | undefined;
|
|
446
|
+
as: string;
|
|
447
|
+
filters?: any;
|
|
448
|
+
}[];
|
|
449
|
+
filters?: any;
|
|
450
|
+
}[];
|
|
451
|
+
calcs?: {
|
|
452
|
+
calc: string;
|
|
453
|
+
as: string;
|
|
454
|
+
}[] | undefined;
|
|
455
|
+
order_by?: {
|
|
456
|
+
field: string;
|
|
457
|
+
direction?: "asc" | "desc" | undefined;
|
|
458
|
+
}[] | undefined;
|
|
459
|
+
limit?: number | undefined;
|
|
460
|
+
offset?: number | undefined;
|
|
461
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
378
462
|
};
|
|
379
463
|
} | {
|
|
380
464
|
id: string;
|
|
@@ -407,6 +491,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
407
491
|
}[];
|
|
408
492
|
};
|
|
409
493
|
query: {
|
|
494
|
+
source?: "resource" | undefined;
|
|
410
495
|
resource: string;
|
|
411
496
|
select?: ({
|
|
412
497
|
field: string;
|
|
@@ -453,6 +538,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
453
538
|
as: string;
|
|
454
539
|
}[] | undefined;
|
|
455
540
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
541
|
+
} | {
|
|
542
|
+
source: "steps";
|
|
543
|
+
steps: {
|
|
544
|
+
name: string;
|
|
545
|
+
resource: string;
|
|
546
|
+
select: {
|
|
547
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
548
|
+
field?: string | undefined;
|
|
549
|
+
as: string;
|
|
550
|
+
filters?: any;
|
|
551
|
+
}[];
|
|
552
|
+
filters?: any;
|
|
553
|
+
}[];
|
|
554
|
+
calcs?: {
|
|
555
|
+
calc: string;
|
|
556
|
+
as: string;
|
|
557
|
+
}[] | undefined;
|
|
558
|
+
order_by?: {
|
|
559
|
+
field: string;
|
|
560
|
+
direction?: "asc" | "desc" | undefined;
|
|
561
|
+
}[] | undefined;
|
|
562
|
+
limit?: number | undefined;
|
|
563
|
+
offset?: number | undefined;
|
|
564
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
456
565
|
};
|
|
457
566
|
};
|
|
458
567
|
data: unknown;
|
|
@@ -491,6 +600,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
491
600
|
page_size?: number | undefined;
|
|
492
601
|
} | undefined;
|
|
493
602
|
query: {
|
|
603
|
+
source?: "resource" | undefined;
|
|
494
604
|
resource: string;
|
|
495
605
|
select?: ({
|
|
496
606
|
field: string;
|
|
@@ -537,6 +647,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
537
647
|
as: string;
|
|
538
648
|
}[] | undefined;
|
|
539
649
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
650
|
+
} | {
|
|
651
|
+
source: "steps";
|
|
652
|
+
steps: {
|
|
653
|
+
name: string;
|
|
654
|
+
resource: string;
|
|
655
|
+
select: {
|
|
656
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
657
|
+
field?: string | undefined;
|
|
658
|
+
as: string;
|
|
659
|
+
filters?: any;
|
|
660
|
+
}[];
|
|
661
|
+
filters?: any;
|
|
662
|
+
}[];
|
|
663
|
+
calcs?: {
|
|
664
|
+
calc: string;
|
|
665
|
+
as: string;
|
|
666
|
+
}[] | undefined;
|
|
667
|
+
order_by?: {
|
|
668
|
+
field: string;
|
|
669
|
+
direction?: "asc" | "desc" | undefined;
|
|
670
|
+
}[] | undefined;
|
|
671
|
+
limit?: number | undefined;
|
|
672
|
+
offset?: number | undefined;
|
|
673
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
540
674
|
};
|
|
541
675
|
} | {
|
|
542
676
|
id: string;
|
|
@@ -591,6 +725,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
591
725
|
colors?: string[] | undefined;
|
|
592
726
|
};
|
|
593
727
|
query: {
|
|
728
|
+
source?: "resource" | undefined;
|
|
594
729
|
resource: string;
|
|
595
730
|
select?: ({
|
|
596
731
|
field: string;
|
|
@@ -638,21 +773,29 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
638
773
|
}[] | undefined;
|
|
639
774
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
640
775
|
} | {
|
|
776
|
+
source: "steps";
|
|
641
777
|
steps: {
|
|
642
778
|
name: string;
|
|
643
779
|
resource: string;
|
|
644
|
-
|
|
780
|
+
select: {
|
|
645
781
|
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
646
782
|
field?: string | undefined;
|
|
647
783
|
as: string;
|
|
648
784
|
filters?: any;
|
|
649
|
-
};
|
|
785
|
+
}[];
|
|
650
786
|
filters?: any;
|
|
651
787
|
}[];
|
|
652
788
|
calcs?: {
|
|
653
789
|
calc: string;
|
|
654
790
|
as: string;
|
|
655
791
|
}[] | undefined;
|
|
792
|
+
order_by?: {
|
|
793
|
+
field: string;
|
|
794
|
+
direction?: "asc" | "desc" | undefined;
|
|
795
|
+
}[] | undefined;
|
|
796
|
+
limit?: number | undefined;
|
|
797
|
+
offset?: number | undefined;
|
|
798
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
656
799
|
};
|
|
657
800
|
} | {
|
|
658
801
|
id: string;
|
|
@@ -703,6 +846,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
703
846
|
} | undefined;
|
|
704
847
|
};
|
|
705
848
|
query: {
|
|
849
|
+
source?: "resource" | undefined;
|
|
706
850
|
resource: string;
|
|
707
851
|
select?: ({
|
|
708
852
|
field: string;
|
|
@@ -749,6 +893,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
749
893
|
as: string;
|
|
750
894
|
}[] | undefined;
|
|
751
895
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
896
|
+
} | {
|
|
897
|
+
source: "steps";
|
|
898
|
+
steps: {
|
|
899
|
+
name: string;
|
|
900
|
+
resource: string;
|
|
901
|
+
select: {
|
|
902
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
903
|
+
field?: string | undefined;
|
|
904
|
+
as: string;
|
|
905
|
+
filters?: any;
|
|
906
|
+
}[];
|
|
907
|
+
filters?: any;
|
|
908
|
+
}[];
|
|
909
|
+
calcs?: {
|
|
910
|
+
calc: string;
|
|
911
|
+
as: string;
|
|
912
|
+
}[] | undefined;
|
|
913
|
+
order_by?: {
|
|
914
|
+
field: string;
|
|
915
|
+
direction?: "asc" | "desc" | undefined;
|
|
916
|
+
}[] | undefined;
|
|
917
|
+
limit?: number | undefined;
|
|
918
|
+
offset?: number | undefined;
|
|
919
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
752
920
|
};
|
|
753
921
|
} | {
|
|
754
922
|
id: string;
|
|
@@ -784,6 +952,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
784
952
|
color?: string | undefined;
|
|
785
953
|
};
|
|
786
954
|
query: {
|
|
955
|
+
source?: "resource" | undefined;
|
|
787
956
|
resource: string;
|
|
788
957
|
select?: ({
|
|
789
958
|
field: string;
|
|
@@ -830,6 +999,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
830
999
|
as: string;
|
|
831
1000
|
}[] | undefined;
|
|
832
1001
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
1002
|
+
} | {
|
|
1003
|
+
source: "steps";
|
|
1004
|
+
steps: {
|
|
1005
|
+
name: string;
|
|
1006
|
+
resource: string;
|
|
1007
|
+
select: {
|
|
1008
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
1009
|
+
field?: string | undefined;
|
|
1010
|
+
as: string;
|
|
1011
|
+
filters?: any;
|
|
1012
|
+
}[];
|
|
1013
|
+
filters?: any;
|
|
1014
|
+
}[];
|
|
1015
|
+
calcs?: {
|
|
1016
|
+
calc: string;
|
|
1017
|
+
as: string;
|
|
1018
|
+
}[] | undefined;
|
|
1019
|
+
order_by?: {
|
|
1020
|
+
field: string;
|
|
1021
|
+
direction?: "asc" | "desc" | undefined;
|
|
1022
|
+
}[] | undefined;
|
|
1023
|
+
limit?: number | undefined;
|
|
1024
|
+
offset?: number | undefined;
|
|
1025
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
833
1026
|
};
|
|
834
1027
|
} | {
|
|
835
1028
|
id: string;
|
|
@@ -862,6 +1055,7 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
862
1055
|
}[];
|
|
863
1056
|
};
|
|
864
1057
|
query: {
|
|
1058
|
+
source?: "resource" | undefined;
|
|
865
1059
|
resource: string;
|
|
866
1060
|
select?: ({
|
|
867
1061
|
field: string;
|
|
@@ -908,6 +1102,30 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
|
|
|
908
1102
|
as: string;
|
|
909
1103
|
}[] | undefined;
|
|
910
1104
|
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
1105
|
+
} | {
|
|
1106
|
+
source: "steps";
|
|
1107
|
+
steps: {
|
|
1108
|
+
name: string;
|
|
1109
|
+
resource: string;
|
|
1110
|
+
select: {
|
|
1111
|
+
agg: import("../model/dashboard.types.js").QueryAggregateOperation;
|
|
1112
|
+
field?: string | undefined;
|
|
1113
|
+
as: string;
|
|
1114
|
+
filters?: any;
|
|
1115
|
+
}[];
|
|
1116
|
+
filters?: any;
|
|
1117
|
+
}[];
|
|
1118
|
+
calcs?: {
|
|
1119
|
+
calc: string;
|
|
1120
|
+
as: string;
|
|
1121
|
+
}[] | undefined;
|
|
1122
|
+
order_by?: {
|
|
1123
|
+
field: string;
|
|
1124
|
+
direction?: "asc" | "desc" | undefined;
|
|
1125
|
+
}[] | undefined;
|
|
1126
|
+
limit?: number | undefined;
|
|
1127
|
+
offset?: number | undefined;
|
|
1128
|
+
formatting?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
|
|
911
1129
|
};
|
|
912
1130
|
};
|
|
913
1131
|
data: unknown;
|
|
@@ -151,8 +151,8 @@ Use resource, not resourceId.
|
|
|
151
151
|
|
|
152
152
|
## Query shape rules
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
All chart widgets, including funnel charts, use the same query shape.
|
|
155
|
+
Use a single-resource query by default.
|
|
156
156
|
|
|
157
157
|
For kpi_card and normal charts, use:
|
|
158
158
|
- query.resource
|
|
@@ -162,6 +162,26 @@ For kpi_card and normal charts, use:
|
|
|
162
162
|
- optional query.order_by
|
|
163
163
|
- optional query.calcs
|
|
164
164
|
|
|
165
|
+
For multi-resource charts or widgets, use the general steps source:
|
|
166
|
+
|
|
167
|
+
query:
|
|
168
|
+
source: steps
|
|
169
|
+
steps:
|
|
170
|
+
- name: Leads
|
|
171
|
+
resource: leads
|
|
172
|
+
select:
|
|
173
|
+
- agg: count
|
|
174
|
+
as: value
|
|
175
|
+
- name: Customers
|
|
176
|
+
resource: orders
|
|
177
|
+
select:
|
|
178
|
+
- agg: count_distinct
|
|
179
|
+
field: customer_id
|
|
180
|
+
as: value
|
|
181
|
+
|
|
182
|
+
Do not use bare query.steps without source: steps.
|
|
183
|
+
Do not use metric. Use select even when a step has only one aggregate.
|
|
184
|
+
|
|
165
185
|
## Date range rules
|
|
166
186
|
|
|
167
187
|
Use only query.filters for time ranges.
|
|
@@ -201,22 +221,18 @@ select raw token totals:
|
|
|
201
221
|
- sum output_tokens as output_tokens
|
|
202
222
|
|
|
203
223
|
then query.calcs:
|
|
204
|
-
- calculate total_spend from those aliases
|
|
224
|
+
- calculate total_spend from those aliases with explicit constants
|
|
205
225
|
|
|
206
|
-
For today vs yesterday KPI, use multiple aggregate select items with filters and distinct aliases, then calcs.
|
|
226
|
+
For today vs yesterday KPI, use multiple aggregate select items with filters and distinct aliases, then calcs.
|
|
207
227
|
|
|
208
|
-
## Calc
|
|
228
|
+
## Calc rules
|
|
209
229
|
|
|
210
|
-
|
|
211
|
-
Use
|
|
230
|
+
Calcs can reference only fields already present in the current row.
|
|
231
|
+
Use explicit constants for rates.
|
|
212
232
|
|
|
213
233
|
Minimal example:
|
|
214
234
|
|
|
215
|
-
variables:
|
|
216
|
-
prices:
|
|
217
|
-
gpt-5.4: 2.5
|
|
218
|
-
|
|
219
235
|
query:
|
|
220
236
|
calcs:
|
|
221
|
-
- calc: tokens / 1000000 *
|
|
237
|
+
- calc: tokens / 1000000 * 2.5
|
|
222
238
|
as: cost
|