Ux and details update (#77)

* fix: added the metadata base

* tidy: refactor the config structure

* fix: fixed the denom and fetching shenanigans

* fix: get rid of injective

* fix: removed logs

* tidy: updated dependencies

* fix: replaced static fallbacks with networkConfig.asset.base

* fix: remove memo

* tidy: added TODO comment

* fix: fixed the accountDetails

* fix: fixed the wallet connector suffix
This commit is contained in:
Linkie Link 2022-12-23 12:23:00 +01:00 committed by GitHub
parent 83fa513bf0
commit 6efa380a98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 811 additions and 465 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

9
public/browserconfig.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#ffffff</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
public/mstile-144x144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
public/mstile-150x150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
public/mstile-310x150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
public/mstile-310x310.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
public/mstile-70x70.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

2
public/robots.txt Normal file
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@ -0,0 +1,247 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3405 6875 c-44 -12 -642 -268 -654 -280 -2 -3 158 -5 357 -5 l362 0
0 150 c0 83 -3 150 -7 149 -5 0 -30 -6 -58 -14z"/>
<path d="M3530 6739 l0 -149 363 0 c209 0 356 4 347 9 -53 31 -642 279 -672
284 l-38 6 0 -150z"/>
<path d="M3865 6832 c10 -9 519 -232 529 -232 7 0 99 130 95 134 -2 2 -139 25
-304 51 -165 25 -307 48 -315 51 -9 3 -11 2 -5 -4z"/>
<path d="M2795 6783 c-154 -25 -282 -47 -284 -49 -4 -4 88 -134 95 -134 4 0
351 150 499 216 l30 13 -30 0 c-16 -1 -156 -21 -310 -46z"/>
<path d="M2148 6573 c-158 -81 -285 -149 -284 -151 5 -4 660 150 668 157 7 6
-81 141 -92 141 -3 0 -134 -67 -292 -147z"/>
<path d="M4511 6656 c-25 -35 -44 -67 -43 -72 1 -8 649 -165 665 -161 7 2
-564 297 -574 297 -2 0 -24 -29 -48 -64z"/>
<path d="M2797 6325 c80 -113 148 -205 152 -205 8 0 461 398 461 405 0 3 -171
5 -379 5 l-380 0 146 -205z"/>
<path d="M3811 6325 c128 -113 236 -205 239 -205 7 0 290 394 290 404 0 3
-171 6 -380 6 l-381 0 232 -205z"/>
<path d="M3261 6312 l-234 -207 237 -3 c130 -1 342 -1 473 0 l236 3 -233 205
c-128 113 -235 206 -239 207 -3 1 -111 -91 -240 -205z"/>
<path d="M2246 6208 c-185 -167 -332 -304 -326 -306 11 -4 927 175 952 186 14
6 -9 43 -130 214 -81 114 -150 208 -154 208 -4 0 -158 -136 -342 -302z"/>
<path d="M4258 6302 c-121 -171 -144 -208 -130 -214 24 -10 943 -189 953 -186
9 3 -643 596 -664 603 -7 3 -76 -86 -159 -203z"/>
<path d="M2040 6401 c-405 -97 -500 -124 -500 -143 0 -10 247 -355 260 -363 5
-3 534 466 679 601 12 11 -67 -6 -439 -95z"/>
<path d="M4521 6496 c174 -161 674 -604 679 -601 13 8 260 353 260 363 0 20
-92 46 -503 143 -394 93 -446 105 -436 95z"/>
<path d="M1448 6182 c-33 -33 -490 -773 -483 -780 4 -4 755 426 773 443 11 10
-10 45 -113 186 -70 96 -130 177 -134 181 -4 5 -23 -9 -43 -30z"/>
<path d="M5381 6039 c-107 -147 -130 -184 -119 -194 18 -16 769 -447 773 -443
7 8 -451 747 -484 781 l-38 39 -132 -183z"/>
<path d="M3022 6008 c14 -18 124 -174 247 -345 122 -172 226 -313 231 -313 5
0 109 141 231 313 122 171 233 327 247 345 l24 32 -502 0 -502 0 24 -32z"/>
<path d="M2350 5924 c-261 -52 -481 -97 -487 -99 -11 -4 355 -524 407 -578 17
-18 24 -10 185 210 430 582 416 563 392 562 -12 -1 -236 -44 -497 -95z"/>
<path d="M4213 5908 c45 -62 177 -241 291 -396 200 -272 209 -283 226 -265 51
54 418 574 407 578 -22 8 -975 195 -991 195 -11 0 12 -38 67 -112z"/>
<path d="M2643 5613 c-161 -219 -291 -399 -289 -400 4 -5 1078 96 1083 101 6
6 -486 696 -495 696 -4 0 -139 -179 -299 -397z"/>
<path d="M3805 5665 c-136 -191 -245 -348 -243 -351 5 -5 1080 -105 1084 -101
5 4 -576 791 -586 795 -5 2 -119 -153 -255 -343z"/>
<path d="M995 5730 l-229 -229 38 -55 c37 -54 64 -83 70 -75 1 2 76 126 166
274 90 149 170 280 178 293 8 12 13 22 11 22 -2 0 -107 -103 -234 -230z"/>
<path d="M5782 5940 c8 -14 90 -150 183 -302 l168 -278 48 65 c27 35 49 68 49
72 0 5 -104 112 -232 238 -127 127 -225 219 -216 205z"/>
<path d="M1546 5334 c-136 -245 -246 -447 -244 -449 5 -5 910 294 921 305 8 7
-409 590 -422 590 -3 0 -118 -201 -255 -446z"/>
<path d="M4981 5489 c-116 -159 -211 -293 -211 -297 1 -8 922 -313 928 -307 5
5 -491 895 -499 895 -4 0 -101 -131 -218 -291z"/>
<path d="M1313 5531 c-216 -124 -393 -230 -393 -234 0 -4 68 -100 152 -212
130 -176 153 -202 163 -187 28 42 477 853 474 856 -2 1 -181 -99 -396 -223z"/>
<path d="M5294 5743 c8 -19 452 -816 471 -845 10 -16 32 9 163 186 84 113 152
208 152 213 0 4 -80 54 -178 109 -97 56 -275 159 -396 228 -136 79 -216 120
-212 109z"/>
<path d="M583 5158 c-78 -155 -141 -283 -140 -284 1 -1 52 55 113 125 61 69
148 168 194 218 l82 93 -48 65 c-26 36 -50 65 -53 65 -3 0 -70 -127 -148 -282z"/>
<path d="M6216 5375 l-48 -65 139 -157 c76 -86 163 -184 193 -219 30 -34 56
-61 57 -60 4 4 -282 566 -288 566 -3 0 -27 -29 -53 -65z"/>
<path d="M2868 5200 c-278 -26 -511 -49 -517 -51 -9 -4 567 -808 579 -809 5 0
501 879 508 900 5 14 -6 13 -570 -40z"/>
<path d="M3562 5240 c10 -29 504 -899 509 -897 9 3 588 801 585 805 -3 3
-1047 102 -1079 102 -10 0 -17 -4 -15 -10z"/>
<path d="M877 5233 c-4 -8 -166 -501 -213 -651 l-23 -74 22 15 c12 7 128 76
257 152 129 76 241 144 249 150 11 11 -11 46 -130 206 -167 228 -155 213 -162
202z"/>
<path d="M5967 5038 c-84 -112 -145 -204 -140 -209 17 -17 516 -309 521 -305
5 5 -217 697 -227 708 -3 3 -73 -84 -154 -194z"/>
<path d="M3243 4771 c-139 -248 -253 -452 -253 -455 0 -3 230 -6 510 -6 281 0
510 3 510 6 0 9 -505 904 -510 904 -3 0 -119 -202 -257 -449z"/>
<path d="M555 4910 c-198 -224 -276 -324 -263 -335 2 -1 65 -23 140 -48 l138
-45 111 340 c61 187 109 341 107 343 -2 2 -107 -113 -233 -255z"/>
<path d="M6210 5165 c0 -5 50 -161 110 -346 l110 -337 138 45 c75 25 138 47
140 48 14 11 -69 117 -263 335 -264 296 -235 265 -235 255z"/>
<path d="M1745 4965 c-258 -86 -459 -158 -458 -164 2 -8 477 -655 499 -680 2
-2 6 -2 9 1 16 16 431 998 422 997 -7 -1 -219 -70 -472 -154z"/>
<path d="M4804 5043 c19 -43 116 -269 216 -503 100 -234 183 -426 184 -427 1
-2 118 153 259 344 142 191 254 350 250 354 -8 6 -925 309 -937 309 -3 0 10
-35 28 -77z"/>
<path d="M2286 5101 c-11 -17 -436 -1005 -433 -1007 3 -3 1017 203 1022 208 3
2 -562 788 -580 806 -2 2 -6 -1 -9 -7z"/>
<path d="M4413 4707 c-160 -221 -290 -403 -288 -406 4 -3 1019 -210 1022 -207
3 2 -428 1000 -435 1008 -4 4 -139 -174 -299 -395z"/>
<path d="M896 4595 c-142 -85 -261 -156 -264 -159 -6 -6 239 -576 247 -576 5
0 278 830 289 876 2 8 0 14 -5 13 -4 0 -124 -70 -267 -154z"/>
<path d="M1083 4283 c-84 -257 -151 -469 -150 -470 4 -4 801 248 809 255 6 7
-483 674 -499 679 -5 2 -77 -207 -160 -464z"/>
<path d="M5504 4414 c-137 -185 -249 -339 -249 -342 0 -7 806 -264 811 -259 5
5 -301 937 -307 937 -3 0 -118 -151 -255 -336z"/>
<path d="M5832 4733 c21 -75 284 -873 289 -873 7 0 253 570 247 575 -8 8 -528
315 -534 315 -4 0 -4 -8 -2 -17z"/>
<path d="M266 4503 c-11 -28 -5 -131 24 -428 17 -165 30 -307 30 -314 0 -9 3
-11 9 -5 12 13 224 665 217 671 -2 3 -65 24 -140 48 -111 35 -136 40 -140 28z"/>
<path d="M6591 4473 c-73 -23 -136 -44 -138 -47 -6 -5 206 -658 218 -670 6 -6
9 -2 9 10 0 10 14 154 30 319 30 305 36 402 22 421 -5 7 -51 -4 -141 -33z"/>
<path d="M6282 4074 c-68 -157 -121 -288 -118 -291 7 -8 470 -152 474 -148 4
3 -215 689 -227 712 -4 7 -62 -116 -129 -273z"/>
<path d="M588 4343 c-11 -18 -230 -705 -226 -708 4 -4 467 141 475 148 5 5
-224 544 -238 560 -4 5 -9 5 -11 0z"/>
<path d="M3000 4244 c0 -11 492 -684 500 -684 8 0 500 673 500 684 0 3 -225 6
-500 6 -275 0 -500 -3 -500 -6z"/>
<path d="M2367 4137 c-329 -66 -497 -104 -495 -112 5 -19 693 -763 699 -756 4
3 66 191 139 416 184 568 180 555 167 554 -7 -1 -236 -46 -510 -102z"/>
<path d="M4124 4199 c54 -176 300 -925 305 -930 7 -7 694 737 699 756 2 8
-155 43 -485 109 -268 54 -498 100 -510 103 -22 5 -22 4 -9 -38z"/>
<path d="M2830 3869 c-61 -189 -131 -404 -155 -478 -25 -74 -43 -136 -42 -138
3 -3 809 256 815 262 4 3 -470 658 -493 684 -11 11 -33 -48 -125 -330z"/>
<path d="M3800 3864 c-138 -190 -250 -347 -248 -349 6 -5 812 -265 814 -262 4
3 -303 947 -309 953 -3 3 -118 -151 -257 -342z"/>
<path d="M166 3874 c-27 -168 -46 -307 -43 -311 7 -6 144 34 150 45 5 8 -48
561 -55 567 -2 2 -26 -133 -52 -301z"/>
<path d="M6776 4150 c-3 -19 -15 -134 -26 -255 -11 -121 -23 -236 -26 -256
l-5 -35 75 -24 c42 -13 79 -21 82 -17 5 5 -79 576 -90 612 -2 6 -6 -6 -10 -25z"/>
<path d="M1346 3879 c-225 -71 -410 -130 -412 -131 -1 -2 19 -32 45 -68 27
-36 158 -218 292 -404 198 -277 244 -336 250 -320 10 23 240 1046 237 1049 -2
2 -187 -55 -412 -126z"/>
<path d="M5243 3987 c3 -12 56 -245 117 -517 61 -272 114 -504 118 -514 7 -16
61 54 299 385 159 222 289 405 289 406 -1 1 -175 57 -387 123 -211 66 -397
125 -413 130 -26 9 -28 8 -23 -13z"/>
<path d="M1694 3448 c-66 -293 -117 -534 -113 -536 3 -1 215 65 470 148 255
83 468 151 472 153 9 3 -691 767 -702 767 -4 0 -61 -240 -127 -532z"/>
<path d="M4844 3623 c-345 -375 -369 -401 -362 -409 8 -7 930 -305 937 -302 9
4 -231 1068 -240 1068 -3 0 -154 -161 -335 -357z"/>
<path d="M590 3643 c-129 -41 -236 -76 -237 -77 -3 -3 348 -791 365 -822 14
-24 12 -32 72 476 27 234 52 442 56 463 4 27 2 37 -8 36 -7 -1 -119 -35 -248
-76z"/>
<path d="M6154 3684 c3 -22 28 -230 56 -464 27 -234 52 -441 56 -460 5 -31 7
-32 17 -15 17 31 367 818 364 820 -2 2 -423 134 -481 152 -16 4 -17 1 -12 -33z"/>
<path d="M900 3669 c0 -8 -27 -240 -60 -514 -32 -275 -58 -501 -56 -502 3 -4
687 216 695 223 4 3 -539 767 -565 794 -12 12 -14 12 -14 -1z"/>
<path d="M5810 3288 c-157 -219 -286 -401 -288 -406 -2 -7 687 -236 694 -229
3 2 -110 968 -119 1017 -1 8 -130 -164 -287 -382z"/>
<path d="M188 3516 c-37 -12 -70 -25 -73 -28 -5 -5 90 -629 99 -653 3 -5 5 1
5 14 1 30 49 604 55 654 5 43 5 43 -86 13z"/>
<path d="M6726 3503 c5 -43 54 -627 55 -658 0 -11 2 -15 5 -10 7 18 105 647
101 651 -5 5 -148 54 -158 54 -4 0 -5 -17 -3 -37z"/>
<path d="M3058 3327 c-219 -72 -398 -134 -398 -138 0 -7 782 -579 802 -587 4
-2 8 190 8 427 0 237 -3 431 -7 430 -5 -1 -187 -60 -405 -132z"/>
<path d="M3530 3029 c0 -236 2 -429 5 -429 3 0 537 386 764 553 l53 39 -363
119 c-200 66 -385 126 -411 133 l-48 15 0 -430z"/>
<path d="M326 3428 c-9 -44 -66 -784 -66 -853 0 -38 4 -75 8 -81 5 -7 73 10
215 56 114 37 211 70 214 74 5 5 -355 826 -363 826 -2 0 -6 -10 -8 -22z"/>
<path d="M6480 3040 c-100 -226 -180 -413 -177 -416 3 -4 100 -37 214 -74 142
-46 210 -63 215 -56 4 6 8 45 8 86 -1 88 -64 858 -72 865 -3 3 -88 -179 -188
-405z"/>
<path d="M2070 3006 c-256 -84 -465 -156 -465 -161 1 -11 814 -729 820 -724 2
2 28 222 59 489 31 267 58 500 61 518 3 17 2 32 -2 31 -4 0 -217 -69 -473
-153z"/>
<path d="M4454 3123 c3 -21 31 -254 61 -517 31 -264 57 -482 60 -484 6 -6 819
712 818 723 -1 7 -917 314 -941 315 -2 0 -1 -17 2 -37z"/>
<path d="M2545 2630 c-32 -280 -56 -512 -53 -515 5 -6 923 409 940 424 6 6
-794 593 -817 599 -7 2 -31 -175 -70 -508z"/>
<path d="M3968 2842 c-224 -163 -404 -300 -400 -303 16 -15 934 -430 939 -425
10 10 -111 1026 -122 1025 -5 0 -193 -134 -417 -297z"/>
<path d="M1152 2707 c-189 -62 -343 -116 -343 -120 0 -4 157 -177 348 -384
l348 -376 2 289 c2 159 0 382 -5 496 l-7 206 -343 -111z"/>
<path d="M5495 2617 c-3 -111 -5 -334 -3 -495 l3 -294 348 376 c191 206 348
379 348 383 1 6 -442 156 -642 217 l-47 14 -7 -201z"/>
<path d="M1561 2498 c1 -161 5 -386 8 -499 l6 -206 409 137 409 136 -404 355
c-222 195 -410 358 -416 362 -10 7 -13 -53 -12 -285z"/>
<path d="M5020 2429 l-412 -362 409 -139 c224 -76 409 -138 409 -138 5 0 16
992 11 996 -2 3 -190 -158 -417 -357z"/>
<path d="M495 2494 c-110 -37 -202 -68 -204 -70 -13 -12 82 -133 323 -413 152
-176 282 -323 288 -327 7 -5 9 1 5 17 -3 13 -45 212 -93 442 -70 329 -92 417
-104 417 -8 0 -105 -30 -215 -66z"/>
<path d="M6181 2124 c-50 -240 -90 -438 -87 -441 7 -8 575 656 597 699 11 22
19 41 17 43 -7 6 -407 135 -420 135 -11 0 -37 -108 -107 -436z"/>
<path d="M802 2480 c21 -115 183 -867 189 -874 7 -8 465 138 483 154 4 5 -137
165 -314 357 -402 433 -363 394 -358 363z"/>
<path d="M5856 2134 c-186 -201 -334 -369 -330 -374 15 -13 475 -162 481 -156
7 7 193 877 190 888 -1 4 -154 -158 -341 -358z"/>
<path d="M2993 2272 c-260 -119 -473 -219 -473 -222 1 -8 941 -563 946 -558 2
3 3 228 2 500 l-3 495 -472 -215z"/>
<path d="M3530 1990 c0 -275 3 -500 6 -500 10 0 943 554 944 560 0 4 -803 376
-922 427 l-28 12 0 -499z"/>
<path d="M451 2105 c6 -15 291 -579 295 -584 6 -6 154 41 160 51 3 4 -95 124
-217 265 -245 284 -243 282 -238 268z"/>
<path d="M6316 1843 c-125 -146 -224 -268 -220 -273 16 -14 143 -52 154 -45 9
6 301 577 297 581 -1 1 -105 -117 -231 -263z"/>
<path d="M2008 1877 c-212 -73 -389 -135 -392 -138 -4 -3 172 -135 390 -293
217 -158 397 -286 399 -284 2 2 7 194 11 426 6 360 5 422 -7 421 -8 0 -188
-59 -401 -132z"/>
<path d="M4583 1589 c3 -232 8 -423 11 -426 2 -3 183 125 400 283 218 158 393
291 389 294 -9 7 -785 270 -798 270 -5 0 -5 -190 -2 -421z"/>
<path d="M2477 1798 c-9 -274 -9 -658 1 -658 14 -1 942 295 942 300 0 4 -622
376 -901 539 l-36 21 -6 -202z"/>
<path d="M4048 1722 c-258 -152 -468 -279 -468 -282 0 -5 929 -301 943 -300 8
0 7 355 -2 657 l-6 203 -467 -278z"/>
<path d="M1278 1632 c-126 -42 -229 -81 -230 -87 -1 -10 594 -447 600 -440 2
2 -26 136 -62 299 -36 163 -66 298 -66 301 0 8 -6 7 -242 -73z"/>
<path d="M5477 1688 c-27 -108 -127 -573 -125 -579 4 -9 600 422 602 435 1 7
-247 95 -455 161 -11 4 -19 -2 -22 -17z"/>
<path d="M1590 1662 c0 -16 131 -596 136 -601 6 -6 624 52 624 58 0 6 -669
494 -731 534 -16 11 -29 14 -29 9z"/>
<path d="M5023 1397 c-205 -150 -373 -275 -373 -278 0 -6 618 -65 624 -58 4 4
136 588 136 602 0 4 -3 7 -7 6 -5 0 -176 -123 -380 -272z"/>
<path d="M873 1497 c-34 -12 -64 -24 -67 -27 -3 -3 96 -107 220 -230 l226
-225 -44 75 c-204 348 -254 430 -263 429 -5 0 -38 -10 -72 -22z"/>
<path d="M5922 1313 c-67 -115 -134 -228 -148 -253 -20 -33 32 13 199 180 125
123 225 225 224 227 -5 4 -137 53 -145 53 -5 0 -63 -93 -130 -207z"/>
<path d="M1081 1419 c9 -13 88 -148 177 -299 89 -152 177 -290 195 -308 l34
-33 63 88 c35 48 74 102 87 120 l24 31 -287 209 c-158 114 -292 210 -298 212
-6 2 -3 -7 5 -20z"/>
<path d="M5635 1234 c-154 -112 -283 -208 -287 -212 -4 -4 31 -60 79 -125 l85
-119 34 33 c40 39 392 632 373 628 -2 0 -130 -92 -284 -205z"/>
<path d="M2998 1242 c-251 -81 -459 -149 -462 -152 -3 -3 194 -97 437 -210
243 -112 454 -209 470 -217 l27 -14 0 371 c0 203 -3 370 -7 369 -5 -1 -214
-67 -465 -147z"/>
<path d="M3530 1021 c0 -351 1 -371 18 -363 9 5 221 103 470 217 248 115 449
212 445 216 -5 4 -210 71 -458 149 -247 79 -456 145 -462 147 -10 4 -13 -73
-13 -366z"/>
<path d="M2065 1031 c-148 -14 -270 -29 -270 -33 0 -5 560 -416 603 -442 9 -6
12 47 12 248 l0 256 -37 -1 c-21 -1 -159 -13 -308 -28z"/>
<path d="M4590 805 c0 -213 2 -255 14 -248 7 4 147 105 310 223 225 163 292
217 279 222 -14 5 -560 58 -595 58 -5 0 -8 -115 -8 -255z"/>
<path d="M2467 792 c-4 -140 -5 -258 -2 -261 3 -6 880 82 907 91 10 4 -145 77
-738 351 l-161 74 -6 -255z"/>
<path d="M4071 836 c-250 -116 -449 -212 -442 -214 24 -8 902 -98 905 -92 1 3
0 120 -3 260 l-6 256 -454 -210z"/>
<path d="M1622 866 c-45 -62 -82 -118 -82 -123 0 -6 20 -18 43 -27 51 -19 676
-158 690 -153 9 3 -553 417 -565 417 -3 0 -41 -51 -86 -114z"/>
<path d="M5010 780 c-271 -198 -321 -236 -290 -226 8 3 161 37 339 76 321 71
401 93 401 112 0 11 -162 238 -170 238 -3 -1 -129 -91 -280 -200z"/>
<path d="M1960 524 c69 -36 196 -101 283 -145 l157 -79 0 85 c0 80 -1 85 -22
90 -181 41 -524 115 -532 115 -6 0 45 -30 114 -66z"/>
<path d="M4871 529 c-146 -32 -269 -63 -274 -68 -6 -6 -7 -40 -2 -85 l7 -75
156 79 c258 130 408 210 392 209 -8 0 -134 -27 -279 -60z"/>
<path d="M3205 545 c-115 -13 -306 -33 -422 -46 -117 -12 -213 -25 -213 -28 0
-3 62 -32 138 -63 75 -31 261 -108 412 -171 151 -63 292 -117 313 -120 l37 -6
0 230 0 229 -27 -1 c-16 -1 -122 -12 -238 -24z"/>
<path d="M3530 340 l0 -230 25 5 c14 3 37 8 52 11 24 5 811 331 822 340 2 2 2
6 0 8 -3 3 -868 96 -891 96 -5 0 -8 -104 -8 -230z"/>
<path d="M2460 359 c0 -49 3 -89 6 -89 3 0 148 -23 321 -50 174 -28 318 -49
320 -47 3 4 -98 47 -519 223 l-128 53 0 -90z"/>
<path d="M4203 308 c-172 -73 -311 -133 -309 -135 2 -2 146 19 321 47 174 27
319 50 321 50 2 0 4 38 4 85 0 62 -3 85 -12 85 -7 -1 -154 -60 -325 -132z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

19
public/site.webmanifest Normal file
View File

@ -0,0 +1,19 @@
{
"name": "Mars V2",
"short_name": "MarsV2",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

18
public/tokens/cro.svg Normal file
View File

@ -0,0 +1,18 @@
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 120.1 138.8" style="enable-background:new 0 0 120.1 138.8;" xml:space="preserve">
<path fill="#002D74" d="M60.1,0L0,34.7v69.4l60.1,34.7l60-34.7V34.7L60.1,0z M102.3,93.8l-42.3,24.4L17.8,93.8V45l42.3-24.4L102.3,45
V93.8z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="90.1166" y1="1.0868" x2="90.1166" y2="70.4884" gradientTransform="matrix(1 0 0 -1 0 139.8898)">
<stop offset="0" style="stop-color:#002D74"/>
<stop offset="1" style="stop-color:#002D74;stop-opacity:0"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M60.1,138.8l60-34.7V34.7L60.1,0v20.6L102.3,45v48.9l-42.3,24.4V138.8z"/>
<linearGradient id="SVGID_00000034064843000503835000000005854543727190432132_" gradientUnits="userSpaceOnUse" x1="30.0233" y1="139.8898" x2="30.0233" y2="70.4884" gradientTransform="matrix(1 0 0 -1 0 139.8898)">
<stop offset="0" style="stop-color:#002D74"/>
<stop offset="1" style="stop-color:#002D74;stop-opacity:0"/>
</linearGradient>
<path fill="url(#SVGID_00000034064843000503835000000005854543727190432132_)" d="M60,0L0,34.7v69.4l60,34.7v-20.6L17.8,93.8
V44.9L60,20.6V0z"/>
<path fill="#002D74" d="M88.1,85.6l-28,16.2L32,85.6V53.2L60.1,37l28,16.2L76.4,60l-16.4-9.5L43.7,60v18.9l16.4,9.5l16.4-9.5L88.1,85.6
z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

29
public/tokens/mars.svg Normal file
View File

@ -0,0 +1,29 @@
<svg width="100%" height="100%" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;">
<path d="M12.985,0.812C13.949,0.812 14.279,0.928 14.929,1.155C15.091,1.211 15.273,1.275 15.49,1.345C19.947,2.795 23.25,7.071 23.25,12.005C23.25,12.829 23.133,13.721 22.963,14.506C22.196,17.622 20.213,20.269 17.543,21.804C16.213,22.568 14.67,23.131 13.068,23.239C12.8,23.257 11.93,23.249 11.339,23.243C11.126,23.241 10.95,23.239 10.85,23.239C5.061,22.419 0.75,18.142 0.75,12.005C0.75,10.447 1.047,8.887 1.653,7.454C2.282,5.968 3.362,4.699 4.486,3.6C5.476,2.634 6.7,2.1 7.906,1.574C8.081,1.498 8.255,1.422 8.428,1.345C9.05,1.068 9.469,1.008 9.996,0.932C10.214,0.9 10.45,0.866 10.727,0.812C11.214,0.719 11.726,0.75 12.234,0.781C12.486,0.797 12.738,0.812 12.985,0.812Z" style="fill:url(#_Linear1);fill-rule:nonzero;"/>
<path d="M12.985,0.812C13.949,0.812 14.279,0.928 14.929,1.155C15.091,1.211 15.273,1.275 15.49,1.345C19.947,2.795 23.25,7.071 23.25,12.005C23.25,12.829 23.133,13.721 22.963,14.506C22.196,17.622 20.213,20.269 17.543,21.804C16.213,22.568 14.67,23.131 13.068,23.239C12.8,23.257 11.93,23.249 11.339,23.243C11.126,23.241 10.95,23.239 10.85,23.239C5.061,22.419 0.75,18.142 0.75,12.005C0.75,10.447 1.047,8.887 1.653,7.454C2.282,5.968 3.362,4.699 4.486,3.6C5.476,2.634 6.7,2.1 7.906,1.574C8.081,1.498 8.255,1.422 8.428,1.345C9.05,1.068 9.469,1.008 9.996,0.932C10.214,0.9 10.45,0.866 10.727,0.812C11.214,0.719 11.726,0.75 12.234,0.781C12.486,0.797 12.738,0.812 12.985,0.812Z" style="fill:none;fill-rule:nonzero;stroke:white;stroke-width:1px;"/>
<path d="M11.999,0.166L15.656,0.746L18.955,2.426L21.573,5.044L23.254,8.342L23.834,11.999L23.254,15.656L21.573,18.955L18.955,21.573L15.656,23.254L11.999,23.834L8.343,23.254L5.044,21.573L2.426,18.955L0.746,15.656L0.166,11.999L0.746,8.343L2.426,5.044L5.044,2.426L8.343,0.746L11.999,0.166ZM8.549,1.381L5.436,2.966L2.967,5.436L1.381,8.549L0.834,11.999L1.381,15.45L2.967,18.562L5.436,21.032L8.549,22.619L11.999,23.166L15.45,22.619L18.562,21.032L21.032,18.562L22.619,15.45L23.166,11.999L22.619,8.549L21.032,5.436L18.562,2.966L15.45,1.381L11.999,0.834L8.549,1.381Z" style="fill:white;"/>
<path d="M11.915,3.928C11.993,3.881 12.094,3.907 12.141,3.985L14.738,8.343C14.785,8.421 14.759,8.523 14.681,8.569C14.603,8.616 14.501,8.59 14.455,8.512L11.857,4.154C11.811,4.076 11.836,3.975 11.915,3.928Z" style="fill:white;"/>
<path d="M11.999,3.904L17.36,4.484L17.325,4.812L11.999,4.236L6.674,4.812L6.639,4.484L11.999,3.904Z" style="fill:white;"/>
<path d="M9.237,8.426C9.237,8.334 9.311,8.261 9.402,8.261L14.596,8.261C14.687,8.261 14.761,8.334 14.761,8.426C14.761,8.517 14.687,8.591 14.596,8.591L9.402,8.591C9.311,8.591 9.237,8.517 9.237,8.426Z" style="fill:white;"/>
<path d="M12.083,3.928C12.161,3.975 12.187,4.076 12.14,4.154L9.544,8.512C9.497,8.59 9.396,8.616 9.318,8.569C9.24,8.523 9.214,8.421 9.261,8.343L11.857,3.985C11.903,3.907 12.004,3.881 12.083,3.928Z" style="fill:white;"/>
<path d="M8.392,0.803L11.999,3.853L15.606,0.803L17.49,4.573L17.195,4.721L15.499,1.326L11.999,4.285L8.499,1.326L6.804,4.721L6.509,4.573L8.392,0.803Z" style="fill:white;"/>
<path d="M5.143,2.563C5.217,2.509 5.32,2.525 5.374,2.599L11.999,11.719L18.625,2.599C18.679,2.525 18.782,2.509 18.856,2.563C18.929,2.616 18.946,2.719 18.892,2.793L12.133,12.097C12.102,12.14 12.052,12.165 11.999,12.165C11.947,12.165 11.897,12.14 11.866,12.097L5.107,2.793C5.053,2.719 5.07,2.616 5.143,2.563Z" style="fill:white;"/>
<path d="M9.525,8.314C9.565,8.358 9.578,8.42 9.56,8.476L7.992,13.303L12.081,16.274L16.727,18.266C16.811,18.302 16.85,18.399 16.814,18.482C16.778,18.566 16.681,18.605 16.597,18.569L11.934,16.57C11.923,16.565 11.912,16.559 11.902,16.552L7.701,13.499C7.643,13.457 7.619,13.383 7.641,13.315L9.156,8.651L4.493,9.709C4.404,9.729 4.315,9.674 4.295,9.585C4.275,9.496 4.331,9.408 4.42,9.387L9.367,8.265C9.424,8.251 9.485,8.27 9.525,8.314Z" style="fill:white;"/>
<path d="M4.347,9.426C4.416,9.366 4.52,9.373 4.58,9.442L7.922,13.259C7.982,13.328 7.975,13.432 7.907,13.492C7.838,13.552 7.734,13.545 7.674,13.477L4.332,9.659C4.272,9.591 4.279,9.486 4.347,9.426Z" style="fill:white;"/>
<path d="M6.931,4.439L4.635,9.553L4.661,9.616L4.603,9.652L3.534,14.751L7.435,18.284L12.078,20.948L15.442,22.696L16.535,18.244L21.105,18.581L20.481,14.837L20.807,14.783L21.499,18.941L16.789,18.593L15.662,23.182L11.917,21.236L7.24,18.553L3.238,14.928L0.234,11.971L4.25,9.483L2.464,5.109L6.931,4.439ZM4.215,9.893L0.765,12.03L3.254,14.48L4.215,9.893ZM4.463,9.131L6.382,4.855L2.928,5.373L4.463,9.131Z" style="fill:white;"/>
<path d="M7.814,13.202C7.904,13.211 7.971,13.291 7.963,13.382L7.502,18.433C7.494,18.524 7.414,18.591 7.323,18.583C7.232,18.574 7.165,18.494 7.174,18.403L7.634,13.352C7.642,13.261 7.723,13.194 7.814,13.202Z" style="fill:white;"/>
<path d="M12.151,16.353C12.187,16.436 12.148,16.533 12.065,16.569L7.403,18.569C7.319,18.604 7.222,18.566 7.186,18.482C7.15,18.398 7.189,18.301 7.273,18.265L11.935,16.266C12.018,16.23 12.115,16.269 12.151,16.353Z" style="fill:white;"/>
<path d="M2.893,18.581L3.517,14.837L3.191,14.783L2.499,18.941L7.211,18.594L8.336,23.182L12.075,21.24L11.923,20.947L8.556,22.696L7.465,18.244L2.893,18.581Z" style="fill:white;"/>
<path d="M12.097,11.865C12.14,11.896 12.165,11.946 12.165,11.998L12.165,23.5C12.165,23.591 12.091,23.665 12,23.665C11.909,23.665 11.835,23.591 11.835,23.5L11.835,12.226L1.115,15.709C1.029,15.737 0.936,15.69 0.908,15.603C0.879,15.517 0.927,15.423 1.013,15.395L11.949,11.842C11.999,11.825 12.054,11.834 12.097,11.865Z" style="fill:white;"/>
<path d="M17.212,4.547C17.248,4.499 17.308,4.475 17.368,4.484L21.327,5.078C21.377,5.085 21.421,5.115 21.446,5.159C21.471,5.203 21.474,5.256 21.455,5.303L19.749,9.483L23.587,11.861C23.63,11.887 23.658,11.932 23.664,11.982C23.669,12.033 23.652,12.083 23.616,12.118L20.762,14.926L20.756,14.932L20.755,14.932C20.755,14.933 20.754,14.934 20.753,14.934L16.773,18.541C16.727,18.583 16.661,18.595 16.602,18.572C16.544,18.55 16.504,18.496 16.498,18.434L16.039,13.4L14.44,8.478C14.421,8.421 14.435,8.359 14.475,8.315C14.515,8.272 14.575,8.253 14.633,8.266L19.258,9.315L17.193,4.715C17.168,4.659 17.175,4.595 17.212,4.547ZM19.237,9.649L14.843,8.652L16.269,13.04L19.237,9.649ZM16.372,13.422L16.797,18.074L20.464,14.751L19.45,9.907L16.372,13.422ZM19.784,9.893L20.744,14.48L23.234,12.03L19.784,9.893ZM19.536,9.13L21.07,5.373L17.617,4.855L19.536,9.13Z" style="fill:white;"/>
<path d="M11.842,11.947C11.87,11.861 11.963,11.813 12.05,11.842L22.987,15.395C23.074,15.423 23.121,15.517 23.093,15.603C23.065,15.69 22.972,15.737 22.885,15.709L11.948,12.155C11.861,12.127 11.814,12.034 11.842,11.947Z" style="fill:white;"/>
<path d="M16.335,13.27C16.389,13.343 16.372,13.447 16.298,13.5L12.096,16.552C12.022,16.606 11.919,16.59 11.866,16.516C11.812,16.442 11.828,16.339 11.902,16.285L16.104,13.233C16.178,13.18 16.281,13.196 16.335,13.27Z" style="fill:white;"/>
<path d="M16.58,18.276C16.653,18.234 16.746,18.254 16.796,18.322L18.892,21.208C18.945,21.282 18.929,21.385 18.855,21.439C18.782,21.492 18.678,21.476 18.625,21.402L16.616,18.636L12.081,21.237C12.002,21.282 11.901,21.255 11.856,21.176C11.81,21.097 11.838,20.996 11.917,20.951L16.58,18.276Z" style="fill:white;"/>
<path d="M11.999,0.335C12.09,0.335 12.164,0.409 12.164,0.5L12.164,4.068C12.164,4.159 12.09,4.233 11.999,4.233C11.908,4.233 11.834,4.159 11.834,4.068L11.834,0.5C11.834,0.409 11.908,0.335 11.999,0.335Z" style="fill:white;"/>
<path d="M23.093,8.396C23.121,8.483 23.073,8.576 22.987,8.604L19.594,9.706C19.507,9.735 19.414,9.687 19.386,9.601C19.358,9.514 19.405,9.421 19.492,9.393L22.885,8.29C22.971,8.262 23.064,8.309 23.093,8.396Z" style="fill:white;"/>
<path d="M7.435,18.286C7.509,18.34 7.525,18.443 7.471,18.516L5.374,21.402C5.32,21.476 5.217,21.492 5.143,21.439C5.069,21.385 5.053,21.282 5.107,21.208L7.204,18.322C7.258,18.249 7.361,18.232 7.435,18.286Z" style="fill:white;"/>
<path d="M0.908,8.396C0.936,8.309 1.029,8.262 1.115,8.29L4.508,9.393C4.595,9.421 4.642,9.514 4.614,9.601C4.586,9.687 4.493,9.735 4.406,9.706L1.013,8.604C0.927,8.576 0.879,8.483 0.908,8.396Z" style="fill:white;"/>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-14.8673,-14.7971,14.7971,-14.8673,20.4244,16.9042)"><stop offset="0" style="stop-color:rgb(239,65,54);stop-opacity:1"/><stop offset="0.01" style="stop-color:rgb(239,65,54);stop-opacity:1"/><stop offset="0.32" style="stop-color:rgb(223,81,83);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(172,11,27);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -5,15 +5,17 @@ import { Button, LabelValuePair, PositionsList } from 'components'
import { AccountManageOverlay, RiskChart } from 'components/Account'
import { ArrowRightLine, ChevronDown, ChevronLeft } from 'components/Icons'
import { useAccountStats, useBalances } from 'hooks/data'
import { useAccountDetailsStore, useSettings } from 'stores'
import { chain } from 'utils/chains'
import { useAccountDetailsStore, useNetworkConfigStore, useSettingsStore } from 'stores'
import { lookup } from 'utils/formatters'
import { createRiskData } from 'utils/risk'
export const AccountDetails = () => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const isOpen = useAccountDetailsStore((s) => s.isOpen)
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const baseAsset = useNetworkConfigStore((s) => s.assets.base)
const balances = useBalances()
const accountStats = useAccountStats()
@ -27,7 +29,7 @@ export const AccountDetails = () => {
return (
<div
className={classNames(
'relative flex w-[400px] basis-[400px] flex-wrap content-start border-white/20 bg-header',
'relative flex w-[400px] basis-[400px] flex-wrap content-start border-l border-white/20 bg-header',
enableAnimations && 'transition-[margin] duration-1000 ease-in-out',
isOpen ? 'mr-0' : '-mr-[400px]',
)}
@ -91,7 +93,7 @@ export const AccountDetails = () => {
label='Total Position:'
value={{
format: 'number',
amount: lookup(accountStats?.totalPosition ?? 0, chain.stakeCurrency.coinDenom),
amount: lookup(accountStats?.totalPosition ?? 0, baseAsset.denom, whitelistedAssets),
prefix: '$',
}}
/>
@ -99,7 +101,7 @@ export const AccountDetails = () => {
label='Total Liabilities:'
value={{
format: 'number',
amount: lookup(accountStats?.totalDebt ?? 0, chain.stakeCurrency.coinDenom),
amount: lookup(accountStats?.totalDebt ?? 0, baseAsset.denom, whitelistedAssets),
prefix: '$',
}}
/>

View File

@ -6,11 +6,11 @@ import { BorrowCapacity } from 'components/BorrowCapacity'
import { useAccountStats } from 'hooks/data'
import { useCreateCreditAccount } from 'hooks/mutations'
import { useCreditAccounts } from 'hooks/queries'
import { useModalStore } from 'stores'
import { chain } from 'utils/chains'
import { useModalStore, useNetworkConfigStore } from 'stores'
import { formatValue } from 'utils/formatters'
export const AccountStatus = () => {
const baseAsset = useNetworkConfigStore((s) => s.assets.base)
const accountStats = useAccountStats()
const { data: creditAccountsList } = useCreditAccounts()
const { mutate: createCreditAccount, isLoading: isLoadingCreate } = useCreateCreditAccount()
@ -35,7 +35,7 @@ export const AccountStatus = () => {
<Text size='sm' className='flex flex-grow text-white'>
<FormattedNumber
amount={BigNumber(accountStats.netWorth)
.dividedBy(10 ** chain.stakeCurrency.coinDecimals)
.dividedBy(10 ** baseAsset.decimals)
.toNumber()}
animate
prefix='$: '

View File

@ -8,7 +8,7 @@ import { Button, CircularProgress, Modal, Slider, Text } from 'components'
import { MarsProtocol } from 'components/Icons'
import { useDepositCreditAccount } from 'hooks/mutations'
import { useAllBalances, useAllowedCoins } from 'hooks/queries'
import { useAccountDetailsStore, useModalStore } from 'stores'
import { useAccountDetailsStore, useModalStore, useNetworkConfigStore } from 'stores'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
export const FundAccountModal = () => {
@ -18,6 +18,7 @@ export const FundAccountModal = () => {
const open = useModalStore((s) => s.fundAccountModal)
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const [lendAssets, setLendAssets] = useLocalStorageState(`lendAssets_${selectedAccount}`, {
defaultValue: false,
})
@ -37,12 +38,14 @@ export const FundAccountModal = () => {
selectedAccount || '',
selectedToken,
BigNumber(amount)
.times(10 ** getTokenDecimals(selectedToken))
.times(10 ** getTokenDecimals(selectedToken, whitelistedAssets))
.toNumber(),
{
onSuccess: () => {
setAmount(0)
toast.success(`${amount} ${getTokenSymbol(selectedToken)} successfully Deposited`)
toast.success(
`${amount} ${getTokenSymbol(selectedToken, whitelistedAssets)} successfully Deposited`,
)
useModalStore.setState({ fundAccountModal: false })
},
},
@ -59,9 +62,9 @@ export const FundAccountModal = () => {
if (!selectedToken) return 0
return BigNumber(balancesData?.find((balance) => balance.denom === selectedToken)?.amount ?? 0)
.div(10 ** getTokenDecimals(selectedToken))
.div(10 ** getTokenDecimals(selectedToken, whitelistedAssets))
.toNumber()
}, [balancesData, selectedToken])
}, [balancesData, selectedToken, whitelistedAssets])
const handleValueChange = (value: number) => {
if (value > walletAmount) {
@ -91,12 +94,10 @@ export const FundAccountModal = () => {
<div className='flex flex-1 flex-col items-start justify-between bg-fund-modal bg-cover p-6'>
<div>
<Text size='2xs' uppercase className='mb-3 text-white'>
About
Fund
</Text>
<Text size='xl' className='mb-4 text-white'>
Bringing the next generation of video creation to the Metaverse.
<br />
Powered by deep-learning.
<Text size='lg' className='mb-4 text-white'>
Fund your Account to enable its borrowing and lending capabilities.
</Text>
</div>
<div className='w-[153px] text-white'>
@ -113,9 +114,9 @@ export const FundAccountModal = () => {
Fund Account
</Text>
<Text size='sm' className='mb-6 text-white/60'>
Transfer assets from your injective wallet to your Mars credit account. If you dont
have any assets in your injective wallet use the injective bridge to transfer funds to
your injective wallet.
Transfer assets from your osmosis wallet to your Mars credit account. If you dont
have any assets in your osmosis wallet use the osmosis bridge to transfer funds to
your osmosis wallet.
</Text>
{isLoadingAllowedCoins ? (
<p>Loading...</p>
@ -137,7 +138,7 @@ export const FundAccountModal = () => {
>
{allowedCoinsData?.map((entry) => (
<option key={entry} value={entry}>
{getTokenSymbol(entry)}
{getTokenSymbol(entry, whitelistedAssets)}
</option>
))}
</select>
@ -159,14 +160,17 @@ export const FundAccountModal = () => {
</div>
</div>
<Text size='xs' uppercase className='mb-2 text-white/60'>
{`In wallet: ${walletAmount.toLocaleString()} ${getTokenSymbol(selectedToken)}`}
{`In wallet: ${walletAmount.toLocaleString()} ${getTokenSymbol(
selectedToken,
whitelistedAssets,
)}`}
</Text>
<Slider
className='mb-6'
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(selectedToken)
const tokenDecimals = getTokenDecimals(selectedToken, whitelistedAssets)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxValue).toFixed(tokenDecimals))

View File

@ -11,11 +11,11 @@ import {
import { FormattedNumber, Text } from 'components'
import { useAccountStats } from 'hooks/data'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
import { formatValue } from 'utils/formatters'
export const RiskChart = ({ data }: RiskChartProps) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const accountStats = useAccountStats()
const currentRisk = accountStats?.risk ?? 0

View File

@ -19,8 +19,12 @@ import { BorrowCapacity } from 'components/BorrowCapacity'
import { useAccountStats, useBalances, useCalculateMaxWithdrawAmount } from 'hooks/data'
import { useWithdrawFunds } from 'hooks/mutations'
import { useCreditAccountPositions, useTokenPrices } from 'hooks/queries'
import { useAccountDetailsStore, useModalStore } from 'stores'
import { chain } from 'utils/chains'
import {
useAccountDetailsStore,
useModalStore,
useNetworkConfigStore,
useWalletStore,
} from 'stores'
import { formatValue, lookup } from 'utils/formatters'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
@ -29,11 +33,11 @@ export const WithdrawModal = () => {
// STORE
// ---------------
const open = useModalStore((s) => s.withdrawModal)
const chainInfo = useWalletStore((s) => s.chainInfo)
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const { data: positionsData, isLoading: isLoadingPositions } = useCreditAccountPositions(
selectedAccount ?? '',
)
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const baseAsset = useNetworkConfigStore((s) => s.assets.base)
// ---------------
// LOCAL STATE
@ -48,8 +52,8 @@ export const WithdrawModal = () => {
const { data: tokenPrices } = useTokenPrices()
const balances = useBalances()
const selectedTokenSymbol = getTokenSymbol(selectedToken)
const selectedTokenDecimals = getTokenDecimals(selectedToken)
const selectedTokenSymbol = getTokenSymbol(selectedToken, whitelistedAssets)
const selectedTokenDecimals = getTokenDecimals(selectedToken, whitelistedAssets)
const tokenAmountInCreditAccount = useMemo(() => {
return BigNumber(positionsData?.coins.find((coin) => coin.denom === selectedToken)?.amount ?? 0)
@ -127,13 +131,13 @@ export const WithdrawModal = () => {
setAmount(0)
}
const getTokenTotalUSDValue = (amount: string, denom: string) => {
const getTokenTotalUSDValue = (amount: string, denom: string, whitelistedAssets: Asset[]) => {
// early return if prices are not fetched yet
if (!tokenPrices) return 0
return (
BigNumber(amount)
.div(10 ** getTokenDecimals(denom))
.div(10 ** getTokenDecimals(denom, whitelistedAssets))
.toNumber() * tokenPrices[denom]
)
}
@ -179,7 +183,7 @@ export const WithdrawModal = () => {
>
{positionsData?.coins?.map((coin) => (
<option key={coin.denom} value={coin.denom}>
{getTokenSymbol(coin.denom)}
{getTokenSymbol(coin.denom, whitelistedAssets)}
</option>
))}
</select>
@ -259,7 +263,7 @@ export const WithdrawModal = () => {
<Text size='sm' className='flex flex-grow text-white'>
<FormattedNumber
amount={BigNumber(accountStats.netWorth)
.dividedBy(10 ** chain.stakeCurrency.coinDecimals)
.dividedBy(10 ** baseAsset.decimals)
.toNumber()}
prefix='$: '
animate
@ -306,7 +310,11 @@ export const WithdrawModal = () => {
label='Total Position:'
value={{
format: 'number',
amount: lookup(accountStats?.totalPosition ?? 0, chain.stakeCurrency.coinDenom),
amount: lookup(
accountStats?.totalPosition ?? 0,
baseAsset.denom,
whitelistedAssets,
),
prefix: '$',
}}
/>
@ -314,7 +322,7 @@ export const WithdrawModal = () => {
label='Total Liabilities:'
value={{
format: 'number',
amount: lookup(accountStats?.totalDebt ?? 0, chain.stakeCurrency.coinDenom),
amount: lookup(accountStats?.totalDebt ?? 0, baseAsset.denom, whitelistedAssets),
prefix: '$',
}}
/>

View File

@ -9,8 +9,8 @@ type AssetRowProps = {
data: {
denom: string
symbol: string
icon: string
chain: string
logo: string
name: string
borrowed: {
amount: number
value: number
@ -32,10 +32,10 @@ export const AssetRow = ({ data, onBorrowClick, onRepayClick }: AssetRowProps) =
>
<div className='flex'>
<div className='flex flex-1 items-center'>
<Image src={data.icon} alt='token' width={32} height={32} />
<Image src={data.logo} alt='token' width={32} height={32} />
<div className='pl-2'>
<div>{data.symbol}</div>
<div className='text-xs'>{data.chain}</div>
<div className='text-xs'>{data.name}</div>
</div>
</div>
<div className='flex flex-1 items-center text-xs'>

View File

@ -9,15 +9,15 @@ import {
import Image from 'next/image'
import React from 'react'
import { AssetRow } from 'components/Borrow'
import { ChevronDown, ChevronUp } from 'components/Icons'
import { formatCurrency } from 'utils/formatters'
import { AssetRow } from 'components/Borrow'
interface Market {
denom: string
symbol: string
icon: string
chain: string
logo: string
name: string
borrowed: {
amount: number
value: number
@ -42,10 +42,10 @@ export const BorrowTable = ({ data, onBorrowClick, onRepayClick }: Props) => {
id: 'symbol',
accessorFn: (row) => (
<div className='flex flex-1 items-center'>
<Image src={row.icon} alt='token' width={32} height={32} />
<Image src={row.logo} alt='token' width={32} height={32} />
<div className='pl-2'>
<div>{row.symbol}</div>
<div className='text-xs'>{row.chain}</div>
<div className='text-xs'>{row.name}</div>
</div>
</div>
),

View File

@ -2,7 +2,7 @@ import classNames from 'classnames'
import { useEffect, useState } from 'react'
import { FormattedNumber, Text, Tooltip } from 'components'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
interface Props {
balance: number
@ -27,7 +27,7 @@ export const BorrowCapacity = ({
hideValues,
decimals = 2,
}: Props) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const [percentOfMaxRound, setPercentOfMaxRound] = useState(0)
const [percentOfMaxRange, setPercentOfMaxRange] = useState(0)

View File

@ -18,8 +18,7 @@ import {
import { useAccountStats, useBalances, useCalculateMaxBorrowAmount } from 'hooks/data'
import { useBorrowFunds } from 'hooks/mutations'
import { useAllBalances, useMarkets, useTokenPrices } from 'hooks/queries'
import { useAccountDetailsStore } from 'stores'
import { chain } from 'utils/chains'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { formatCurrency, formatValue } from 'utils/formatters'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
@ -34,12 +33,14 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
const [isBorrowToCreditAccount, setIsBorrowToCreditAccount] = useState(false)
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const baseAsset = useNetworkConfigStore((s) => s.assets.base)
const balances = useBalances()
const { actions, borrowAmount } = useMemo(() => {
const borrowAmount = BigNumber(amount)
.times(10 ** getTokenDecimals(tokenDenom))
.times(10 ** getTokenDecimals(tokenDenom, whitelistedAssets))
.toNumber()
const withdrawAmount = isBorrowToCreditAccount ? 0 : borrowAmount
@ -60,11 +61,11 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
},
] as AccountStatsAction[],
}
}, [amount, isBorrowToCreditAccount, tokenDenom])
}, [amount, isBorrowToCreditAccount, tokenDenom, whitelistedAssets])
const accountStats = useAccountStats(actions)
const tokenSymbol = getTokenSymbol(tokenDenom)
const tokenSymbol = getTokenSymbol(tokenDenom, whitelistedAssets)
const { mutate, isLoading } = useBorrowFunds(borrowAmount, tokenDenom, !isBorrowToCreditAccount, {
onSuccess: () => {
@ -83,9 +84,9 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
const walletAmount = useMemo(() => {
return BigNumber(balancesData?.find((balance) => balance.denom === tokenDenom)?.amount ?? 0)
.div(10 ** getTokenDecimals(tokenDenom))
.div(10 ** getTokenDecimals(tokenDenom, whitelistedAssets))
.toNumber()
}, [balancesData, tokenDenom])
}, [balancesData, tokenDenom, whitelistedAssets])
const tokenPrice = tokenPrices?.[tokenDenom] ?? 0
const borrowRate = Number(marketsData?.[tokenDenom]?.borrow_rate)
@ -109,7 +110,7 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
const handleSliderValueChange = (value: number[]) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(tokenDenom)
const tokenDecimals = getTokenDecimals(tokenDenom, whitelistedAssets)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxValue).toFixed(tokenDecimals))
@ -174,7 +175,7 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
allowNegative={false}
onValueChange={(v) => handleValueChange(v.floatValue || 0)}
suffix={` ${tokenSymbol}`}
decimalScale={getTokenDecimals(tokenDenom)}
decimalScale={getTokenDecimals(tokenDenom, whitelistedAssets)}
/>
<div className='flex justify-between text-xs tracking-widest'>
<div>
@ -244,7 +245,7 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
<p className='flex-1 text-xs'>
{formatCurrency(
BigNumber(accountStats.netWorth)
.dividedBy(10 ** chain.stakeCurrency.coinDecimals)
.dividedBy(10 ** baseAsset.decimals)
.toNumber(),
)}
</p>
@ -281,7 +282,7 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
<div className='font-semibold'>
{formatCurrency(
BigNumber(accountStats?.totalPosition ?? 0)
.dividedBy(10 ** chain.stakeCurrency.coinDecimals)
.dividedBy(10 ** baseAsset.decimals)
.toNumber(),
)}
</div>
@ -291,7 +292,7 @@ export const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
<div className='font-semibold'>
{formatCurrency(
BigNumber(accountStats?.totalDebt ?? 0)
.dividedBy(10 ** chain.stakeCurrency.coinDecimals)
.dividedBy(10 ** baseAsset.decimals)
.toNumber(),
)}
</div>

View File

@ -2,7 +2,7 @@ import classNames from 'classnames'
import React, { LegacyRef, ReactNode } from 'react'
import { CircularProgress } from 'components'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
interface Props {
children?: string | ReactNode
@ -74,7 +74,7 @@ export const Button = React.forwardRef(function Button(
ref,
) {
const buttonClasses = []
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
switch (variant) {
case 'round':

View File

@ -1,7 +1,7 @@
import classNames from 'classnames'
import { Text } from 'components'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
interface Props {
color?: string
@ -10,7 +10,7 @@ interface Props {
}
export const CircularProgress = ({ color = '#FFFFFF', size = 20, className }: Props) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const borderWidth = `${size / 10}px`
const borderColor = `${color} transparent transparent transparent`

View File

@ -2,7 +2,7 @@ import classNames from 'classnames'
import React, { useEffect, useRef } from 'react'
import { animated, useSpring } from 'react-spring'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
import { formatValue } from 'utils/formatters'
export const FormattedNumber = React.memo(
@ -18,7 +18,7 @@ export const FormattedNumber = React.memo(
rounded = false,
abbreviated = false,
}: FormattedNumberProps) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const prevAmountRef = useRef<number>(0)
useEffect(() => {

View File

@ -2,7 +2,7 @@ import classNames from 'classnames'
import { ReactNode } from 'react'
import { Tooltip } from 'components'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
interface Props {
tooltip: string | ReactNode
@ -20,7 +20,7 @@ export const Gauge = ({
label,
tooltip,
}: Props) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const percentage = value * 100
const percentageValue = percentage > 100 ? 100 : percentage < 0 ? 0 : percentage

View File

@ -5,7 +5,7 @@ import React, { useEffect } from 'react'
import { AccountDetails } from 'components/Account'
import { DesktopNavigation } from 'components/Navigation'
import { useCreditAccounts } from 'hooks/queries'
import { useSettings, useWalletStore } from 'stores'
import { useSettingsStore, useWalletStore } from 'stores'
const filter = {
day: 'brightness-100 hue-rotate-0',
@ -13,7 +13,7 @@ const filter = {
}
export const Layout = ({ children }: { children: React.ReactNode }) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const { data: creditAccountsList } = useCreditAccounts()
const hasCreditAccounts = creditAccountsList && creditAccountsList.length > 0

View File

@ -7,10 +7,10 @@ import { toast } from 'react-toastify'
import { Button, CircularProgress, ContainerSecondary, Slider } from 'components'
import { useRepayFunds } from 'hooks/mutations'
import { useAccountDetailsStore } from 'stores'
import { useAllBalances, useCreditAccountPositions, useTokenPrices } from 'hooks/queries'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { formatCurrency } from 'utils/formatters'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
import { useAllBalances, useCreditAccountPositions, useTokenPrices } from 'hooks/queries'
// 0.001% buffer / slippage to avoid repay action from not fully repaying the debt amount
const REPAY_BUFFER = 1.00001
@ -26,8 +26,9 @@ export const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const tokenSymbol = getTokenSymbol(tokenDenom)
const tokenSymbol = getTokenSymbol(tokenDenom, whitelistedAssets)
const maxRepayAmount = useMemo(() => {
const tokenDebtAmount =
@ -36,13 +37,13 @@ export const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
return BigNumber(tokenDebtAmount)
.times(REPAY_BUFFER)
.decimalPlaces(0)
.div(10 ** getTokenDecimals(tokenDenom))
.div(10 ** getTokenDecimals(tokenDenom, whitelistedAssets))
.toNumber()
}, [positionsData, tokenDenom])
}, [positionsData, tokenDenom, whitelistedAssets])
const { mutate, isLoading } = useRepayFunds(
BigNumber(amount)
.times(10 ** getTokenDecimals(tokenDenom))
.times(10 ** getTokenDecimals(tokenDenom, whitelistedAssets))
.toNumber(),
tokenDenom,
{
@ -62,9 +63,9 @@ export const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
const walletAmount = useMemo(() => {
return BigNumber(balancesData?.find((balance) => balance.denom === tokenDenom)?.amount ?? 0)
.div(10 ** getTokenDecimals(tokenDenom))
.div(10 ** getTokenDecimals(tokenDenom, whitelistedAssets))
.toNumber()
}, [balancesData, tokenDenom])
}, [balancesData, tokenDenom, whitelistedAssets])
const tokenPrice = tokenPrices?.[tokenDenom] ?? 0
@ -115,11 +116,9 @@ export const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
<div className='flex flex-1 flex-col items-start justify-between bg-[#4A4C60] p-6'>
<div>
<p className='text-bold mb-3 text-xs uppercase text-white/50'>About</p>
<p className='text-bold mb-3 text-xs uppercase text-white/50'>Repay</p>
<h4 className='mb-4 text-xl leading-8'>
Bringing the next generation of video creation to the Metaverse.
<br />
Powered by deep-learning.
Repay borrowed amounts to reduce risk.
</h4>
</div>
<Image src='/logo.svg' alt='mars' width={50} height={50} />
@ -144,7 +143,7 @@ export const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
allowNegative={false}
onValueChange={(v) => handleValueChange(v.floatValue || 0)}
suffix={` ${tokenSymbol}`}
decimalScale={getTokenDecimals(tokenDenom)}
decimalScale={getTokenDecimals(tokenDenom, whitelistedAssets)}
/>
<div className='flex justify-between text-xs tracking-widest'>
<div>
@ -159,7 +158,7 @@ export const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(tokenDenom)
const tokenDecimals = getTokenDecimals(tokenDenom, whitelistedAssets)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxValue).toFixed(tokenDecimals))

View File

@ -3,7 +3,7 @@ import classNames from 'classnames'
import { ReactNode } from 'react'
import { Questionmark } from 'components/Icons'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
interface Props {
children?: ReactNode | string
@ -22,7 +22,7 @@ export const Tooltip = ({
inderactive = false,
underline = false,
}: Props) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
return (
<Tippy

View File

@ -14,7 +14,7 @@ import {
useMarkets,
useTokenPrices,
} from 'hooks/queries'
import { useAccountDetailsStore } from 'stores'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
enum FundingMode {
@ -23,6 +23,8 @@ enum FundingMode {
}
export const TradeActionModule = () => {
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const [selectedTokenIn, setSelectedTokenIn] = useState('')
const [selectedTokenOut, setSelectedTokenOut] = useState('')
const [amountIn, setAmountIn] = useState(0)
@ -92,9 +94,10 @@ export const TradeActionModule = () => {
{
onSuccess: () => {
toast.success(
`${amountIn} ${getTokenSymbol(selectedTokenIn)} swapped for ${amountOut} ${getTokenSymbol(
selectedTokenOut,
)}`,
`${amountIn} ${getTokenSymbol(
selectedTokenIn,
whitelistedAssets,
)} swapped for ${amountOut} ${getTokenSymbol(selectedTokenOut, whitelistedAssets)}`,
)
resetAmounts()
},
@ -189,19 +192,20 @@ export const TradeActionModule = () => {
>
{allowedCoinsData?.map((entry) => (
<option key={entry} value={entry}>
{getTokenSymbol(entry)}
{getTokenSymbol(entry, whitelistedAssets)}
</option>
))}
</select>
<input
type='number'
className='h-8 flex-1 px-2 text-black outline-0'
value={amountIn / 10 ** getTokenDecimals(selectedTokenIn)}
value={amountIn / 10 ** getTokenDecimals(selectedTokenIn, whitelistedAssets)}
min='0'
placeholder='0.00'
onChange={(e) => {
const valueAsNumber = e.target.valueAsNumber
const valueWithDecimals = valueAsNumber * 10 ** getTokenDecimals(selectedTokenIn)
const valueWithDecimals =
valueAsNumber * 10 ** getTokenDecimals(selectedTokenIn, whitelistedAssets)
handleAmountChange(valueWithDecimals, 'in')
}}
@ -228,19 +232,20 @@ export const TradeActionModule = () => {
>
{allowedCoinsData?.map((entry) => (
<option key={entry} value={entry}>
{getTokenSymbol(entry)}
{getTokenSymbol(entry, whitelistedAssets)}
</option>
))}
</select>
<input
type='number'
className='h-8 flex-1 px-2 text-black outline-0'
value={amountOut / 10 ** getTokenDecimals(selectedTokenOut)}
value={amountOut / 10 ** getTokenDecimals(selectedTokenOut, whitelistedAssets)}
min='0'
placeholder='0.00'
onChange={(e) => {
const valueAsNumber = e.target.valueAsNumber
const valueWithDecimals = valueAsNumber * 10 ** getTokenDecimals(selectedTokenOut)
const valueWithDecimals =
valueAsNumber * 10 ** getTokenDecimals(selectedTokenOut, whitelistedAssets)
handleAmountChange(valueWithDecimals, 'out')
}}
@ -250,29 +255,29 @@ export const TradeActionModule = () => {
<div className='mb-1'>
In Wallet:{' '}
{BigNumber(walletAmount)
.dividedBy(10 ** getTokenDecimals(selectedTokenIn))
.dividedBy(10 ** getTokenDecimals(selectedTokenIn, whitelistedAssets))
.toNumber()
.toLocaleString(undefined, {
maximumFractionDigits: getTokenDecimals(selectedTokenIn),
maximumFractionDigits: getTokenDecimals(selectedTokenIn, whitelistedAssets),
})}{' '}
<span>{getTokenSymbol(selectedTokenIn)}</span>
<span>{getTokenSymbol(selectedTokenIn, whitelistedAssets)}</span>
</div>
<div className='mb-4'>
In Account:{' '}
{BigNumber(accountAmount)
.dividedBy(10 ** getTokenDecimals(selectedTokenIn))
.dividedBy(10 ** getTokenDecimals(selectedTokenIn, whitelistedAssets))
.toNumber()
.toLocaleString(undefined, {
maximumFractionDigits: getTokenDecimals(selectedTokenIn),
maximumFractionDigits: getTokenDecimals(selectedTokenIn, whitelistedAssets),
})}{' '}
<span>{getTokenSymbol(selectedTokenIn)}</span>
<span>{getTokenSymbol(selectedTokenIn, whitelistedAssets)}</span>
</div>
<Slider
className='mb-6'
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(selectedTokenIn)
const tokenDecimals = getTokenDecimals(selectedTokenIn, whitelistedAssets)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxAmount).toFixed(0))
@ -308,10 +313,10 @@ export const TradeActionModule = () => {
<p>
{isMarginEnabled
? BigNumber(borrowAmount)
.dividedBy(10 ** getTokenDecimals(selectedTokenIn))
.dividedBy(10 ** getTokenDecimals(selectedTokenIn, whitelistedAssets))
.toNumber()
.toLocaleString(undefined, {
maximumFractionDigits: getTokenDecimals(selectedTokenIn),
maximumFractionDigits: getTokenDecimals(selectedTokenIn, whitelistedAssets),
})
: '-'}
</p>

View File

@ -1,9 +1,5 @@
import {
ChainInfoID,
SimpleChainInfoList,
useWallet,
useWalletManager,
} from '@marsprotocol/wallet-connector'
import { ChainInfoID, SimpleChainInfoList, useWalletManager } from '@marsprotocol/wallet-connector'
import BigNumber from 'bignumber.js'
import classNames from 'classnames'
import { useCallback, useEffect, useState } from 'react'
import useClipboard from 'react-use-clipboard'
@ -11,7 +7,8 @@ import useClipboard from 'react-use-clipboard'
import { Button, CircularProgress, FormattedNumber, Text } from 'components'
import { Check, Copy, ExternalLink, Osmo, Wallet } from 'components/Icons'
import { Overlay } from 'components/Overlay'
import { useTokenBalance } from 'hooks/queries'
import { useAllBalances } from 'hooks/queries'
import { useNetworkConfigStore, useWalletStore } from 'stores'
import { formatValue, truncate } from 'utils/formatters'
export const ConnectedButton = () => {
@ -19,18 +16,22 @@ export const ConnectedButton = () => {
// EXTERNAL HOOKS
// ---------------
const { disconnect } = useWalletManager()
const { chainInfo, address, name } = useWallet()
const address = useWalletStore((s) => s.address)
const chainInfo = useWalletStore((s) => s.chainInfo)
const name = useWalletStore((s) => s.name)
const baseAsset = useNetworkConfigStore((s) => s.assets.base)
// ---------------
// LOCAL HOOKS
// ---------------
const { data } = useTokenBalance()
const { data } = useAllBalances()
// ---------------
// LOCAL STATE
// ---------------
const [isLoading, setIsLoading] = useState(false)
const [showDetails, setShowDetails] = useState(false)
const [walletAmount, setWalletAmount] = useState(0)
const [isCopied, setCopied] = useClipboard(address || '', {
successDuration: 1000 * 5,
})
@ -52,6 +53,14 @@ export const ConnectedButton = () => {
setIsLoading(loading)
}, [address, name, chainInfo])
useEffect(() => {
setWalletAmount(
BigNumber(data?.find((balance) => balance.denom === baseAsset.denom)?.amount ?? 0)
.div(10 ** baseAsset.decimals)
.toNumber(),
)
}, [data, baseAsset.denom, baseAsset.decimals])
return (
<div className={'relative'}>
{chainInfo?.chainId !== ChainInfoID.Osmosis1 && (
@ -90,7 +99,7 @@ export const ConnectedButton = () => {
)}
>
{!isLoading ? (
`${formatValue(data, 2, 2, true, false, ` ${chainInfo?.stakeCurrency?.coinDenom}`)}`
`${formatValue(walletAmount, 2, 2, true, false, ` ${baseAsset.symbol}`)}`
) : (
<CircularProgress size={12} />
)}
@ -101,13 +110,13 @@ export const ConnectedButton = () => {
<div className='flex-0 mb-4 flex w-full flex-nowrap items-start'>
<div className='flex w-auto flex-1'>
<div className='mr-2 flex h-[31px] items-end pb-0.5 text-secondary-dark text-base-caps'>
{chainInfo?.stakeCurrency?.coinDenom}
{baseAsset.denom}
</div>
<div className='flex-0 flex flex-wrap justify-end'>
<FormattedNumber
animate
className='flex items-end text-2xl text-secondary-dark'
amount={data}
amount={walletAmount}
/>
</div>
</div>

View File

@ -5,22 +5,24 @@ import { FC } from 'react'
import { CircularProgress } from 'components'
import { buttonColorClasses, buttonSizeClasses, buttonVariantClasses } from 'components/Button'
import { Close } from 'components/Icons'
import KeplrImage from 'images/keplr-wallet-extension.png'
import WalletConnectImage from 'images/walletconnect-keplr.png'
import { useSettings } from 'stores'
// TODO: get networkConfig source dynamically
import { networkConfig } from 'config/osmo-test-4'
import KeplrImage from 'images/wallets/keplr-wallet-extension.png'
import WalletConnectImage from 'images/wallets/walletconnect-keplr.png'
import { useSettingsStore } from 'stores'
type Props = {
children?: React.ReactNode
}
export const WalletConnectProvider: FC<Props> = ({ children }) => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
return (
<WalletManagerProvider
chainInfoOverrides={{
[ChainInfoID.OsmosisTestnet]: {
rpc: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc',
rest: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd',
rpc: networkConfig.rpcUrl,
rest: networkConfig.restUrl,
},
}}
classNames={{

View File

@ -1,15 +0,0 @@
// https://github.com/mars-protocol/rover/blob/master/scripts/deploy/addresses/osmo-test-4.json
export const roverContracts = {
accountNft: 'osmo1xvne7u9svgy9vtqtqnaet4nvn8zcpp984zzrlezfzgk4798tps8srkf5wa',
mockVault: 'osmo1yqgjaehalz0pv5j22fdnaaekuprlggd7hth8m66jmdxe58ztqs4sjqtrlk',
marsOracleAdapter: 'osmo1tlad2hj9rm7az7atx2qq8pdpl2007hrhpzua42j8wgxr0kc0ct4sahuyh7',
swapper: 'osmo15kxcpvjaqlrj8ezecnghf2qs2x87veqx0fcemye0jpdr8jq7qkvsnyvuuf',
mockZapper: 'osmo1axad429tgnvzvfax08s4ytmf7ndg0f9z4jy355zyh4m6nasgtnzs5aw8u7',
creditManager: 'osmo1krz37p6xkkyu0f240enyt4ccxk7ds69kfgc5pnldsmpmmuvn3vpsnmpjaf',
}
export const contractAddresses = {
...roverContracts,
redBank: 'osmo1g30recyv8pfy3qd4qn3dn7plc0rn5z68y5gn32j39e96tjhthzxsw3uvvu',
oracle: 'osmo1hkkx42777dyfz7wc8acjjhfdh9x2ugcjvdt7shtft6ha9cn420cquz3u3j',
}

68
src/config/osmo-test-4.ts Normal file
View File

@ -0,0 +1,68 @@
import { ChainInfoID } from '@marsprotocol/wallet-connector'
const Assets: { [key: string]: Asset } = {
osmo: {
symbol: 'OSMO',
name: 'Osmosis',
denom: 'uosmo',
color: '#9f1ab9',
decimals: 6,
hasOraclePrice: true,
logo: '/tokens/osmo.svg',
},
atom: {
symbol: 'ATOM',
name: 'Atom',
denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
color: '#6f7390',
logo: '/tokens/atom.svg',
decimals: 6,
hasOraclePrice: true,
},
cro: {
symbol: 'CRO',
name: 'Cronos',
denom: 'ibc/E6931F78057F7CC5DA0FD6CEF82FF39373A6E0452BF1FD76910B93292CF356C1',
color: '#002D74',
logo: '/tokens/cro.svg',
decimals: 8,
hasOraclePrice: true,
},
}
const OtherAssets: { [key: string]: OtherAsset } = {
mars: {
symbol: 'MARS',
name: 'Mars',
denom: 'ibc/EA3E1640F9B1532AB129A571203A0B9F789A7F14BB66E350DCBFA18E1A1931F0',
//denom: 'ibc/1BF910A3C8A30C8E3331764FA0113B920AE14B913F487DF7E1989FD75EFE61FD'
color: '#a03b45',
logo: '/tokens/mars.svg',
decimals: 6,
hasOraclePrice: true,
poolId: 601,
},
}
export const networkConfig: NetworkConfig = {
name: ChainInfoID.OsmosisTestnet,
hiveUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-hive/graphql',
rpcUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc',
restUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd',
contracts: {
accountNft: 'osmo1xvne7u9svgy9vtqtqnaet4nvn8zcpp984zzrlezfzgk4798tps8srkf5wa',
mockVault: 'osmo1yqgjaehalz0pv5j22fdnaaekuprlggd7hth8m66jmdxe58ztqs4sjqtrlk',
marsOracleAdapter: 'osmo1tlad2hj9rm7az7atx2qq8pdpl2007hrhpzua42j8wgxr0kc0ct4sahuyh7',
swapper: 'osmo15kxcpvjaqlrj8ezecnghf2qs2x87veqx0fcemye0jpdr8jq7qkvsnyvuuf',
mockZapper: 'osmo1axad429tgnvzvfax08s4ytmf7ndg0f9z4jy355zyh4m6nasgtnzs5aw8u7',
creditManager: 'osmo1krz37p6xkkyu0f240enyt4ccxk7ds69kfgc5pnldsmpmmuvn3vpsnmpjaf',
redBank: 'osmo1g30recyv8pfy3qd4qn3dn7plc0rn5z68y5gn32j39e96tjhthzxsw3uvvu',
oracle: 'osmo1hkkx42777dyfz7wc8acjjhfdh9x2ugcjvdt7shtft6ha9cn420cquz3u3j',
},
assets: {
base: Assets.osmo,
whitelist: [Assets.osmo, Assets.atom, Assets.cro],
other: [OtherAssets.mars],
},
appUrl: 'https://testnet.osmosis.zone',
}

View File

@ -1,31 +0,0 @@
type Token = {
denom: string
symbol: string
decimals: number
icon: string
chain: string
}
export const tokenInfo: { [key in string]: Token } = {
uosmo: {
denom: 'uosmo',
symbol: 'OSMO',
decimals: 6,
icon: '/tokens/osmo.svg',
chain: 'Osmosis',
},
'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2': {
denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
symbol: 'ATOM',
icon: '/tokens/atom.svg',
decimals: 6,
chain: 'Cosmos',
},
'ibc/E6931F78057F7CC5DA0FD6CEF82FF39373A6E0452BF1FD76910B93292CF356C1': {
denom: 'ibc/E6931F78057F7CC5DA0FD6CEF82FF39373A6E0452BF1FD76910B93292CF356C1',
symbol: 'CRO',
icon: '/tokens/cro.jpg',
decimals: 8,
chain: 'Crypto.org',
},
}

View File

@ -1,19 +1,19 @@
import { useEffect } from 'react'
import { useSettings } from 'stores'
import { useSettingsStore } from 'stores'
export const useAnimations = () => {
const enableAnimations = useSettings((s) => s.enableAnimations)
const enableAnimations = useSettingsStore((s) => s.enableAnimations)
const queryChangeHandler = (event: MediaQueryListEvent) => {
useSettings.setState({ enableAnimations: !event?.matches ?? true })
useSettingsStore.setState({ enableAnimations: !event?.matches ?? true })
}
useEffect(() => {
const mediaQuery: MediaQueryList = window.matchMedia('(prefers-reduced-motion: reduce)')
if (mediaQuery) {
useSettings.setState({ enableAnimations: !mediaQuery.matches })
useSettingsStore.setState({ enableAnimations: !mediaQuery.matches })
mediaQuery.addEventListener('change', queryChangeHandler)
return () => mediaQuery.removeEventListener('change', queryChangeHandler)
}

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import { useCreditAccountPositions, useMarkets, useTokenPrices } from 'hooks/queries'
import { useAccountDetailsStore } from 'stores'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { formatBalances } from 'utils/balances'
export const useBalances = () => {
@ -10,6 +10,7 @@ export const useBalances = () => {
const { data: marketsData } = useMarkets()
const { data: tokenPrices } = useTokenPrices()
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const { data: positionsData, isLoading: isLoadingPositions } = useCreditAccountPositions(
selectedAccount ?? '',
@ -18,15 +19,15 @@ export const useBalances = () => {
useEffect(() => {
const balances =
positionsData?.coins && tokenPrices
? formatBalances(positionsData.coins, tokenPrices, false)
? formatBalances(positionsData.coins, tokenPrices, false, whitelistedAssets)
: []
const debtBalances =
positionsData?.debts && tokenPrices
? formatBalances(positionsData.debts, tokenPrices, true, marketsData)
? formatBalances(positionsData.debts, tokenPrices, true, whitelistedAssets, marketsData)
: []
setBalanceData([...balances, ...debtBalances])
}, [positionsData, marketsData, tokenPrices])
}, [positionsData, marketsData, tokenPrices, whitelistedAssets])
return balanceData
}

View File

@ -7,7 +7,7 @@ import {
useRedbankBalances,
useTokenPrices,
} from 'hooks/queries'
import { useAccountDetailsStore } from 'stores'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { getTokenDecimals } from 'utils/tokens'
const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
@ -18,6 +18,7 @@ const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
export const useCalculateMaxBorrowAmount = (denom: string, isUnderCollateralized: boolean) => {
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
const { data: marketsData } = useMarkets()
@ -61,7 +62,7 @@ export const useCalculateMaxBorrowAmount = (denom: string, isUnderCollateralized
}, 0)
const borrowTokenPrice = tokenPrices[denom]
const tokenDecimals = getTokenDecimals(denom)
const tokenDecimals = getTokenDecimals(denom, whitelistedAssets)
let maxAmountCapacity
if (isUnderCollateralized) {
@ -76,7 +77,10 @@ export const useCalculateMaxBorrowAmount = (denom: string, isUnderCollateralized
.div(borrowTokenPrice)
}
const marketLiquidity = redbankBalances?.[denom] ?? 0
const marketLiquidity = BigNumber(
redbankBalances?.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())?.amount ||
0,
)
const maxBorrowAmount = maxAmountCapacity.gt(marketLiquidity)
? marketLiquidity
@ -96,5 +100,6 @@ export const useCalculateMaxBorrowAmount = (denom: string, isUnderCollateralized
positionsData,
redbankBalances,
tokenPrices,
whitelistedAssets,
])
}

View File

@ -7,7 +7,7 @@ import {
useRedbankBalances,
useTokenPrices,
} from 'hooks/queries'
import { useAccountDetailsStore } from 'stores'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { getTokenDecimals } from 'utils/tokens'
const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
@ -18,13 +18,14 @@ const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
export const useCalculateMaxWithdrawAmount = (denom: string, borrow: boolean) => {
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
const { data: marketsData } = useMarkets()
const { data: tokenPrices } = useTokenPrices()
const { data: redbankBalances } = useRedbankBalances()
const tokenDecimals = getTokenDecimals(denom)
const tokenDecimals = getTokenDecimals(denom, whitelistedAssets)
const getTokenValue = useCallback(
(amount: string, denom: string) => {
@ -101,7 +102,10 @@ export const useCalculateMaxWithdrawAmount = (denom: string, borrow: boolean) =>
maxAmountCapacity = maxAmountCapacity < 0 ? 0 : maxAmountCapacity
}
const marketLiquidity = redbankBalances?.[denom] ?? 0
const marketLiquidity = BigNumber(
redbankBalances?.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())?.amount ||
0,
)
const maxWithdrawAmount = BigNumber(maxAmountCapacity).gt(marketLiquidity)
? marketLiquidity

View File

@ -1,8 +1,12 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'react-toastify'
import { contractAddresses } from 'config/contracts'
import { useAccountDetailsStore, useWalletStore } from 'stores'
import {
useAccountDetailsStore,
useModalStore,
useNetworkConfigStore,
useWalletStore,
} from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { hardcodedFee } from 'utils/contants'
@ -14,17 +18,13 @@ const executeMsg = {
export const useCreateCreditAccount = () => {
const signingClient = useWalletStore((s) => s.signingClient)
const address = useWalletStore((s) => s.address)
const creditManagerAddress = useNetworkConfigStore((s) => s.contracts.creditManager)
const queryClient = useQueryClient()
return useMutation(
async () =>
await signingClient?.execute(
address ?? '',
contractAddresses.creditManager,
executeMsg,
hardcodedFee,
),
await signingClient?.execute(address ?? '', creditManagerAddress, executeMsg, hardcodedFee),
{
onSettled: () => {
queryClient.invalidateQueries(queryKeys.creditAccounts(address ?? ''))
@ -38,7 +38,7 @@ export const useCreateCreditAccount = () => {
// TODO: is there some better way to parse response to extract token id???
const createdID = data.logs[0].events[2].attributes[6].value
useAccountDetailsStore.setState({ selectedAccount: createdID })
toast.success('New account created')
useModalStore.setState({ fundAccountModal: true })
},
},
)

View File

@ -1,14 +1,14 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'react-toastify'
import { contractAddresses } from 'config/contracts'
import { useWalletStore } from 'stores'
import { useNetworkConfigStore, useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { hardcodedFee } from 'utils/contants'
export const useDeleteCreditAccount = (accountId: string) => {
const signingClient = useWalletStore((s) => s.signingClient)
const address = useWalletStore((s) => s.address)
const accountNftAddress = useNetworkConfigStore((s) => s.contracts.accountNft)
const queryClient = useQueryClient()
@ -16,7 +16,7 @@ export const useDeleteCreditAccount = (accountId: string) => {
async () =>
await signingClient?.execute(
address ?? '',
contractAddresses.accountNft,
accountNftAddress,
{
burn: {
token_id: accountId,

View File

@ -1,8 +1,7 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'react-toastify'
import { contractAddresses } from 'config/contracts'
import { useWalletStore } from 'stores'
import { useNetworkConfigStore, useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { hardcodedFee } from 'utils/contants'
@ -16,6 +15,7 @@ export const useDepositCreditAccount = (
) => {
const signingClient = useWalletStore((s) => s.signingClient)
const address = useWalletStore((s) => s.address)
const creditManagerAddress = useNetworkConfigStore((s) => s.contracts.creditManager)
const queryClient = useQueryClient()
@ -23,7 +23,7 @@ export const useDepositCreditAccount = (
async () =>
await signingClient?.execute(
address ?? '',
contractAddresses.creditManager,
creditManagerAddress,
{
update_credit_account: {
account_id: accountId,

View File

@ -5,6 +5,5 @@ export { useCreditAccountPositions } from './useCreditAccountPositions'
export { useCreditAccounts } from './useCreditAccounts'
export { useMarkets } from './useMarkets'
export { useRedbankBalances } from './useRedbankBalances'
export { useTokenBalance } from './useTokenBalance'
export { useTokenPrices } from './useTokenPrices'
// @endindex

View File

@ -1,27 +1,48 @@
import { Coin } from '@cosmjs/stargate'
import { useQuery } from '@tanstack/react-query'
import request, { gql } from 'graphql-request'
import { useMemo } from 'react'
import { useWalletStore } from 'stores'
import { useNetworkConfigStore, useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { chain } from 'utils/chains'
type Result = {
balances: { amount: string; denom: string }[]
interface UserBalanceData {
balance: {
balance: Coin[]
}
}
export const useAllBalances = () => {
const address = useWalletStore((s) => s.address)
const hiveUrl = useNetworkConfigStore((s) => s.hiveUrl)
const result = useQuery<Result>(
const result = useQuery<UserBalanceData>(
queryKeys.allBalances(address ?? ''),
() => fetch(`${chain.rest}/cosmos/bank/v1beta1/balances/${address}`).then((res) => res.json()),
async () => {
return await request(
hiveUrl!,
gql`
query UserBalanceQuery {
balance: bank {
balance(
address: "${address}"
) {
amount
denom
}
}
}
`,
)
},
{
enabled: !!address,
staleTime: Infinity,
enabled: !!hiveUrl && !!address,
staleTime: 30000,
refetchInterval: 30000,
},
)
return {
...result,
data: result?.data?.balances,
data: useMemo(() => result.data && result.data.balance.balance, [result.data]),
}
}

View File

@ -1,7 +1,6 @@
import { useQuery } from '@tanstack/react-query'
import { contractAddresses } from 'config/contracts'
import { useWalletStore } from 'stores'
import { useNetworkConfigStore, useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
type Result = string[]
@ -12,10 +11,11 @@ const queryMsg = {
export const useAllowedCoins = () => {
const client = useWalletStore((s) => s.signingClient)
const creditManagerAddress = useNetworkConfigStore((s) => s.contracts.creditManager)
const result = useQuery<Result>(
queryKeys.allowedCoins(),
async () => client?.queryContractSmart(contractAddresses.creditManager, queryMsg),
async () => client?.queryContractSmart(creditManagerAddress, queryMsg),
{
enabled: !!client,
staleTime: Infinity,

View File

@ -2,8 +2,7 @@ import { Coin } from '@cosmjs/stargate'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { contractAddresses } from 'config/contracts'
import { useWalletStore } from 'stores'
import { useNetworkConfigStore, useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
interface DebtAmount {
@ -27,11 +26,12 @@ interface Result {
export const useCreditAccountPositions = (accountId: string) => {
const address = useWalletStore((s) => s.address)
const client = useWalletStore((s) => s.signingClient)
const creditManagerAddress = useNetworkConfigStore((s) => s.contracts.creditManager)
const result = useQuery<Result>(
queryKeys.creditAccountsPositions(accountId),
async () =>
client?.queryContractSmart(contractAddresses.creditManager, {
client?.queryContractSmart(creditManagerAddress, {
positions: {
account_id: accountId,
},

View File

@ -1,8 +1,7 @@
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { contractAddresses } from 'config/contracts'
import { useAccountDetailsStore, useWalletStore } from 'stores'
import { useAccountDetailsStore, useNetworkConfigStore, useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
type Result = {
@ -13,6 +12,7 @@ export const useCreditAccounts = () => {
const address = useWalletStore((s) => s.address)
const client = useWalletStore((s) => s.signingClient)
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
const accountNftAddress = useNetworkConfigStore((s) => s.contracts.accountNft)
const setSelectedAccount = (account: string) => {
useAccountDetailsStore.setState({ selectedAccount: account })
}
@ -27,7 +27,7 @@ export const useCreditAccounts = () => {
const result = useQuery<Result>(
queryKeys.creditAccounts(address ?? ''),
async () => client?.queryContractSmart(contractAddresses.accountNft, queryMsg),
async () => client?.queryContractSmart(accountNftAddress, queryMsg),
{
staleTime: Infinity,
enabled: !!address && !!client,

View File

@ -1,57 +1,48 @@
import { Coin } from '@cosmjs/stargate'
import { useQuery } from '@tanstack/react-query'
import request, { gql } from 'graphql-request'
import { useMemo } from 'react'
import { contractAddresses } from 'config/contracts'
import { useNetworkConfigStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { chain } from 'utils/chains'
interface Result {
data: {
bank: {
balance: Coin[]
}
bank: {
balance: Coin[]
}
}
const fetchBalances = () => {
return fetch(chain.hive, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
query RedbankBalances {
bank {
balance(
address: "${contractAddresses.redBank}"
) {
amount
denom
}
}
}
`,
}),
}).then((res) => res.json())
}
export const useRedbankBalances = () => {
const result = useQuery<Result>(queryKeys.redbankBalances(), fetchBalances)
const hiveUrl = useNetworkConfigStore((s) => s.hiveUrl)
const redBankAddress = useNetworkConfigStore((s) => s.contracts.redBank)
const result = useQuery<Result>(
queryKeys.redbankBalances(),
async () => {
return await request(
hiveUrl!,
gql`
query RedbankBalances {
bank {
balance(
address: "${redBankAddress}"
) {
amount
denom
}
}
}
`,
)
},
{
enabled: !!hiveUrl && !!redBankAddress,
staleTime: 30000,
refetchInterval: 30000,
},
)
return {
...result,
data: useMemo(() => {
if (!result.data) return
return result.data?.data.bank.balance.reduce(
(acc, coin) => ({
...acc,
[coin.denom]: coin.amount,
}),
{},
) as { [key in string]: string }
}, [result.data]),
data: useMemo(() => result.data && result.data.bank.balance, [result.data]),
}
}

View File

@ -1,39 +0,0 @@
import { useQuery } from '@tanstack/react-query'
import BigNumber from 'bignumber.js'
import { useWalletStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { chain } from 'utils/chains'
type Result = {
balance: {
amount: number
denom: string
}
}
export const useTokenBalance = (denom?: string) => {
const address = useWalletStore((s) => s.address)
const result = useQuery<Result>(
queryKeys.tokenBalance(address ?? '', denom || chain.stakeCurrency.coinMinimalDenom),
async () =>
fetch(
`${chain.rest}/cosmos/bank/v1beta1/balances/${address}/by_denom?denom=${
denom || chain.stakeCurrency.coinMinimalDenom
}`,
).then((res) => res.json()),
{
enabled: !!address,
},
)
return {
...result,
data: result?.data
? BigNumber(result.data.balance.amount)
.div(10 ** chain.stakeCurrency.coinDecimals)
.toNumber()
: 0,
}
}

View File

@ -2,23 +2,22 @@ import { useQuery } from '@tanstack/react-query'
import { gql, request } from 'graphql-request'
import { useMemo } from 'react'
import { contractAddresses } from 'config/contracts'
import { tokenInfo } from 'config/tokenInfo'
import { useNetworkConfigStore } from 'stores'
import { queryKeys } from 'types/query-keys-factory'
import { chain } from 'utils/chains'
const tokenInfoList = Object.values(tokenInfo)
// TODO: build gql query dynamically on whitelisted tokens
const fetchTokenPrices = () => {
const fetchTokenPrices = async (
hiveUrl: string,
whitelistedTokens: Asset[],
oracleAddress: string,
) => {
return request(
chain.hive,
hiveUrl,
gql`
query PriceOracle {
prices: wasm {
${tokenInfoList.map((token) => {
${whitelistedTokens.map((token) => {
return `${token.symbol}: contractQuery(
contractAddress: "${contractAddresses.oracle}"
contractAddress: "${oracleAddress}"
query: {
price: {
denom: "${token.denom}"
@ -33,10 +32,17 @@ const fetchTokenPrices = () => {
}
export const useTokenPrices = () => {
const result = useQuery<TokenPricesResult>(queryKeys.tokenPrices(), fetchTokenPrices, {
refetchInterval: 30000,
staleTime: Infinity,
})
const hiveUrl = useNetworkConfigStore((s) => s.hiveUrl)
const whitelistedTokens = useNetworkConfigStore((s) => s.assets.whitelist)
const oracleAddress = useNetworkConfigStore((s) => s.contracts.oracle)
const result = useQuery<TokenPricesResult>(
queryKeys.tokenPrices(),
async () => await fetchTokenPrices(hiveUrl, whitelistedTokens, oracleAddress),
{
refetchInterval: 30000,
staleTime: Infinity,
},
)
return {
...result,

View File

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -19,8 +19,30 @@ const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<Head>
<title>Mars V2</title>
<link rel='icon' href='/favicon.svg' />
<title>Mars Protocol V2</title>
<meta charSet='utf-8' />
<link href='/favicon.svg' rel='icon' />
<link href='/apple-touch-icon.png' rel='apple-touch-icon' sizes='180x180' />
<link href='/site.webmanifest' rel='manifest' />
<link color='#dd5b65' href='/safari-pinned-tab.svg' rel='mask-icon' />
<meta content='index,follow' name='robots' />
<meta
content="Lend, borrow and earn on the galaxy's most powerful credit protocol or enter the Fields of Mars for advanced DeFi strategies."
name='description'
/>
<meta content='summary_large_image' name='twitter:card' />
<meta content='@mars_protocol' name='twitter:site' />
<meta content='@mars_protocol' name='twitter:creator' />
<meta content='https://osmosis.marsprotocol.io' property='og:url' />
<meta content='Mars Protocol V2 - Powered by Osmosis' property='og:title' />
<meta
content="Lend, borrow and earn on the galaxy's most powerful credit protocol or enter the Fields of Mars for advanced DeFi strategies."
property='og:description'
/>
<meta content='https://osmosis.marsprotocol.io/banner.png' property='og:image' />
<meta content='Mars Protocol V2' property='og:site_name' />
<meta content='#ffffff' name='msapplication-TileColor' />
<meta content='#ffffff' name='theme-color' />
</Head>
<WalletConnectProvider>
<QueryClientProvider client={queryClient}>

View File

@ -3,8 +3,6 @@ import { useMemo, useRef, useState } from 'react'
import { BorrowModal, Card, RepayModal, Text } from 'components'
import { BorrowTable } from 'components/Borrow'
import { useAccountDetailsStore } from 'stores'
import { getTokenDecimals, getTokenInfo } from 'utils/tokens'
import {
useAllowedCoins,
useCreditAccountPositions,
@ -12,6 +10,8 @@ import {
useRedbankBalances,
useTokenPrices,
} from 'hooks/queries'
import { useAccountDetailsStore, useNetworkConfigStore } from 'stores'
import { getTokenDecimals, getTokenInfo } from 'utils/tokens'
type ModalState = {
show: 'borrow' | 'repay' | false
@ -21,6 +21,8 @@ type ModalState = {
}
const Borrow = () => {
const whitelistedAssets = useNetworkConfigStore((s) => s.assets.whitelist)
const [modalState, setModalState] = useState<ModalState>({
show: false,
data: { tokenDenom: '' },
@ -53,22 +55,25 @@ const Borrow = () => {
allowedCoinsData
?.filter((denom) => borrowedAssetsMap.has(denom))
.map((denom) => {
const { symbol, chain, icon } = getTokenInfo(denom)
const { symbol, name, logo } = getTokenInfo(denom, whitelistedAssets)
const borrowRate = Number(marketsData?.[denom].borrow_rate) || 0
const marketLiquidity = BigNumber(redbankBalances?.[denom] ?? 0)
.div(10 ** getTokenDecimals(denom))
const marketLiquidity = BigNumber(
redbankBalances?.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())
?.amount || 0,
)
.div(10 ** getTokenDecimals(denom, whitelistedAssets))
.toNumber()
const borrowAmount = BigNumber(borrowedAssetsMap.get(denom) as string)
.div(10 ** getTokenDecimals(denom))
.div(10 ** getTokenDecimals(denom, whitelistedAssets))
.toNumber()
const borrowValue = borrowAmount * (tokenPrices?.[denom] ?? 0)
const rowData = {
denom,
symbol,
icon,
chain,
logo,
name,
borrowed: {
amount: borrowAmount,
value: borrowValue,
@ -83,17 +88,20 @@ const Borrow = () => {
allowedCoinsData
?.filter((denom) => !borrowedAssetsMap.has(denom))
.map((denom) => {
const { symbol, chain, icon } = getTokenInfo(denom)
const { symbol, name, logo } = getTokenInfo(denom, whitelistedAssets)
const borrowRate = Number(marketsData?.[denom].borrow_rate) || 0
const marketLiquidity = BigNumber(redbankBalances?.[denom] ?? 0)
.div(10 ** getTokenDecimals(denom))
const marketLiquidity = BigNumber(
redbankBalances?.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())
?.amount || 0,
)
.div(10 ** getTokenDecimals(denom, whitelistedAssets))
.toNumber()
const rowData = {
denom,
symbol,
icon,
chain,
logo,
name,
borrowed: null,
borrowRate,
marketLiquidity,
@ -102,7 +110,14 @@ const Borrow = () => {
return rowData
}) ?? [],
}
}, [allowedCoinsData, borrowedAssetsMap, marketsData, redbankBalances, tokenPrices])
}, [
allowedCoinsData,
borrowedAssetsMap,
marketsData,
redbankBalances,
tokenPrices,
whitelistedAssets,
])
const handleBorrowClick = (denom: string) => {
setModalState({ show: 'borrow', data: { tokenDenom: denom } })
@ -131,7 +146,7 @@ const Borrow = () => {
</Card>
<Card>
<div>
<Text tag='h3' size='xl' uppercase className='mb-7 text-center text-lg-caps'>
<Text tag='h3' size='xl' uppercase className='mb-7 text-center'>
Available to Borrow
</Text>
<BorrowTable

View File

@ -1,6 +1,7 @@
// @index(['./*.tsx'], f => `export { ${f.name} } from '${f.path}'`)
export { useAccountDetailsStore } from './useAccountDetailsStore'
export { useModalStore } from './useModalStore'
export { useSettings } from './useSettings'
export { useNetworkConfigStore } from './useNetworkConfigStore'
export { useSettingsStore } from './useSettingsStore'
export { useWalletStore } from './useWalletStore'
// @endindex

View File

@ -0,0 +1,8 @@
import create from 'zustand'
import { networkConfig } from 'config/osmo-test-4'
// TODO: Create dynamic network import
export const useNetworkConfigStore = create<NetworkConfig>()(() => {
return networkConfig
})

View File

@ -4,6 +4,6 @@ interface SettingsStore {
enableAnimations: boolean
}
export const useSettings = create<SettingsStore>()(() => ({
export const useSettingsStore = create<SettingsStore>()(() => ({
enableAnimations: true,
}))

View File

@ -5,7 +5,7 @@ import {
} from '@marsprotocol/wallet-connector'
import create from 'zustand'
import { contractAddresses } from 'config/contracts'
import { networkConfig } from 'config/osmo-test-4'
import { MarsAccountNftClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
import { MarsCreditManagerClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
import { MarsSwapperBaseClient } from 'types/generated/mars-swapper-base/MarsSwapperBase.client'
@ -40,22 +40,23 @@ export const useWalletStore = create<WalletStore>()((set, get) => ({
status: WalletConnectionStatus.ReadyForConnection,
clients: {},
actions: {
// TODO: work with slices in one global store instead
initClients: (address, signingClient) => {
if (!signingClient) return
const accountNft = new MarsAccountNftClient(
signingClient,
address,
contractAddresses.accountNft,
networkConfig.contracts.accountNft,
)
const creditManager = new MarsCreditManagerClient(
signingClient,
address,
contractAddresses.creditManager,
networkConfig.contracts.creditManager,
)
const swapperBase = new MarsSwapperBaseClient(
signingClient,
address,
contractAddresses.swapper,
networkConfig.contracts.swapper,
)
set(() => ({

View File

@ -1,28 +0,0 @@
// ENUMS
export enum ChainId {
Mainnet = 'injective-1',
Testnet = 'injective-888',
Devnet = 'injective-777',
}
export enum Wallet {
Metamask = 'metamask',
Ledger = 'ledger',
LedgerLegacy = 'ledger-legacy',
Trezor = 'trezor',
Keplr = 'keplr',
Torus = 'torus',
WalletConnect = 'wallet-connect',
}
// COSMOS
export enum CosmosChainId {
Injective = 'injective-1',
Osmosis = 'osmosis-1',
}
export enum TestnetCosmosChainId {
Osmosis = 'osmo-test-4',
Cosmoshub = 'cosmoshub-testnet',
}

15
src/types/interfaces/asset.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
interface Asset {
color: string
name: string
denom: string
symbol: 'OSMO' | 'ATOM' | 'CRO'
contract_addr?: string
logo: string
decimals: number
hasOraclePrice: boolean
poolId?: number
}
interface OtherAsset extends Omit<Asset, 'symbol'> {
symbol: 'MARS'
}

22
src/types/interfaces/networkConfig.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
interface NetworkConfig {
name: string
hiveUrl: string
rpcUrl: string
restUrl: string
contracts: {
accountNft: string
mockVault: string
marsOracleAdapter: string
swapper: string
mockZapper: string
creditManager: string
redBank: string
oracle: string
}
assets: {
base: Asset
whitelist: Asset[]
other: OtherAsset[]
}
appUrl: string
}

View File

@ -1,16 +0,0 @@
import { bech32 } from 'bech32'
import { Address } from 'ethereumjs-util'
export const getInjectiveAddress = (address: string): string => {
const addressBuffer = Address.fromString(address.toString()).toBuffer()
return bech32.encode('inj', bech32.toWords(addressBuffer))
}
export const getAddressFromInjectiveAddress = (address: string): string => {
if (address.startsWith('0x')) {
return address
}
return `0x${Buffer.from(bech32.fromWords(bech32.decode(address).words)).toString('hex')}`
}

View File

@ -7,6 +7,7 @@ export const formatBalances = (
positionData: Coin[],
tokenPrices: KeyValuePair,
debt: boolean,
whitelistedAssets: Asset[],
marketsData?: MarketData,
): PositionsData[] => {
const balances: PositionsData[] = []
@ -14,16 +15,16 @@ export const formatBalances = (
positionData.forEach((coin) => {
const dataEntry: PositionsData = {
asset: {
amount: getTokenSymbol(coin.denom),
amount: getTokenSymbol(coin.denom, whitelistedAssets),
type: debt ? 'debt' : undefined,
},
value: {
amount: getTokenTotalUSDValue(coin.amount, coin.denom, tokenPrices),
amount: getTokenTotalUSDValue(coin.amount, coin.denom, whitelistedAssets, tokenPrices),
format: 'number',
prefix: '$',
},
size: {
amount: lookup(coin.amount, coin.denom),
amount: lookup(coin.amount, coin.denom, whitelistedAssets),
format: 'number',
maxDecimals: 4,
minDecimals: 0,

View File

@ -1,56 +0,0 @@
export const chainsInfo = {
Injective: {
chainId: 'injective-1',
rpc: 'https://tm.injective.network',
rest: 'https://lcd.injective.network',
stakeCurrency: {
coinDenom: 'INJ',
coinMinimalDenom: 'inj',
coinDecimals: 18,
coinGeckoId: 'injective-protocol',
coinImageUrl: '/tokens/injective.svg',
},
// works
// rest: "https://lcd.injective.network",
},
InjectiveTestnet: {
chainId: 'injective-888',
// need to check
rpc: 'https://testnet.tm.injective.dev',
rest: 'https://testnet.lcd.injective.dev',
stakeCurrency: {
coinDenom: 'INJ',
coinMinimalDenom: 'inj',
coinDecimals: 18,
coinGeckoId: 'injective-protocol',
coinImageUrl: '/tokens/injective.svg',
},
},
Osmosis: {
chainId: 'osmosis-1',
rpc: 'https://rpc.osmosis.zone',
rest: 'https://lcd.osmosis.zone',
stakeCurrency: {
coinDenom: 'OSMO',
coinMinimalDenom: 'uosmo',
coinDecimals: 6,
coinGeckoId: 'osmosis',
coinImageUrl: '/tokens/osmo.svg',
},
},
OsmosisTestnet: {
chainId: 'osmo-test-4',
rpc: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc',
rest: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd',
hive: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-hive/graphql',
stakeCurrency: {
coinDenom: 'OSMO',
coinMinimalDenom: 'uosmo',
coinDecimals: 6,
coinGeckoId: 'osmosis',
coinImageUrl: '/tokens/osmo.svg',
},
},
}
export const chain = chainsInfo.OsmosisTestnet

View File

@ -1,11 +1,9 @@
import { chain } from 'utils/chains'
// StdFee
// TODO: decide some strategy to handle fees
export const hardcodedFee = {
amount: [
{
denom: chain.stakeCurrency.coinMinimalDenom,
denom: 'uosmo',
amount: '100000',
},
],

View File

@ -20,20 +20,21 @@ export const formatCurrency = (value: string | number) => {
export const getTokenTotalUSDValue = (
amount: string,
denom: string,
whitelistedAssets: Asset[],
tokenPrices?: KeyValuePair,
) => {
if (!tokenPrices) return 0
return (
BigNumber(amount)
.div(10 ** getTokenDecimals(denom))
.div(10 ** getTokenDecimals(denom, whitelistedAssets))
.toNumber() * tokenPrices[denom]
)
}
export const lookup = (amount: string | number, denom: string) => {
export const lookup = (amount: string | number, denom: string, whitelistedAssets: Asset[]) => {
return BigNumber(amount)
.div(10 ** getTokenDecimals(denom))
.div(10 ** getTokenDecimals(denom, whitelistedAssets))
.toNumber()
}

View File

@ -1,17 +1,15 @@
import { tokenInfo } from 'config/tokenInfo'
import { networkConfig } from 'config/osmo-test-4'
export const getTokenSymbol = (denom: string) => {
return tokenInfo[denom]?.symbol ?? denom
}
export const getTokenSymbol = (denom: string, whitelistedAssets: Asset[]) =>
whitelistedAssets.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())?.symbol || ''
export const getTokenDecimals = (denom: string) => {
return tokenInfo[denom]?.decimals ?? 6
}
export const getTokenDecimals = (denom: string, whitelistedAssets: Asset[]) =>
whitelistedAssets.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())?.decimals ||
6
export const getTokenIcon = (denom: string) => {
return tokenInfo[denom].icon
}
export const getTokenIcon = (denom: string, whitelistedAssets: Asset[]) =>
whitelistedAssets.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase())?.logo || ''
export const getTokenInfo = (denom: string) => {
return tokenInfo[denom]
}
export const getTokenInfo = (denom: string, whitelistedAssets: Asset[]) =>
whitelistedAssets.find((asset) => asset.denom.toLowerCase() === denom.toLowerCase()) ||
networkConfig.assets.base

View File

@ -2625,10 +2625,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
"@types/node@18.7.14":
version "18.7.14"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.14.tgz#0fe081752a3333392d00586d815485a17c2cf3c9"
integrity sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==
"@types/node@^18.11.13":
version "18.11.17"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.17.tgz#5c009e1d9c38f4a2a9d45c0b0c493fe6cdb4bcb5"
integrity sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==
"@types/parse-json@^4.0.0":
version "4.0.0"