Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd24a1d231 | ||
|
|
414e38afec | ||
|
|
e93850484b | ||
|
|
521b6d6135 | ||
|
|
94772bf4dc | ||
|
|
149f21e7e0 | ||
|
|
0a3ef3a7ab | ||
|
|
fef9935883 |
+1
-1
@@ -39,7 +39,7 @@
|
||||
"@cosmjs/proto-signing": "^0.31.0",
|
||||
"@cosmjs/stargate": "^0.31.0",
|
||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||
"@dydxprotocol/v4-abacus": "^1.2.3",
|
||||
"@dydxprotocol/v4-abacus": "^1.2.5",
|
||||
"@dydxprotocol/v4-client-js": "^1.0.11",
|
||||
"@dydxprotocol/v4-localization": "^1.1.11",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
|
||||
Generated
+8
-8
@@ -1,9 +1,5 @@
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@0xsquid/sdk':
|
||||
specifier: ^1.10.0
|
||||
@@ -27,8 +23,8 @@ dependencies:
|
||||
specifier: ^0.31.0
|
||||
version: 0.31.0
|
||||
'@dydxprotocol/v4-abacus':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3
|
||||
specifier: ^1.2.5
|
||||
version: 1.2.5
|
||||
'@dydxprotocol/v4-client-js':
|
||||
specifier: ^1.0.11
|
||||
version: 1.0.11
|
||||
@@ -991,8 +987,8 @@ packages:
|
||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||
dev: true
|
||||
|
||||
/@dydxprotocol/v4-abacus@1.2.3:
|
||||
resolution: {integrity: sha512-OHGhN4uQo/ikRjeGzf+wGblFvb0uRA916QvQXG4LixsJy7H7HAt7AeZr9LqTM/GqYJicMmZCUS3WIMqgZ20hKA==}
|
||||
/@dydxprotocol/v4-abacus@1.2.5:
|
||||
resolution: {integrity: sha512-pB3Fv1bzJRUDp29kAN61daZ34gTSGrSTNh+/AP3TUB63/Q/gaXQVBf91xVcso4Hw23xM3FwIcrRK0cvOSWgXKg==}
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-client-js@1.0.11:
|
||||
@@ -14813,3 +14809,7 @@ packages:
|
||||
/zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
dev: true
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
<svg width="254" height="77" viewBox="0 0 254 77" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 1258">
|
||||
<g id="Ellipse 9" opacity="0.4" filter="url(#filter0_f_20300_14972)">
|
||||
<ellipse cx="86.5425" cy="-3.91219" rx="116.542" ry="20.0878" fill="#7774FF"/>
|
||||
</g>
|
||||
<g id="Ellipse 10" opacity="0.3" filter="url(#filter1_f_20300_14972)">
|
||||
<circle cx="74.5734" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 12" opacity="0.3" filter="url(#filter2_f_20300_14972)">
|
||||
<circle cx="82.1105" cy="7.64179" r="1.00507" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 22" opacity="0.3" filter="url(#filter3_f_20300_14972)">
|
||||
<circle cx="116.785" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 11" opacity="0.3" filter="url(#filter4_f_20300_14972)">
|
||||
<circle cx="64.774" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 18" opacity="0.3" filter="url(#filter5_f_20300_14972)">
|
||||
<circle cx="96.4322" cy="3.87363" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 20" opacity="0.3" filter="url(#filter6_f_20300_14972)">
|
||||
<circle cx="76.0807" cy="14.9361" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 21" opacity="0.3" filter="url(#filter7_f_20300_14972)">
|
||||
<circle cx="104.725" cy="4.87754" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 23" opacity="0.3" filter="url(#filter8_f_20300_14972)">
|
||||
<circle cx="114.021" cy="7.13925" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 24" opacity="0.3" filter="url(#filter9_f_20300_14972)">
|
||||
<circle cx="109.75" cy="15.4361" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 25" opacity="0.3" filter="url(#filter10_f_20300_14972)">
|
||||
<circle cx="119.801" cy="12.6705" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 27" opacity="0.3" filter="url(#filter11_f_20300_14972)">
|
||||
<circle cx="94.0885" cy="11.0182" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 30" opacity="0.3" filter="url(#filter12_f_20300_14972)">
|
||||
<circle cx="154.475" cy="11.6666" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 29" opacity="0.3" filter="url(#filter13_f_20300_14972)">
|
||||
<circle cx="146.435" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 15" opacity="0.3" filter="url(#filter14_f_20300_14972)">
|
||||
<circle cx="24.0103" cy="4.44785" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 33" opacity="0.3" filter="url(#filter15_f_20300_14972)">
|
||||
<circle cx="-1.05899" cy="13.6783" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 16" opacity="0.3" filter="url(#filter16_f_20300_14972)">
|
||||
<circle cx="17.441" cy="16.4908" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 35" opacity="0.3" filter="url(#filter17_f_20300_14972)">
|
||||
<circle cx="36.0553" cy="6.63535" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 32" opacity="0.3" filter="url(#filter18_f_20300_14972)">
|
||||
<circle cx="10.8707" cy="14.2994" r="0.502536" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 13" opacity="0.3" filter="url(#filter19_f_20300_14972)">
|
||||
<circle cx="55.7274" cy="9.65615" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 19" opacity="0.3" filter="url(#filter20_f_20300_14972)">
|
||||
<circle cx="87.3886" cy="20.7108" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 26" opacity="0.3" filter="url(#filter21_f_20300_14972)">
|
||||
<circle cx="123.82" cy="15.1874" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 36" opacity="0.3" filter="url(#filter22_f_20300_14972)">
|
||||
<circle cx="134.876" cy="14.4335" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 28" opacity="0.3" filter="url(#filter23_f_20300_14972)">
|
||||
<circle cx="129.6" cy="6.38662" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 14" opacity="0.3" filter="url(#filter24_f_20300_14972)">
|
||||
<circle cx="41.6571" cy="14.9335" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 31" opacity="0.3" filter="url(#filter25_f_20300_14972)">
|
||||
<circle cx="4.21767" cy="17.9491" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 34" opacity="0.3" filter="url(#filter26_f_20300_14972)">
|
||||
<circle cx="12.2177" cy="6.88662" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
<g id="Ellipse 17" opacity="0.3" filter="url(#filter27_f_20300_14972)">
|
||||
<circle cx="50.2001" cy="3.6249" r="0.753803" fill="#9A9AFF"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_20300_14972" x="-94" y="-88" width="361.085" height="168.176" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="32" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter1_f_20300_14972" x="72.5633" y="2.61993" width="4.01991" height="4.02186" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter2_f_20300_14972" x="80.6029" y="6.13418" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter3_f_20300_14972" x="115.278" y="3.12246" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter4_f_20300_14972" x="63.2664" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter5_f_20300_14972" x="94.9246" y="2.36602" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter6_f_20300_14972" x="74.5731" y="13.4285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter7_f_20300_14972" x="103.218" y="3.36993" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter8_f_20300_14972" x="112.513" y="5.63165" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter9_f_20300_14972" x="108.242" y="13.9285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter10_f_20300_14972" x="118.294" y="11.1629" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter11_f_20300_14972" x="92.5809" y="9.51055" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter12_f_20300_14972" x="153.47" y="10.6615" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter13_f_20300_14972" x="144.928" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter14_f_20300_14972" x="22.5027" y="2.94024" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter15_f_20300_14972" x="-2.56659" y="12.1707" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter16_f_20300_14972" x="15.9334" y="14.9832" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter17_f_20300_14972" x="35.0502" y="5.63028" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter18_f_20300_14972" x="9.86563" y="13.2943" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter19_f_20300_14972" x="53.9686" y="7.89727" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter20_f_20300_14972" x="85.6297" y="18.952" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter21_f_20300_14972" x="122.061" y="13.4285" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter22_f_20300_14972" x="133.117" y="12.6746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter23_f_20300_14972" x="127.842" y="4.62774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter24_f_20300_14972" x="39.8982" y="13.1746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter25_f_20300_14972" x="2.4588" y="16.1902" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter26_f_20300_14972" x="10.4588" y="5.12774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
<filter id="filter27_f_20300_14972" x="48.4412" y="1.86602" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
@@ -14,7 +14,7 @@ export const DiffArrowStory: Story<DiffArrowProps> = (args) => (
|
||||
|
||||
DiffArrowStory.argTypes = {
|
||||
direction: {
|
||||
options: ['left', 'right'],
|
||||
options: ['left', 'right', 'up', 'down'],
|
||||
control: { type: 'select' },
|
||||
defaultValue: 'right',
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ type ElementProps = {
|
||||
|
||||
type StyleProps = {
|
||||
className?: string;
|
||||
direction?: 'right' | 'left';
|
||||
direction?: 'right' | 'left' | 'up' | 'down';
|
||||
};
|
||||
|
||||
export type DiffArrowProps = ElementProps & StyleProps;
|
||||
@@ -57,5 +57,11 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
|
||||
left: css`
|
||||
transform: scaleX(-1);
|
||||
`,
|
||||
up: css`
|
||||
transform: rotate(-90deg);
|
||||
`,
|
||||
down: css`
|
||||
transform: rotate(90deg);
|
||||
`
|
||||
}[direction || 'right'])}
|
||||
`;
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
MenuIcon,
|
||||
MigrateIcon,
|
||||
MintscanIcon,
|
||||
MoonIcon,
|
||||
OrderbookIcon,
|
||||
OrderCanceledIcon,
|
||||
OrderFilledIcon,
|
||||
@@ -59,12 +60,14 @@ import {
|
||||
PriceChartIcon,
|
||||
PrivacyIcon,
|
||||
QrIcon,
|
||||
RewardStarIcon,
|
||||
SearchIcon,
|
||||
SendIcon,
|
||||
ShareIcon,
|
||||
ShowIcon,
|
||||
TogglesMenuIcon,
|
||||
StarIcon,
|
||||
SunIcon,
|
||||
TerminalIcon,
|
||||
TradeIcon,
|
||||
TransferIcon,
|
||||
@@ -118,6 +121,7 @@ export enum IconName {
|
||||
Menu = 'Menu',
|
||||
Migrate = 'Migrate',
|
||||
Mintscan = 'Mintscan',
|
||||
Moon = 'Moon',
|
||||
Onboarding = 'Onboarding',
|
||||
Orderbook = 'OrderbookIcon',
|
||||
OrderCanceled = 'OrderCanceled',
|
||||
@@ -134,11 +138,13 @@ export enum IconName {
|
||||
PriceChart = 'PriceChart',
|
||||
Privacy = 'Privacy',
|
||||
Qr = 'Qr',
|
||||
RewardStar = 'RewardStar',
|
||||
Search = 'Search',
|
||||
Send = 'Send',
|
||||
Share = 'Share',
|
||||
Show = 'Show',
|
||||
Star = 'Star',
|
||||
Sun = 'Sun',
|
||||
Terminal = 'Terminal',
|
||||
TogglesMenu = 'TogglesMenu',
|
||||
Trade = 'Trade',
|
||||
@@ -193,6 +199,7 @@ const icons = {
|
||||
[IconName.Menu]: MenuIcon,
|
||||
[IconName.Migrate]: MigrateIcon,
|
||||
[IconName.Mintscan]: MintscanIcon,
|
||||
[IconName.Moon]: MoonIcon,
|
||||
[IconName.Orderbook]: OrderbookIcon,
|
||||
[IconName.OrderCanceled]: OrderCanceledIcon,
|
||||
[IconName.OrderFilled]: OrderFilledIcon,
|
||||
@@ -208,11 +215,13 @@ const icons = {
|
||||
[IconName.PriceChart]: PriceChartIcon,
|
||||
[IconName.Privacy]: PrivacyIcon,
|
||||
[IconName.Qr]: QrIcon,
|
||||
[IconName.RewardStar]: RewardStarIcon,
|
||||
[IconName.Search]: SearchIcon,
|
||||
[IconName.Send]: SendIcon,
|
||||
[IconName.Share]: ShareIcon,
|
||||
[IconName.Show]: ShowIcon,
|
||||
[IconName.Star]: StarIcon,
|
||||
[IconName.Sun]: SunIcon,
|
||||
[IconName.Terminal]: TerminalIcon,
|
||||
[IconName.TogglesMenu]: TogglesMenuIcon,
|
||||
[IconName.Trade]: TradeIcon,
|
||||
|
||||
@@ -27,9 +27,8 @@ export const ToastArea = ({ swipeDirection, children, className }: ToastAreaProp
|
||||
const $ToastArea = styled.aside`
|
||||
// Params
|
||||
--toasts-gap: 0.5rem;
|
||||
|
||||
|
||||
// Rules
|
||||
${layoutMixins.scrollArea}
|
||||
z-index: 1;
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
@@ -96,6 +96,7 @@ export type AnalyticsEventData<T extends AnalyticsEvent> =
|
||||
elapsedTime?: number;
|
||||
blockHeight?: number;
|
||||
indexerBlockHeight?: number;
|
||||
trailingBlocks?: number;
|
||||
}
|
||||
: // Navigation
|
||||
T extends AnalyticsEvent.NavigatePage
|
||||
|
||||
@@ -87,6 +87,8 @@ export type NotificationDisplayData = {
|
||||
slotTitleLeft?: React.ReactNode;
|
||||
slotTitleRight?: React.ReactNode;
|
||||
|
||||
groupKey: string; // Grouping key toast notification stacking
|
||||
|
||||
// Overrides title/body for Notification in NotificationMenu
|
||||
renderCustomBody?: ({
|
||||
isToast,
|
||||
|
||||
@@ -97,7 +97,7 @@ export const useAnalytics = () => {
|
||||
}, []);
|
||||
|
||||
// AnalyticsEvent.NetworkStatus
|
||||
const { height, indexerHeight, status } = useApiState();
|
||||
const { height, indexerHeight, status, trailingBlocks} = useApiState();
|
||||
|
||||
useEffect(() => {
|
||||
if (status) {
|
||||
@@ -114,6 +114,7 @@ export const useAnalytics = () => {
|
||||
elapsedTime: lastSuccessfulIndexerRpcQuery && Date.now() - lastSuccessfulIndexerRpcQuery,
|
||||
blockHeight: height ?? undefined,
|
||||
indexerBlockHeight: indexerHeight ?? undefined,
|
||||
trailingBlocks: trailingBlocks ?? undefined
|
||||
});
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
@@ -71,7 +71,7 @@ export const getIndexerHeight = (apiState: Nullable<AbacusApiState>) => {
|
||||
export const useApiState = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
const apiState = useSelector(getApiState, shallowEqual);
|
||||
const { haltedBlock, height, status, trailingBlocks } = apiState ?? {};
|
||||
const { haltedBlock, height, status, trailingBlocks} = apiState ?? {};
|
||||
const statusErrorMessage = getStatusErrorMessage({ apiState, stringGetter });
|
||||
const indexerHeight = getIndexerHeight(apiState);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
||||
|
||||
import { AssetIcon } from '@/components/AssetIcon';
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
import { BlockRewardNotification } from '@/views/notifications/BlockRewardNotification';
|
||||
import { TradeNotification } from '@/views/notifications/TradeNotification';
|
||||
import { TransferStatusNotification } from '@/views/notifications/TransferStatusNotification';
|
||||
|
||||
@@ -80,6 +81,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: abacusNotificationType,
|
||||
renderCustomBody: ({ isToast, notification }) => (
|
||||
<TradeNotification
|
||||
isToast={isToast}
|
||||
@@ -93,6 +95,29 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'blockReward': {
|
||||
trigger(
|
||||
abacusNotif.id,
|
||||
{
|
||||
icon: abacusNotif.image && <$Icon src={abacusNotif.image} alt="" />,
|
||||
title: stringGetter({ key: abacusNotif.title }),
|
||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: abacusNotificationType,
|
||||
renderCustomBody: ({ isToast, notification }) => (
|
||||
<BlockRewardNotification
|
||||
isToast={isToast}
|
||||
data={parsedData}
|
||||
notification={notification}
|
||||
/>
|
||||
),
|
||||
},
|
||||
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data],
|
||||
true
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
trigger(
|
||||
abacusNotif.id,
|
||||
@@ -102,6 +127,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: abacusNotificationType,
|
||||
},
|
||||
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data]
|
||||
);
|
||||
@@ -197,6 +223,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
/>
|
||||
),
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: NotificationType.SquidTransfer,
|
||||
},
|
||||
[isFinished]
|
||||
);
|
||||
@@ -242,6 +269,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
},
|
||||
}),
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: NotificationType.ReleaseUpdates,
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { EvmDerivedAddresses } from '@/constants/account';
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
|
||||
@@ -104,11 +105,17 @@ export const useWalletConnection = () => {
|
||||
[walletConnectConfig, walletType, walletConnectionType]
|
||||
);
|
||||
|
||||
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector })
|
||||
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector });
|
||||
const { suggestAndConnect: connectGraz } = useConnectGraz();
|
||||
const [evmDerivedAddresses] = useLocalStorage({
|
||||
key: LocalStorageKey.EvmDerivedAddresses,
|
||||
defaultValue: {} as EvmDerivedAddresses,
|
||||
});
|
||||
|
||||
const connectWallet = useCallback(
|
||||
async ({ walletType }: { walletType: WalletType }) => {
|
||||
async ({ walletType, forceConnect }: { walletType?: WalletType; forceConnect?: boolean }) => {
|
||||
if (!walletType) return { walletType, walletConnectionType };
|
||||
|
||||
const walletConnection = getWalletConnection({ walletType });
|
||||
|
||||
try {
|
||||
@@ -132,7 +139,11 @@ export const useWalletConnection = () => {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!isConnectedWagmi) {
|
||||
const isAccountConnected = Boolean(
|
||||
evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature
|
||||
);
|
||||
// if account connected (via remember me), do not show wagmi popup until forceConnect
|
||||
if (!isConnectedWagmi && (forceConnect || !isAccountConnected)) {
|
||||
await connectWagmi({
|
||||
connector: resolveWagmiConnector({
|
||||
walletType,
|
||||
@@ -228,6 +239,12 @@ export const useWalletConnection = () => {
|
||||
evmAddressWagmi,
|
||||
signerWagmi,
|
||||
publicClientWagmi,
|
||||
isConnectedWagmi,
|
||||
connectWallet: () =>
|
||||
connectWallet({
|
||||
walletType: selectedWalletType,
|
||||
forceConnect: true,
|
||||
}),
|
||||
|
||||
// Wallet connection (Cosmos)
|
||||
dydxAddress,
|
||||
|
||||
@@ -39,6 +39,7 @@ export { default as MarketsIcon } from './markets.svg';
|
||||
export { default as MenuIcon } from './menu.svg';
|
||||
export { default as MigrateIcon } from './migrate.svg';
|
||||
export { default as MintscanIcon } from './logos/mintscan.svg';
|
||||
export { default as MoonIcon } from './moon.svg';
|
||||
export { default as OrderbookIcon } from './orderbook.svg';
|
||||
export { default as OverviewIcon } from './overview.svg';
|
||||
export { default as PencilIcon } from './pencil.svg';
|
||||
@@ -50,11 +51,13 @@ export { default as PriceChartIcon } from './price-chart.svg';
|
||||
export { default as PrivacyIcon } from './privacy.svg';
|
||||
export { default as ProfileIcon } from './profile.svg';
|
||||
export { default as QrIcon } from './qr.svg';
|
||||
export { default as RewardStarIcon } from './reward-star.svg';
|
||||
export { default as SearchIcon } from './search.svg';
|
||||
export { default as SendIcon } from './send.svg';
|
||||
export { default as ShareIcon } from './share.svg';
|
||||
export { default as ShowIcon } from './show.svg';
|
||||
export { default as StarIcon } from './star.svg';
|
||||
export { default as SunIcon } from './sun.svg';
|
||||
export { default as TerminalIcon } from './terminal.svg';
|
||||
export { default as TogglesMenuIcon } from './toggles-menu.svg';
|
||||
export { default as TradeIcon } from './trade.svg';
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 380 B |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 481 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 393 B |
+34
-59
@@ -1,7 +1,11 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
|
||||
import { NotificationStatus } from '@/constants/notifications';
|
||||
import {
|
||||
type Notification,
|
||||
type NotificationDisplayData,
|
||||
NotificationStatus,
|
||||
} from '@/constants/notifications';
|
||||
import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
||||
import { useNotifications } from '@/hooks/useNotifications';
|
||||
import { useBreakpoints } from '@/hooks/useBreakpoints';
|
||||
@@ -13,54 +17,31 @@ import { Toast } from '@/components/Toast';
|
||||
import { ToastArea } from '@/components/ToastArea';
|
||||
import { ToggleButton } from '@/components/ToggleButton';
|
||||
|
||||
type ElementProps = {
|
||||
notifications: {
|
||||
notification: Notification<any, any>;
|
||||
key: string;
|
||||
displayData: NotificationDisplayData;
|
||||
}[];
|
||||
};
|
||||
|
||||
type StyleProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const MAX_TOASTS = 10;
|
||||
|
||||
export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
export const NotificationStack = ({ notifications, className }: ElementProps & StyleProps) => {
|
||||
const [shouldStackNotifications, setshouldStackNotifications] = useState(true);
|
||||
|
||||
const {
|
||||
notifications,
|
||||
getKey,
|
||||
getDisplayData,
|
||||
markUnseen,
|
||||
markSeen,
|
||||
isMenuOpen,
|
||||
onNotificationAction,
|
||||
} = useNotifications();
|
||||
|
||||
const { markUnseen, markSeen, onNotificationAction } = useNotifications();
|
||||
const { isMobile } = useBreakpoints();
|
||||
const notificationMap = useMemo(() => {
|
||||
return (
|
||||
Object.values(notifications)
|
||||
// Sort by time of first trigger
|
||||
.sort(
|
||||
(n1, n2) =>
|
||||
n1.timestamps[NotificationStatus.Triggered]! -
|
||||
n2.timestamps[NotificationStatus.Triggered]!
|
||||
)
|
||||
.map((notification) => ({
|
||||
notification,
|
||||
key: getKey(notification),
|
||||
displayData: getDisplayData(notification),
|
||||
}))
|
||||
.filter(
|
||||
({ displayData, notification }) =>
|
||||
displayData && notification.status < NotificationStatus.Unseen
|
||||
)
|
||||
.slice(-MAX_TOASTS)
|
||||
);
|
||||
}, [notifications, getKey, getDisplayData]);
|
||||
|
||||
if (isMenuOpen) return null;
|
||||
|
||||
const hasMultipleToasts = notificationMap.length > 1;
|
||||
const hasMultipleToasts = notifications.length > 1;
|
||||
|
||||
return (
|
||||
<StyledToastArea swipeDirection={isMobile ? 'up' : 'right'} className={className}>
|
||||
<StyledToastArea
|
||||
swipeDirection={isMobile ? 'up' : 'right'}
|
||||
className={className}
|
||||
size={notifications.length}
|
||||
>
|
||||
{hasMultipleToasts && (
|
||||
<StyledToggleButton
|
||||
shape={ButtonShape.Pill}
|
||||
@@ -72,12 +53,12 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
</StyledToggleButton>
|
||||
)}
|
||||
|
||||
{notificationMap.map(({ notification, key, displayData }, idx) => (
|
||||
{notifications.map(({ notification, key, displayData }, idx) => (
|
||||
<StyledToast
|
||||
key={key}
|
||||
isStacked={shouldStackNotifications}
|
||||
isStacked={idx > 0 && shouldStackNotifications}
|
||||
isOpen={notification.status < NotificationStatus.Unseen}
|
||||
layer={notificationMap.length - 1 - idx}
|
||||
layer={idx}
|
||||
notification={notification}
|
||||
slotIcon={displayData.icon}
|
||||
slotTitle={displayData.title}
|
||||
@@ -110,19 +91,13 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const StyledToastArea = styled(ToastArea)`
|
||||
position: absolute;
|
||||
width: min(17.5rem, 100%);
|
||||
inset: 0 0 0 auto;
|
||||
|
||||
padding: 0.75rem 0.75rem 0.75rem 0;
|
||||
|
||||
mask-image: linear-gradient(to left, transparent, white 0.5rem);
|
||||
|
||||
@media ${breakpoints.mobile} {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
}
|
||||
const StyledToastArea = styled(ToastArea)<{ size: number }>`
|
||||
position: relative;
|
||||
${({ size }) =>
|
||||
size &&
|
||||
css`
|
||||
padding-bottom: calc(${size - 1} * 2px);
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
||||
@@ -133,7 +108,7 @@ const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(${layer} * 2px);
|
||||
right: calc(${layer} * -2px);
|
||||
right: 0;
|
||||
`
|
||||
: css`
|
||||
margin-bottom: 0.75rem;
|
||||
@@ -145,7 +120,7 @@ const StyledToggleButton = styled(ToggleButton)<{ isPressed: boolean }>`
|
||||
pointer-events: auto;
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
top: -0.5rem;
|
||||
left: calc(50% - 0.75rem);
|
||||
--button-width: 2rem;
|
||||
--button-height: 1rem;
|
||||
@@ -0,0 +1,71 @@
|
||||
import { useMemo } from 'react';
|
||||
import { groupBy } from 'lodash';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { breakpoints } from '@/styles';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
import { NotificationStatus } from '@/constants/notifications';
|
||||
import { useNotifications } from '@/hooks/useNotifications';
|
||||
|
||||
import { NotificationStack } from './NotifcationStack';
|
||||
|
||||
type StyleProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const MAX_TOASTS = 10;
|
||||
|
||||
export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
const { notifications, getKey, getDisplayData, isMenuOpen } = useNotifications();
|
||||
|
||||
const notificationMapByType = useMemo(() => {
|
||||
const notificationMap = Object.values(notifications)
|
||||
// Sort by time of first trigger
|
||||
.sort(
|
||||
(n1, n2) =>
|
||||
n1.timestamps[NotificationStatus.Triggered]! -
|
||||
n2.timestamps[NotificationStatus.Triggered]!
|
||||
)
|
||||
.map((notification) => ({
|
||||
notification,
|
||||
key: getKey(notification),
|
||||
displayData: getDisplayData(notification),
|
||||
}))
|
||||
.filter(
|
||||
({ displayData, notification }) =>
|
||||
displayData && notification.status < NotificationStatus.Unseen
|
||||
)
|
||||
.slice(-MAX_TOASTS);
|
||||
return groupBy(notificationMap, (notification) => notification.displayData?.groupKey);
|
||||
}, [notifications, getKey, getDisplayData]);
|
||||
|
||||
if (isMenuOpen) return null;
|
||||
|
||||
return (
|
||||
<StyledToastArea className={className}>
|
||||
{Object.keys(notificationMapByType).map((groupKey) => (
|
||||
<NotificationStack notifications={notificationMapByType[groupKey]} key={groupKey} />
|
||||
))}
|
||||
</StyledToastArea>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledToastArea = styled.div`
|
||||
${layoutMixins.scrollArea}
|
||||
|
||||
position: absolute;
|
||||
width: min(17.5rem, 100%);
|
||||
inset: 0 0 0 auto;
|
||||
|
||||
padding: 0.75rem 0.75rem 0.75rem 0;
|
||||
|
||||
mask-image: linear-gradient(to left, transparent, white 0.5rem);
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
@media ${breakpoints.mobile} {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
}
|
||||
`;
|
||||
@@ -56,6 +56,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
this.store = undefined;
|
||||
}
|
||||
|
||||
get isNobleClientConnected(): boolean {
|
||||
return this.nobleClient?.isConnected ?? false;
|
||||
}
|
||||
|
||||
setStore(store: RootStore): void {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
+10
-5
@@ -171,6 +171,15 @@ class AbacusStateManager {
|
||||
this.setTransferValue({ value: null, field: TransferInputField.usdcSize });
|
||||
};
|
||||
|
||||
resetInputState = () => {
|
||||
this.clearTransferInputValues();
|
||||
this.setTransferValue({
|
||||
field: TransferInputField.type,
|
||||
value: null,
|
||||
});
|
||||
this.clearTradeInputValues();
|
||||
};
|
||||
|
||||
// ------ Set Data ------ //
|
||||
setStore = (store: RootStore) => {
|
||||
this.store = store;
|
||||
@@ -262,11 +271,7 @@ class AbacusStateManager {
|
||||
) => this.stateManager.cancelOrder(orderId, callback);
|
||||
|
||||
cctpWithdraw = (
|
||||
callback: (
|
||||
success: boolean,
|
||||
parsingError: Nullable<ParsingError>,
|
||||
data: string,
|
||||
) => void
|
||||
callback: (success: boolean, parsingError: Nullable<ParsingError>, data: string) => void
|
||||
): void => this.stateManager.commitCCTPWithdraw(callback);
|
||||
|
||||
// ------ Utils ------ //
|
||||
|
||||
@@ -11,16 +11,16 @@ class TestFlags {
|
||||
const params = new URLSearchParams(queryParamsString);
|
||||
|
||||
for (const [key, value] of params) {
|
||||
this.queryParams[key] = value;
|
||||
this.queryParams[key.toLowerCase()] = value;
|
||||
}
|
||||
}
|
||||
|
||||
get displayInitializingMarkets() {
|
||||
return !!this.queryParams.displayInitializingMarkets;
|
||||
return !!this.queryParams.displayinitializingmarkets;
|
||||
}
|
||||
|
||||
get withCCTP() {
|
||||
return !!this.queryParams.withCCTP;
|
||||
get showMobileSignInOption() {
|
||||
return !!this.queryParams.mobilesignin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ export const MarketDetails: React.FC = () => {
|
||||
if (!configs) return null;
|
||||
|
||||
const {
|
||||
basePositionNotional,
|
||||
tickSize,
|
||||
stepSize,
|
||||
initialMarginFraction,
|
||||
|
||||
@@ -72,6 +72,7 @@ export const GenerateKeys = ({
|
||||
if (message) {
|
||||
log('GenerateKeys/switchNetwork', error, { walletErrorType });
|
||||
setError(message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { EvmAddress } from '@/constants/wallets';
|
||||
import { useAccounts, useDebounce, useStringGetter, useSelectedNetwork } from '@/hooks';
|
||||
import { useAccountBalance, CHAIN_DEFAULT_TOKEN_ADDRESS } from '@/hooks/useAccountBalance';
|
||||
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
||||
import { useWalletConnection } from '@/hooks/useWalletConnection';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { formMixins } from '@/styles/formMixins';
|
||||
@@ -120,11 +121,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
});
|
||||
|
||||
return () => {
|
||||
abacusStateManager.clearTransferInputValues();
|
||||
abacusStateManager.setTransferValue({
|
||||
field: TransferInputField.type,
|
||||
value: null,
|
||||
});
|
||||
abacusStateManager.resetInputState();
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -235,6 +232,10 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
throw new Error('Missing request payload');
|
||||
}
|
||||
|
||||
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||
throw new Error('Noble RPC endpoint unaccessible');
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
await validateTokenApproval();
|
||||
@@ -364,6 +365,8 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
return <LoadingSpace id="DepositForm" />;
|
||||
}
|
||||
|
||||
const [requireUserActionInWallet, setRequireUserActionInWallet] = useState(false);
|
||||
|
||||
return (
|
||||
<Styled.Form onSubmit={onSubmit}>
|
||||
<ChainSelectMenu selectedChain={chainIdStr || undefined} onSelectChain={onSelectChain} />
|
||||
@@ -382,7 +385,11 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
/>
|
||||
</Styled.WithDetailsReceipt>
|
||||
{errorMessage && <AlertMessage type={AlertType.Error}>{errorMessage}</AlertMessage>}
|
||||
|
||||
{requireUserActionInWallet && (
|
||||
<AlertMessage type={AlertType.Warning}>
|
||||
{stringGetter({ key: STRING_KEYS.CHECK_WALLET_FOR_REQUEST })}
|
||||
</AlertMessage>
|
||||
)}
|
||||
<Styled.Footer>
|
||||
<DepositButtonAndReceipt
|
||||
isDisabled={isDisabled}
|
||||
@@ -391,6 +398,8 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
setSlippage={onSetSlippage}
|
||||
slippage={slippage}
|
||||
sourceToken={sourceToken || undefined}
|
||||
setRequireUserActionInWallet={setRequireUserActionInWallet}
|
||||
setError={setError}
|
||||
/>
|
||||
</Styled.Footer>
|
||||
</Styled.Form>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { type Dispatch, type ReactNode, type SetStateAction, useState, useMemo } from 'react';
|
||||
import { type Dispatch, type SetStateAction, useState, type ReactNode, useEffect } from 'react';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import type { RouteData } from '@0xsquid/sdk';
|
||||
import { formatUnits } from 'viem';
|
||||
|
||||
import { ButtonAction, ButtonShape, ButtonSize, ButtonType } from '@/constants/buttons';
|
||||
|
||||
@@ -12,6 +11,7 @@ import { NumberSign, TOKEN_DECIMALS } from '@/constants/numbers';
|
||||
|
||||
import { useStringGetter, useTokenConfigs } from '@/hooks';
|
||||
import { useMatchingEvmNetwork } from '@/hooks/useMatchingEvmNetwork';
|
||||
import { useWalletConnection } from '@/hooks/useWalletConnection';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
@@ -39,7 +39,8 @@ type ElementProps = {
|
||||
isLoading?: boolean;
|
||||
|
||||
chainId?: string | number;
|
||||
setError?: Dispatch<SetStateAction<Error | undefined>>;
|
||||
setError?: Dispatch<SetStateAction<Error | null>>;
|
||||
setRequireUserActionInWallet: (val: boolean) => void;
|
||||
slippage: number;
|
||||
slotError?: ReactNode;
|
||||
setSlippage: (slippage: number) => void;
|
||||
@@ -57,6 +58,7 @@ export const DepositButtonAndReceipt = ({
|
||||
isDisabled,
|
||||
isLoading,
|
||||
slotError,
|
||||
setRequireUserActionInWallet,
|
||||
}: ElementProps) => {
|
||||
const [showFeeBreakdown, setShowFeeBreakdown] = useState(false);
|
||||
const [isEditingSlippage, setIsEditingSlipapge] = useState(false);
|
||||
@@ -64,6 +66,24 @@ export const DepositButtonAndReceipt = ({
|
||||
|
||||
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
||||
|
||||
const { connectWallet, isConnectedWagmi } = useWalletConnection();
|
||||
|
||||
const connectWagmi = async () => {
|
||||
try {
|
||||
setRequireUserActionInWallet(false);
|
||||
await connectWallet();
|
||||
setRequireUserActionInWallet(false);
|
||||
} catch (e) {
|
||||
setRequireUserActionInWallet(true);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isConnectedWagmi && canAccountTrade) {
|
||||
connectWagmi();
|
||||
}
|
||||
}, [isConnectedWagmi, canAccountTrade]);
|
||||
|
||||
const {
|
||||
matchNetwork: switchNetwork,
|
||||
isSwitchingNetwork,
|
||||
@@ -80,7 +100,7 @@ export const DepositButtonAndReceipt = ({
|
||||
useSelector(getSubaccountBuyingPower, shallowEqual) || {};
|
||||
|
||||
const { isCctp, summary, requestPayload } = useSelector(getTransferInputs, shallowEqual) || {};
|
||||
const { usdcDecimals, usdcLabel } = useTokenConfigs();
|
||||
const { usdcLabel } = useTokenConfigs();
|
||||
|
||||
const feeSubitems: DetailsItem[] = [];
|
||||
|
||||
@@ -116,7 +136,9 @@ export const DepositButtonAndReceipt = ({
|
||||
{stringGetter({ key: STRING_KEYS.EXPECTED_DEPOSIT_AMOUNT })} <Tag>{usdcLabel}</Tag>
|
||||
</span>
|
||||
),
|
||||
value: <Output type={OutputType.Fiat} fractionDigits={TOKEN_DECIMALS} value={summary?.toAmount} />,
|
||||
value: (
|
||||
<Output type={OutputType.Fiat} fractionDigits={TOKEN_DECIMALS} value={summary?.toAmount} />
|
||||
),
|
||||
subitems: [
|
||||
{
|
||||
key: 'minimum-deposit-amount',
|
||||
@@ -126,7 +148,11 @@ export const DepositButtonAndReceipt = ({
|
||||
</span>
|
||||
),
|
||||
value: (
|
||||
<Output type={OutputType.Fiat} fractionDigits={TOKEN_DECIMALS} value={summary?.toAmountMin} />
|
||||
<Output
|
||||
type={OutputType.Fiat}
|
||||
fractionDigits={TOKEN_DECIMALS}
|
||||
value={summary?.toAmountMin}
|
||||
/>
|
||||
),
|
||||
tooltip: 'minimum-deposit-amount',
|
||||
},
|
||||
@@ -253,6 +279,8 @@ export const DepositButtonAndReceipt = ({
|
||||
>
|
||||
{!canAccountTrade ? (
|
||||
<OnboardingTriggerButton size={ButtonSize.Base} />
|
||||
) : !isConnectedWagmi ? (
|
||||
<Button action={ButtonAction.Primary} onClick={connectWallet} state={{ isLoading: true }} />
|
||||
) : !isMatchingNetwork ? (
|
||||
<Button
|
||||
action={ButtonAction.Primary}
|
||||
|
||||
@@ -101,11 +101,7 @@ export const WithdrawForm = () => {
|
||||
});
|
||||
|
||||
return () => {
|
||||
abacusStateManager.clearTransferInputValues();
|
||||
abacusStateManager.setTransferValue({
|
||||
field: TransferInputField.type,
|
||||
value: null,
|
||||
});
|
||||
abacusStateManager.resetInputState();
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -148,6 +144,10 @@ export const WithdrawForm = () => {
|
||||
throw new Error('Invalid request payload');
|
||||
}
|
||||
|
||||
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||
throw new Error('Noble RPC endpoint unaccessible');
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(undefined);
|
||||
|
||||
|
||||
@@ -118,11 +118,7 @@ export const TransferForm = ({
|
||||
onChangeAsset(selectedAsset);
|
||||
|
||||
return () => {
|
||||
abacusStateManager.clearTransferInputValues();
|
||||
abacusStateManager.setTransferValue({
|
||||
field: TransferInputField.type,
|
||||
value: null,
|
||||
});
|
||||
abacusStateManager.resetInputState();
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ import { STRING_KEYS, StringGetterFunction, TOOLTIP_STRING_KEYS } from '@/consta
|
||||
import { isMainnet } from '@/constants/networks';
|
||||
import { DydxChainAsset, wallets } from '@/constants/wallets';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { headerMixins } from '@/styles/headerMixins';
|
||||
|
||||
import {
|
||||
useAccounts,
|
||||
useBreakpoints,
|
||||
@@ -35,10 +38,8 @@ import { getOnboardingState, getSubaccount } from '@/state/accountSelectors';
|
||||
|
||||
import { isTruthy } from '@/lib/isTruthy';
|
||||
import { truncateAddress } from '@/lib/wallet';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { headerMixins } from '@/styles/headerMixins';
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
import { testFlags } from '@/lib/testFlags';
|
||||
|
||||
export const AccountMenu = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
@@ -178,7 +179,7 @@ export const AccountMenu = () => {
|
||||
},
|
||||
...(onboardingState === OnboardingState.AccountConnected && hdKey
|
||||
? [
|
||||
!isMainnet && {
|
||||
(!isMainnet || testFlags.showMobileSignInOption) && {
|
||||
value: 'MobileQrSignIn',
|
||||
icon: <Icon iconName={IconName.Qr} />,
|
||||
label: stringGetter({ key: STRING_KEYS.TITLE_SIGN_INTO_MOBILE }),
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { useStringGetter } from '@/hooks';
|
||||
|
||||
import { Details } from '@/components/Details';
|
||||
import { Notification, NotificationProps } from '@/components/Notification';
|
||||
import { Output, OutputType } from '@/components/Output';
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
|
||||
type ElementProps = {
|
||||
data: {
|
||||
BLOCK_REWARD_AMOUNT: string;
|
||||
BLOCK_REWARD_HEIGHT: string;
|
||||
BLOCK_REWARD_TIME_MILLISECONDS: string;
|
||||
TOKEN_NAME: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type BlockRewardNotificationProps = NotificationProps & ElementProps;
|
||||
|
||||
export const BlockRewardNotification = ({
|
||||
isToast,
|
||||
data,
|
||||
notification,
|
||||
}: BlockRewardNotificationProps) => {
|
||||
const stringGetter = useStringGetter();
|
||||
const { BLOCK_REWARD_AMOUNT, TOKEN_NAME } = data;
|
||||
|
||||
return (
|
||||
<Styled.Notification
|
||||
isToast={isToast}
|
||||
notification={notification}
|
||||
slotIcon={<Icon iconName={IconName.RewardStar} />}
|
||||
slotTitle={stringGetter({ key: STRING_KEYS.TRADING_REWARD_RECEIVED })}
|
||||
slotCustomContent={
|
||||
<Styled.Details
|
||||
items={[
|
||||
{
|
||||
key: 'block_reward',
|
||||
label: stringGetter({ key: STRING_KEYS.BLOCK_REWARD }),
|
||||
value: (
|
||||
<Styled.Output
|
||||
type={OutputType.Asset}
|
||||
value={BLOCK_REWARD_AMOUNT}
|
||||
tag={TOKEN_NAME}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.Details = styled(Details)`
|
||||
--details-item-height: 1.5rem;
|
||||
|
||||
dd {
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
`;
|
||||
|
||||
Styled.Notification = styled(Notification)`
|
||||
background-image: url('/dots-background-2.svg');
|
||||
background-size: cover;
|
||||
`;
|
||||
|
||||
Styled.Output = styled(Output)`
|
||||
&:before {
|
||||
content: '+';
|
||||
color: var(--color-positive);
|
||||
margin-right: 0.5ch;
|
||||
}
|
||||
`;
|
||||
Reference in New Issue
Block a user