ton-evm-bridge 0.0.1-security → 2.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.

Potentially problematic release.


This version of ton-evm-bridge might be problematic. Click here for more details.

Files changed (65) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintrc.js +16 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yaml +108 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierrc +4 -0
  6. package/@types/global.d.ts +1 -0
  7. package/@types/params.d.ts +24 -0
  8. package/@types/tonweb.d.ts +44 -0
  9. package/LICENSE +674 -0
  10. package/README.md +71 -5
  11. package/assets/WTON.json +1 -0
  12. package/assets/pics/arrow.svg +44 -0
  13. package/assets/pics/done.svg +38 -0
  14. package/assets/pics/link.svg +15 -0
  15. package/assets/pics/swap.svg +331 -0
  16. package/assets/styles/reboot.css +163 -0
  17. package/components/BridgeProcessor.vue +977 -0
  18. package/docs/.nojekyll +0 -0
  19. package/docs/200.html +9 -0
  20. package/docs/_nuxt/1f2ac62.js +1 -0
  21. package/docs/_nuxt/1f2ac62.js.br +0 -0
  22. package/docs/_nuxt/1f2ac62.js.gz +0 -0
  23. package/docs/_nuxt/5cc51a5.js +1 -0
  24. package/docs/_nuxt/5cc51a5.js.br +0 -0
  25. package/docs/_nuxt/5cc51a5.js.gz +0 -0
  26. package/docs/_nuxt/7767db0.js +2 -0
  27. package/docs/_nuxt/7767db0.js.br +0 -0
  28. package/docs/_nuxt/7767db0.js.gz +0 -0
  29. package/docs/_nuxt/9ead974.js +2 -0
  30. package/docs/_nuxt/9ead974.js.br +0 -0
  31. package/docs/_nuxt/9ead974.js.gz +0 -0
  32. package/docs/_nuxt/LICENSES +98 -0
  33. package/docs/_nuxt/a46cdc5.js +1 -0
  34. package/docs/_nuxt/a46cdc5.js.br +0 -0
  35. package/docs/_nuxt/a46cdc5.js.gz +0 -0
  36. package/docs/_nuxt/b3f7827.js +1 -0
  37. package/docs/_nuxt/b3f7827.js.br +0 -0
  38. package/docs/_nuxt/b3f7827.js.gz +0 -0
  39. package/docs/_nuxt/b5d388d.js +1 -0
  40. package/docs/_nuxt/b5d388d.js.br +0 -0
  41. package/docs/_nuxt/b5d388d.js.gz +0 -0
  42. package/docs/_nuxt/fe8ca79.js +2 -0
  43. package/docs/_nuxt/fe8ca79.js.br +0 -0
  44. package/docs/_nuxt/fe8ca79.js.gz +0 -0
  45. package/docs/_nuxt/img/arrow.69e1e70.svg +44 -0
  46. package/docs/_nuxt/img/arrow.69e1e70.svg.br +0 -0
  47. package/docs/_nuxt/img/arrow.69e1e70.svg.gz +0 -0
  48. package/docs/_nuxt/img/swap.b8b4b2f.svg +331 -0
  49. package/docs/_nuxt/img/swap.b8b4b2f.svg.br +0 -0
  50. package/docs/_nuxt/img/swap.b8b4b2f.svg.gz +0 -0
  51. package/docs/favicon.ico +0 -0
  52. package/docs/index.html +9 -0
  53. package/index.js +66 -0
  54. package/lang/en/bridge.json +105 -0
  55. package/lang/en-US.js +7 -0
  56. package/layouts/default.vue +53 -0
  57. package/modules/i18n.js +44 -0
  58. package/nuxt.config.js +73 -0
  59. package/package.json +61 -6
  60. package/pages/index.vue +635 -0
  61. package/static/favicon.ico +0 -0
  62. package/tsconfig.json +39 -0
  63. package/utils/constants.ts +65 -0
  64. package/utils/helpers.ts +37 -0
  65. package/vue-shim.d.ts +4 -0
@@ -0,0 +1,635 @@
1
+ <template>
2
+ <main class="Bridge">
3
+ <div class="Bridge-testnetWarning" v-if="isTestnet">{{$t('Bridge.testnet')}}</div>
4
+ <div class="Bridge-content">
5
+ <div class="Bridge-img" :class="{isFromTon}"></div>
6
+ <div class="Bridge-form">
7
+ <div class="Bridge-switchers" :class="{isFromTon}" :key="isFromTon">
8
+ <div class="Bridge-switcher">
9
+ <div class="Bridge-switcherTitle" :class="{disabled: isInterfaceBlocked}">
10
+ <span>{{tonNetworkName}}&nbsp;▾</span>
11
+ <ul class="Bridge-switcherList">
12
+ <li
13
+ v-for="item in fromPairs"
14
+ :key="item"
15
+ @click="onPairClick(true, item)"><button>{{$t(`Bridge.networks.${item}.${netTypeName}.name`)}}</button></li>
16
+ </ul>
17
+ </div>
18
+ <div class="Bridge-switcherAnno">{{tonNetworkCoin}}</div>
19
+ </div>
20
+
21
+ <button
22
+ class="Bridge-switcher-arrow"
23
+ :disabled="isInterfaceBlocked"
24
+ @click="toggleFromTon"></button>
25
+
26
+ <div class="Bridge-switcher">
27
+ <div class="Bridge-switcherTitle" :class="{disabled: isInterfaceBlocked}">
28
+ <span>{{pairNetworkName}}&nbsp;▾</span>
29
+ <ul class="Bridge-switcherList">
30
+ <li
31
+ v-for="item in toPairs"
32
+ :key="item"
33
+ @click="onPairClick(item === 'ton', item === 'ton' ? pair : item)"><button>{{$t(`Bridge.networks.${item}.${netTypeName}.name`)}}</button></li>
34
+ </ul>
35
+ </div>
36
+ <div class="Bridge-switcherAnno"><a :href="pairNetworkCoinUrl" target="_blank">{{pairNetworkCoin}}</a></div>
37
+ </div>
38
+ </div>
39
+
40
+ <div class="Bridge-inputWrapper">
41
+ <label for="amountInput">{{$t('Bridge.amountOfTon')}}</label><br>
42
+ <input
43
+ :disabled="isInterfaceBlocked"
44
+ type="number"
45
+ id="amountInput"
46
+ v-model="amountInner">
47
+ </div>
48
+
49
+ <div class="Bridge-inputWrapper">
50
+ <label for="toInput" id="toInputLabel">{{addressInputLabel}}</label><br>
51
+ <input
52
+ :disabled="isInterfaceBlocked"
53
+ type="text"
54
+ id="toInput"
55
+ v-model="toAddress">
56
+ </div>
57
+
58
+ <div class="Bridge-pairFee">{{pairFee}}</div>
59
+ <div class="Bridge-bridgeFee">{{bridgeFee}}</div>
60
+
61
+ <BridgeProcessor
62
+ ref="bridgeProcessor"
63
+ :key="pair"
64
+ :is-testnet="isTestnet"
65
+ :is-recover="isRecover"
66
+ :lt="lt"
67
+ :hash="hash"
68
+ :is-from-ton="isFromTon"
69
+ :pair="pair"
70
+ :amount="amount"
71
+ :to-address="toAddress"
72
+ @interface-blocked="onInterfaceBlocked"
73
+ @state-changed="getPairGasFee__debounced"
74
+ @reset-state="resetState"
75
+ @save-state="saveState"
76
+ @delete-state="deleteState"
77
+ /></BridgeProcessor>
78
+
79
+ <div class="Bridge-footer">
80
+ v2.11,
81
+ <a href="https://github.com/ton-blockchain/bridge" target="_blank">{{$t('Bridge.sourceCode')}}</a>,
82
+ <!-- <a href="https://ton.org/how-it-works/bridge" target="_blank">{{$t('Bridge.howItWorks')}}</a>,-->
83
+ <a href="https://github.com/ton-blockchain/TIPs/issues/24" target="_blank">{{$t('Bridge.documentation')}}</a>.
84
+ </div>
85
+ </div>
86
+ </div>
87
+ </main>
88
+ </template>
89
+
90
+ <script lang="ts">
91
+ import Vue from 'vue'
92
+ import lodashDebounce from 'lodash.debounce';
93
+ import { supportsLocalStorage } from '~/utils/helpers';
94
+ import { PARAMS } from '~/utils/constants';
95
+ import BridgeProcessor from '~/components/BridgeProcessor.vue'
96
+
97
+ const PAIRS = ['eth', 'bsc'];
98
+
99
+ declare interface IComponentData {
100
+ getPairGasFee__debounced: () => void,
101
+ gasPrice: number,
102
+
103
+ isTestnet: boolean,
104
+ isRecover: boolean,
105
+ lt: number,
106
+ hash: string,
107
+
108
+ isFromTon: boolean,
109
+ pair: string,
110
+ amountInner: string,
111
+ toAddress: string,
112
+
113
+ isInterfaceBlocked: boolean
114
+ }
115
+
116
+ export default Vue.extend({
117
+
118
+ components: {
119
+ BridgeProcessor
120
+ },
121
+
122
+ head(): object {
123
+ return {
124
+ title: this.$t(`Bridge.networks.${this.pair}.pageTitle`) as string
125
+ }
126
+ },
127
+
128
+ data(): IComponentData {
129
+ return {
130
+ getPairGasFee__debounced: () => {},
131
+ gasPrice: 0,
132
+
133
+ isTestnet: false,
134
+ isRecover: false,
135
+ lt: 0,
136
+ hash: '',
137
+
138
+ isFromTon: true,
139
+ pair: 'eth',
140
+ amountInner: '',
141
+ toAddress: '',
142
+
143
+ isInterfaceBlocked: false
144
+ }
145
+ },
146
+
147
+ computed: {
148
+ netTypeName(): string {
149
+ return this.isTestnet ? 'test' : 'main';
150
+ },
151
+ params(): IParamsNetwork {
152
+ const pairParams = PARAMS.networks[this.pair];
153
+ return pairParams[this.netTypeName as keyof typeof pairParams];
154
+ },
155
+ tonNetworkName(): string {
156
+ return this.$t(`Bridge.networks.ton.${this.netTypeName}.name`) as string;
157
+ },
158
+ tonNetworkCoin(): string {
159
+ return this.$t(`Bridge.networks.ton.${this.netTypeName}.coin`) as string;
160
+ },
161
+ pairNetworkName(): string {
162
+ return this.$t(`Bridge.networks.${this.pair}.${this.netTypeName}.name`) as string;
163
+ },
164
+ pairNetworkCoin(): string {
165
+ return this.$t(`Bridge.networks.${this.pair}.${this.netTypeName}.coin`) as string;
166
+ },
167
+ pairNetworkCoinUrl(): string {
168
+ const url = this.params.explorerUrl as string;
169
+ const address = this.params.wTonAddress as string;
170
+ return url.replace('<ADDRESS>', address) as string;
171
+ },
172
+ addressInputLabel(): string {
173
+ const pair = this.isFromTon ? this.pair : 'ton';
174
+ const networkFillName = this.$t(`Bridge.networks.${pair}.${this.netTypeName}.full`) as string;
175
+ const label = this.$t(`Bridge.addressInputLabel`) as string;
176
+ return label.replace('<NETWORK>', networkFillName) as string;
177
+ },
178
+ pairFee(): string {
179
+ const n = this.gasPrice ? this.gasPrice / this.params.defaultGwei : 1;
180
+ const fee = this.isFromTon ? (this.params.coinsPerGweiTo * n) : (this.params.coinsPerGweiFrom * n);
181
+
182
+ return (this.$t(`Bridge.networks.${this.pair}.gasFee`) as string).replace('<FEE>', fee.toFixed(4));
183
+ },
184
+ amount: {
185
+ get(): number {
186
+ const amount = parseFloat(this.amountInner);
187
+ return !amount || isNaN(amount) ? 0 : amount;
188
+ },
189
+
190
+ set(value: number): void {
191
+ this.amountInner = isNaN(value) ? '' : String(value);
192
+ }
193
+ },
194
+ bridgeFee(): string {
195
+ if (!isNaN(this.amount) && this.amount >= 10) {
196
+ return (this.$t('Bridge.bridgeFeeAbove10') as string).replace('<FEE>', String(5 + (this.amount - 5) * (0.25 / 100)));
197
+ } else {
198
+ return this.$t('Bridge.bridgeFeeBelow10') as string;
199
+ }
200
+ },
201
+ fromPairs(): string[] {
202
+ return PAIRS;
203
+ },
204
+ toPairs(): string[] {
205
+ return ['ton', ...PAIRS.filter(i => i !== this.pair)];
206
+ }
207
+ },
208
+
209
+ watch: {
210
+ isFromTon() {
211
+ this.getPairGasFee__debounced();
212
+ },
213
+ pair() {
214
+ this.getPairGasFee__debounced();
215
+ }
216
+ },
217
+
218
+ created(): void {
219
+ this.getPairGasFee__debounced = lodashDebounce(this.getPairGasFee, 100);
220
+
221
+ if (this.$route.query.testnet) {
222
+ this.isTestnet = (this.$route.query.testnet as string).toLowerCase() === 'true';
223
+ }
224
+ if (this.$route.query.recover || this.$route.query.recovery) {
225
+ this.isRecover = true;
226
+ }
227
+ if (this.$route.query.lt) {
228
+ const lt = parseInt(this.$route.query.lt, 10);
229
+ this.lt = !lt || isNaN(lt) ? 0 : lt;
230
+ }
231
+ if (this.$route.query.hash) {
232
+ this.hash = this.$route.query.hash as string;
233
+ }
234
+ if (this.$route.query.amount) {
235
+ const amount = parseFloat(this.$route.query.amount) / 1e9; //TODO refactor
236
+ this.amount = !amount || isNaN(amount) ? 0 : amount;
237
+ }
238
+ if (this.$route.query.toAddress) {
239
+ this.toAddress = this.$route.query.toAddress as string;
240
+ }
241
+ if (this.$route.query.fromNetwork && this.$route.query.toNetwork) {
242
+ const fromNetwork = this.$route.query.fromNetwork.toLowerCase();
243
+ const toNetwork = this.$route.query.toNetwork.toLowerCase();
244
+
245
+ if (fromNetwork === 'ton' && PAIRS.includes(toNetwork)) {
246
+ this.isFromTon = true;
247
+ this.pair = toNetwork;
248
+ }
249
+
250
+ if (toNetwork === 'ton' && PAIRS.includes(fromNetwork)) {
251
+ this.isFromTon = false;
252
+ this.pair = fromNetwork;
253
+ }
254
+ }
255
+ },
256
+
257
+ mounted(): void {
258
+ this.getPairGasFee__debounced();
259
+ this.loadState();
260
+ },
261
+
262
+ methods: {
263
+ onPairClick(switchDirection: boolean, toPair: string): void {
264
+ if (this.isInterfaceBlocked) {
265
+ return
266
+ }
267
+
268
+ if (switchDirection) {
269
+ this.isFromTon = !this.isFromTon;
270
+ }
271
+ this.pair = toPair;
272
+ },
273
+ resetState(): void {
274
+ this.isRecover = false;
275
+ this.lt = 0;
276
+ this.hash = '';
277
+ this.amountInner = '';
278
+ this.toAddress = '';
279
+ },
280
+ loadState(): void {
281
+ if (!supportsLocalStorage) {
282
+ return;
283
+ }
284
+
285
+ const raw = localStorage.getItem('bridgeState');
286
+
287
+ if (raw) {
288
+ let state: any;
289
+ try {
290
+ state = JSON.parse(raw);
291
+ } catch (e) {
292
+ return;
293
+ }
294
+
295
+ // for previous version
296
+ if (!state.pair) {
297
+ return;
298
+ }
299
+
300
+ this.amount = state.amount;
301
+ this.toAddress = state.toAddress;
302
+ this.pair = state.pair;
303
+
304
+ this.$nextTick(() => {
305
+ this.$refs.bridgeProcessor.loadState(state.processingState);
306
+ });
307
+ }
308
+ },
309
+ saveState(processingState: any): void {
310
+ if (!supportsLocalStorage) {
311
+ return;
312
+ }
313
+
314
+ const state = {
315
+ amount: this.amount,
316
+ toAddress: this.toAddress,
317
+ pair: this.pair,
318
+ processingState: processingState
319
+ }
320
+
321
+ localStorage.setItem('bridgeState', JSON.stringify(state));
322
+ },
323
+ deleteState(): void {
324
+ if (!supportsLocalStorage) {
325
+ return;
326
+ }
327
+
328
+ localStorage.removeItem('bridgeState');
329
+ },
330
+ onInterfaceBlocked(isBlocked: boolean): void {
331
+ this.isInterfaceBlocked = isBlocked;
332
+ },
333
+ toggleFromTon(): void {
334
+ if (this.isInterfaceBlocked) {
335
+ return
336
+ }
337
+ this.isFromTon = !this.isFromTon;
338
+ },
339
+ async getPairGasFee(): Promise<void> {
340
+ let data;
341
+ let gasPrice = 0;
342
+
343
+ try {
344
+ const response = await fetch(this.params.getGasUrl, {
345
+ method: 'GET',
346
+ headers: {
347
+ 'Cache-Control': 'no-store, max-age=0'
348
+ }
349
+ });
350
+
351
+ if (!response.ok) {
352
+ throw new Error(`An error has occured: ${response.status}`);
353
+ }
354
+
355
+ data = await response.json();
356
+ } catch (e) {
357
+ this.gasPrice = 0;
358
+ return;
359
+ }
360
+
361
+ if (this.pair === 'eth') {
362
+ gasPrice = parseFloat(data.average) / 10;
363
+ }
364
+
365
+ if (this.pair === 'bsc') {
366
+ gasPrice = parseFloat(data.result.SafeGasPrice);
367
+ }
368
+
369
+ this.gasPrice = gasPrice > 0 ? gasPrice : this.params.defaultGwei;
370
+ }
371
+ }
372
+ })
373
+ </script>
374
+
375
+
376
+ <style lang="less" scoped>
377
+ @r: .Bridge;
378
+
379
+ @{r} {
380
+ &-testnetWarning {
381
+ position: absolute;
382
+ left: 0;
383
+ top: 0;
384
+ color: white;
385
+ width: 100%;
386
+ padding: 8px 0;
387
+ text-align: center;
388
+ background: red;
389
+ font-weight: bold;
390
+ }
391
+
392
+ &-content {
393
+ display: flex;
394
+ flex-direction: column;
395
+ align-items: center;
396
+ padding: 100px 40px 10px;
397
+
398
+ @media (max-width: 800px) {
399
+ padding: 48px 16px 10px;
400
+ }
401
+ }
402
+
403
+ &-img {
404
+ background-image: url('~assets/pics/swap.svg');
405
+ background-size: contain;
406
+ background-repeat: no-repeat;
407
+ background-position: center;
408
+ max-width: 450px;
409
+ width: 100%;
410
+ height: 450px;
411
+ transition: transform 0.15s ease-out;
412
+ transform: scale(-1, 1);
413
+
414
+ @media (max-width: 800px) {
415
+ height: 300px;
416
+ }
417
+
418
+ &.isFromTon {
419
+ transform: none;
420
+ }
421
+ }
422
+
423
+ &-form {
424
+ text-align: center;
425
+ display: flex;
426
+ flex-direction: column;
427
+ align-items: center;
428
+ max-width: 500px;
429
+ width: 100%;
430
+ }
431
+
432
+ &-switchers {
433
+ width: 100%;
434
+ display: flex;
435
+ flex-direction: row-reverse;
436
+ align-items: center;
437
+ margin-bottom: 40px;
438
+
439
+ &.isFromTon {
440
+ flex-direction: row;
441
+ }
442
+ }
443
+
444
+ &-switcher {
445
+ position: relative;
446
+ flex: 1 0;
447
+
448
+ &Title {
449
+ position: relative;
450
+ font-size: 36px;
451
+ font-weight: bold;
452
+ cursor: pointer;
453
+ white-space: nowrap;
454
+
455
+ @media (max-width: 800px) {
456
+ font-size: 22px;
457
+ }
458
+
459
+ &.disabled {
460
+ cursor: default;
461
+ pointer-events: none;
462
+ }
463
+
464
+ span {
465
+ white-space: normal;
466
+ }
467
+
468
+ em {
469
+ display: inline-block;
470
+ vertical-align: 5px;
471
+ width: 0;
472
+ height: 0;
473
+ border-style: solid;
474
+ border-width: 10px 5px 0 5px;
475
+ border-color: #000 transparent transparent transparent;
476
+ }
477
+ }
478
+
479
+
480
+ // .isPointer &Title:hover &List,
481
+ // .isTouch &Title:active &List {
482
+ &Title:hover &List {
483
+ transition: opacity 0.15s ease-in-out;
484
+ opacity: 1;
485
+ visibility: inherit;
486
+ }
487
+
488
+ &Anno {
489
+ margin-top: 4px;
490
+ height: 20px;
491
+
492
+ a {
493
+ display: inline-block;
494
+ color: #000;
495
+ border-bottom: 1px dotted #AAA;
496
+
497
+ .isPointer &:hover,
498
+ .isTouch &:active {
499
+ border-bottom: 1px dotted transparent;
500
+ }
501
+
502
+ &:after {
503
+ content: '';
504
+ display: inline-block;
505
+ height: 16px;
506
+ width: 16px;
507
+ background-image: url('~assets/pics/link.svg');
508
+ background-repeat: no-repeat;
509
+ background-size: contain;
510
+ background-position: 0 3px;
511
+
512
+ @media (max-width: 800px) {
513
+ display: none
514
+ };
515
+ }
516
+ }
517
+
518
+ @media (max-width: 800px) {
519
+ font-size: 12px;
520
+ }
521
+ }
522
+
523
+ &List {
524
+ background: #FFF;
525
+ border-radius: 16px;
526
+ box-shadow: 0px 8px 24px rgb(48 55 87 / 12%);
527
+ box-sizing: border-box;
528
+ color: #303757;
529
+ font-size: 16px;
530
+ left: -16px;
531
+ line-height: 20px;
532
+ list-style-type: none;
533
+ margin: 0;
534
+ padding: 12px 24px;
535
+ position: absolute;
536
+ right: -16px;
537
+ top: 100%;
538
+ word-break: break-word;
539
+ white-space: normal;
540
+
541
+ transition: all 0 ease-in-out;
542
+ opacity: 0;
543
+ visibility: hidden;
544
+
545
+ &:before {
546
+ content: '';
547
+ position: absolute;
548
+ top: -20px;
549
+ width: 100%;
550
+ left: 0;
551
+ height: 20px;
552
+ }
553
+
554
+ li {
555
+ button {
556
+ padding: 10px 0;
557
+ color: #303757;
558
+ font-weight: 700;
559
+ cursor: pointer;
560
+
561
+ .isPointer &:hover,
562
+ .isTouch &:active {
563
+ color: #1d98dc;
564
+ }
565
+ }
566
+ }
567
+
568
+ }
569
+ }
570
+
571
+ &-switcher-arrow {
572
+ cursor: pointer;
573
+ background-image: url('~assets/pics/arrow.svg');
574
+ background-size: contain;
575
+ background-repeat: no-repeat;
576
+ background-position: center;
577
+ width: 32px;
578
+ height: 32px;
579
+ margin-left: 16px;
580
+ margin-right: 16px;
581
+
582
+ &[disabled] {
583
+ cursor: default;
584
+ }
585
+ }
586
+
587
+ &-inputWrapper {
588
+ width: 100%;
589
+
590
+ input {
591
+ line-height: 36px;
592
+ width: 100%;
593
+ max-width: 500px;
594
+ padding: 8px;
595
+ font-size: 18px;
596
+ border: 1px solid #ccc;
597
+ border-radius: 8px;
598
+ margin-top: 8px;
599
+ margin-bottom: 20px;
600
+ -webkit-appearance: none;
601
+
602
+ &[disabled] {
603
+ color: gray;
604
+ }
605
+ }
606
+ }
607
+
608
+ &-pairFee {
609
+ color: #666666;
610
+ margin-bottom: 4px;
611
+ }
612
+
613
+ &-bridgeFee {
614
+ color: #666666;
615
+ margin-bottom: 10px;
616
+ }
617
+
618
+ &-footer {
619
+ margin-top: 100px;
620
+ text-align: center;
621
+ font-size: 12px;
622
+ color: #666666;
623
+
624
+ a {
625
+ color: #666666;
626
+ text-decoration: underline;
627
+
628
+ .isPointer &:hover,
629
+ .isTouch &:active {
630
+ text-decoration: none;
631
+ }
632
+ }
633
+ }
634
+ }
635
+ </style>
Binary file
package/tsconfig.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2018",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "resolveJsonModule": true,
7
+ "lib": [
8
+ "ESNext",
9
+ "ESNext.AsyncIterable",
10
+ "DOM"
11
+ ],
12
+ "esModuleInterop": true,
13
+ "allowJs": true,
14
+ "sourceMap": true,
15
+ "strict": true,
16
+ "noEmit": true,
17
+ "experimentalDecorators": true,
18
+ "baseUrl": ".",
19
+ "paths": {
20
+ "~/*": [
21
+ "./*"
22
+ ],
23
+ "@/*": [
24
+ "./*"
25
+ ]
26
+ },
27
+ "types": [
28
+ "@nuxt/types",
29
+ "@nuxtjs/axios",
30
+ "@types/node",
31
+ "nuxt-i18n"
32
+ ]
33
+ },
34
+ "exclude": [
35
+ "node_modules",
36
+ ".nuxt",
37
+ "dist"
38
+ ]
39
+ }