mirror of
				https://github.com/Instadapp/assembly.git
				synced 2024-07-29 22:37:06 +00:00 
			
		
		
		
	Merge branch 'l-sp' of https://github.com/backstop-protocol/assembly into l-sp
This commit is contained in:
		
						commit
						95d148f570
					
				
							
								
								
									
										400
									
								
								abis/read/yearnV2.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								abis/read/yearnV2.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,400 @@ | |||
| [ | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "contract YearnV2Interface", | ||||
|                 "name": "vault", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getAvailableDepositLimit", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "owner", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "contract YearnV2Interface", | ||||
|                 "name": "vault", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getBalance", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "owner", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "contract YearnV2Interface", | ||||
|                 "name": "vault", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getExpectedShareValue", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "owner", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "address[]", | ||||
|                 "name": "wantAddresses", | ||||
|                 "type": "address[]" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getPositions", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "components": [ | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "vaultLatestVersion", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "vault", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "want", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "pricePerShare", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "availableDepositLimit", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "totalAssets", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "balanceOf", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "wantBalanceOf", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "expectedShareValue", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "decimals", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "bool", | ||||
|                         "name": "isDeprecated", | ||||
|                         "type": "bool" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "bool", | ||||
|                         "name": "emergencyShutdown", | ||||
|                         "type": "bool" | ||||
|                     } | ||||
|                 ], | ||||
|                 "internalType": "struct Helpers.VaultData[]", | ||||
|                 "name": "", | ||||
|                 "type": "tuple[]" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "owner", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "address[]", | ||||
|                 "name": "wantAddresses", | ||||
|                 "type": "address[]" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getPositionsForLatest", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "components": [ | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "vaultLatestVersion", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "vault", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "want", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "pricePerShare", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "availableDepositLimit", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "totalAssets", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "balanceOf", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "wantBalanceOf", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "expectedShareValue", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint256", | ||||
|                         "name": "decimals", | ||||
|                         "type": "uint256" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "bool", | ||||
|                         "name": "isDeprecated", | ||||
|                         "type": "bool" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "bool", | ||||
|                         "name": "emergencyShutdown", | ||||
|                         "type": "bool" | ||||
|                     } | ||||
|                 ], | ||||
|                 "internalType": "struct Helpers.VaultData[]", | ||||
|                 "name": "", | ||||
|                 "type": "tuple[]" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "contract YearnV2Interface", | ||||
|                 "name": "vault", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getPricePerShare", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "getRegistry", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "contract YearnRegistryInterface", | ||||
|                 "name": "", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "pure", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "contract YearnV2Interface", | ||||
|                 "name": "vault", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getTotalAssets", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "contract YearnV2Interface", | ||||
|                 "name": "vault", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "isEmergencyShutdown", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "bool", | ||||
|                 "name": "", | ||||
|                 "type": "bool" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "want", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "isWantSupported", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "bool", | ||||
|                 "name": "", | ||||
|                 "type": "bool" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "want", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "latestForWant", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "want", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "listVaultsForWant", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "address[]", | ||||
|                 "name": "vaultAddresses", | ||||
|                 "type": "address[]" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "name", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "", | ||||
|                 "type": "string" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "want", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "numVaultsForWant", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "numVaults", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     } | ||||
| ] | ||||
							
								
								
									
										20
									
								
								assets/icons/arbitrum.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								assets/icons/arbitrum.svg
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| <svg viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
|     <g clip-path="url(#clip0arb)"> | ||||
|         <path d="M10.5337 12.0149L12.2372 14.7045L13.8109 13.7871L11.5736 10.2397L10.5337 12.0149Z" fill="currentColor" /> | ||||
|         <path | ||||
|             d="M15.2441 11.9721L12.7995 8.14176L11.8925 9.68992L14.2525 13.5294L15.1057 13.032C15.1895 12.9636 15.2401 12.8632 15.2454 12.755L15.2441 11.9721Z" | ||||
|             fill="currentColor" /> | ||||
|         <path | ||||
|             d="M5 12.9604C5 13.2327 5.14504 13.4844 5.38065 13.621L6.20496 14.0988L10.2148 7.62987L9.53425 7.61181C8.9544 7.60359 8.32976 7.75522 8.0431 8.22599L5.76604 11.7763L5 12.9604Z" | ||||
|             fill="currentColor" /> | ||||
|         <path d="M12.5291 7.62917L10.7355 7.63572L6.67766 14.3718L8.09601 15.1933L12.5291 7.62917Z" fill="currentColor" /> | ||||
|         <path | ||||
|             d="M16 7.623C15.985 7.24569 15.7819 6.90026 15.4638 6.69913L11.0048 4.11963C10.6901 3.96024 10.297 3.96004 9.98178 4.11953C9.94451 4.13844 5.64557 6.6465 5.64557 6.6465C5.58608 6.67521 5.52878 6.70942 5.47486 6.74824C5.19089 6.95296 5.01778 7.27114 5 7.6207V12.9628L5.76604 11.7788L5.75937 7.6568C5.76027 7.64172 5.76212 7.62689 5.76481 7.61224C5.78213 7.51528 5.83596 7.42875 5.91701 7.37028C5.93723 7.35572 10.3096 4.80972 10.3235 4.80274C10.4263 4.75082 10.5569 4.7502 10.6598 4.80112L15.061 7.34782C15.1651 7.41455 15.2304 7.52766 15.2362 7.65129V12.7574C15.2309 12.8657 15.1883 12.966 15.1047 13.0344L10.6416 15.6363C10.5556 15.6675 10.4551 15.6657 10.3699 15.6309L8.48168 14.5384L8.09597 15.1965L9.79282 16.1793C9.84893 16.2114 9.8989 16.2398 9.93994 16.263C10.0035 16.2988 10.0468 16.3228 10.062 16.3303C10.1826 16.3892 10.3562 16.4235 10.5125 16.4235C10.6559 16.4235 10.7957 16.397 10.928 16.3449L15.5634 13.6444C15.8294 13.437 15.9859 13.1243 16 12.7855V7.623Z" | ||||
|             fill="currentColor" /> | ||||
|     </g> | ||||
|     <defs> | ||||
|         <clipPath id="clip0arb"> | ||||
|             <rect x="0.580627" width="20" height="20" rx="2" fill="currentColor" /> | ||||
|         </clipPath> | ||||
|     </defs> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										7
									
								
								assets/icons/yearn.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								assets/icons/yearn.svg
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| <svg viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path d="M11.375 11.375C11.375 10.4788 12.1038 9.75 13 9.75C13.8962 9.75 14.625 10.4788 14.625 11.375C14.625 12.2712 13.8962 13 13 13C12.1038 13 11.375 12.2712 11.375 11.375Z" fill="white"/> | ||||
| <path d="M7.3125 16.25H18.6875V6.5H7.3125V16.25ZM13 8.125C14.5096 8.125 15.7714 9.165 16.1346 10.5625H17.0625C17.511 10.5625 17.875 10.9265 17.875 11.375C17.875 11.8235 17.511 12.1875 17.0625 12.1875H16.1346C15.7714 13.585 14.5096 14.625 13 14.625C11.2076 14.625 9.75 13.1674 9.75 11.375C9.75 9.58262 11.2076 8.125 13 8.125Z" fill="white"/> | ||||
| <path d="M21.125 1.625H4.875C3.53112 1.625 2.4375 2.71862 2.4375 4.0625V18.6875C2.4375 20.0314 3.53112 21.125 4.875 21.125H21.125C22.4689 21.125 23.5625 20.0314 23.5625 18.6875V4.0625C23.5625 2.71862 22.4689 1.625 21.125 1.625ZM20.3125 17.0625C20.3125 17.511 19.9485 17.875 19.5 17.875H6.5C6.0515 17.875 5.6875 17.511 5.6875 17.0625V5.6875C5.6875 5.239 6.0515 4.875 6.5 4.875H19.5C19.9485 4.875 20.3125 5.239 20.3125 5.6875V17.0625Z" fill="white"/> | ||||
| <path d="M17.0625 22.75H21.125V23.5625C21.125 24.011 20.761 24.375 20.3125 24.375H17.875C17.4265 24.375 17.0625 24.011 17.0625 23.5625V22.75Z" fill="white"/> | ||||
| <path d="M4.875 22.75H8.9375V23.5625C8.9375 24.011 8.5735 24.375 8.125 24.375H5.6875C5.239 24.375 4.875 24.011 4.875 23.5625V22.75Z" fill="white"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										108
									
								
								components/protocols/yearn-v2/CardYearn.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								components/protocols/yearn-v2/CardYearn.vue
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,108 @@ | |||
| <template> | ||||
|   <div | ||||
|     class="flex-shrink-0 bg-white rounded-lg relative flex flex-col flex-1 px-6 pt-4 pb-6 dark:bg-dark-500" | ||||
|     style="box-shadow: -1px -3px 10px rgba(12, 25, 91, 0.03), 2px 4px 12px rgba(12, 25, 91, 0.05)" | ||||
|   > | ||||
|     <div class="flex items-center h-14"> | ||||
|       <div class="flex mr-4 -space-x-3 overflow-hidden"> | ||||
|         <div | ||||
|           v-if="tokenIcon" | ||||
|           class="inline-flex items-center justify-center dark:opacity-90 w-12 h-12" | ||||
|         > | ||||
|           <img class="w-full h-full object-cover" :src="tokenIcon" /> | ||||
|         </div> | ||||
|         <IconCurrency v-else :currency="tokenKey" class="w-12 h-12" no-height /> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="flex flex-col flex-grow"> | ||||
|         <div class="mb-1 font-medium leading-none whitespace-no-wrap text-19"> | ||||
|           {{ formatUsd(supplyUsd) }} | ||||
|         </div> | ||||
|         <div class="flex leading-none whitespace-no-wrap"> | ||||
|           <span class="text-grey-pure text-14" | ||||
|             >{{ formatDecimal(supply) }} {{ symbol }}</span | ||||
|           > | ||||
|           <Info | ||||
|             :text="`${formatUsd(priceInUsd, 2)}/${symbol}`" | ||||
|             icon="price" | ||||
|             class="ml-1" | ||||
|           /> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="ml-auto text-right"> | ||||
|         <p class="text-lg font-medium">{{ formatPercent(netAPY) }}</p> | ||||
|         <p class="text-sm font-medium text-[#9FB0C9]">net APY</p> | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <hr class="mt-4" /> | ||||
| 
 | ||||
|     <div class="flex items-center justify-around mt-6"> | ||||
|       <button | ||||
|         class="mr-4 h-10 w-full bg-primary-blue-dark shadow text-white rounded-[4px] hover:bg-primary-blue-hover" | ||||
|         @click="showSupply" | ||||
|       > | ||||
|         Supply | ||||
|       </button> | ||||
|       <button | ||||
|         class="h-10 w-full text-primary-blue-dark shadow border border-primary-blue-dark hover:border-primary-blue-hover rounded-[4px] hover:text-primary-blue-hover" | ||||
|         @click="showWithdraw" | ||||
|       > | ||||
|         Withdraw | ||||
|       </button> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import { computed, defineComponent, useContext } from "@nuxtjs/composition-api"; | ||||
| import { useFormatting } from "~/composables/useFormatting"; | ||||
| import { useToken } from "~/composables/useToken"; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   props: { | ||||
|     tokenKey: { type: String, required: true }, | ||||
|     tokenIcon: { type: String, required: false }, | ||||
|     vault: { type: String, default: null }, | ||||
|     supply: { type: String, required: true }, | ||||
|     supplyUsd: { type: String, required: true }, | ||||
|     priceInUsd: { type: String, default: "0" }, | ||||
|     netAPY: { type: String, default: "0" } | ||||
|   }, | ||||
| 
 | ||||
|   setup(props) { | ||||
|     const { app } = useContext(); | ||||
|     const { formatPercent, formatUsd, formatDecimal } = useFormatting(); | ||||
|     const { getTokenByKey } = useToken(); | ||||
| 
 | ||||
|     const symbol = computed( | ||||
|       () => getTokenByKey(props.tokenKey)?.symbol || props.tokenKey | ||||
|     ); | ||||
| 
 | ||||
|     function showSupply() { | ||||
|       app.router.push({ hash: `supply?vault=${props.vault}` }); | ||||
|     } | ||||
| 
 | ||||
|     function showWithdraw() { | ||||
|       app.router.push({ hash: `withdraw?vault=${props.vault}` }); | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       showSupply, | ||||
|       showWithdraw, | ||||
|       formatPercent, | ||||
|       formatUsd, | ||||
|       formatDecimal, | ||||
|       symbol | ||||
|     }; | ||||
|   } | ||||
| }); | ||||
| </script> | ||||
| <style scoped> | ||||
| .position-button { | ||||
|   @apply flex-1; | ||||
|   @apply h-8; | ||||
|   @apply h-8; | ||||
| } | ||||
| </style> | ||||
|  | @ -2,9 +2,9 @@ | |||
|   <SidebarContextContainer class="flex-1 h-full overflow-hidden"> | ||||
|     <SidebarContextHeader><slot name="title" /></SidebarContextHeader> | ||||
| 
 | ||||
|     <div class="overflow-y-scroll scrollbar-hover"> | ||||
|       <div class="mx-auto w-full"> | ||||
|         <div class="py-2 sm:py-4"> | ||||
|     <div class="overflow-y-scroll scrollbar-hover h-full"> | ||||
|       <div class="mx-auto w-full h-full"> | ||||
|         <div class="py-2 sm:py-4 h-full"> | ||||
|           <slot /> | ||||
|         </div> | ||||
|       </div> | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ | |||
| 
 | ||||
|       <SidebarSectionStatus | ||||
|         class="mt-8" | ||||
|         :liquidation="maxLiquidation" | ||||
|         :liquidation="liquidation" | ||||
|         :status="status" | ||||
|       /> | ||||
| 
 | ||||
|  | @ -212,6 +212,7 @@ export default defineComponent({ | |||
|       formatUsdMax, | ||||
|       formatUsd, | ||||
|       maxLiquidation, | ||||
|       liquidation, | ||||
|       liquidationPrice, | ||||
|       liquidationMaxPrice, | ||||
|       errorMessages, | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|     <template #title>Supply to Stability Pool</template> | ||||
| 
 | ||||
|     <div class="flex justify-around items-center w-full"> | ||||
|       <SidebarSectionValueWithIcon class="" label="Debt" center> | ||||
|       <SidebarSectionValueWithIcon class="" label="Stability Pool Balance" center> | ||||
|         <template #icon | ||||
|           ><IconCurrency :currency="poolToken.key" class="w-16 h-16" noHeight | ||||
|         /></template> | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|     <template #title>Withdraw from Stability Pool</template> | ||||
| 
 | ||||
|     <div class="flex justify-around items-center w-full"> | ||||
|       <SidebarSectionValueWithIcon class="" label="Debt" center> | ||||
|       <SidebarSectionValueWithIcon class="" label="Stability Pool Balance" center> | ||||
|         <template #icon | ||||
|           ><IconCurrency :currency="poolToken.key" class="w-16 h-16" noHeight | ||||
|         /></template> | ||||
|  |  | |||
							
								
								
									
										183
									
								
								components/sidebar/context/yearn-v2/SidebarYearnV2Supply.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								components/sidebar/context/yearn-v2/SidebarYearnV2Supply.vue
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,183 @@ | |||
| <template> | ||||
|   <SidebarContextRootContainer> | ||||
|     <template #title>Supply {{ symbol }}</template> | ||||
| 
 | ||||
|     <SidebarSectionValueWithIcon label="Token Balance" center> | ||||
|       <template #icon | ||||
|         ><IconCurrency :currency="token.key" class="w-20 h-20" noHeight | ||||
|       /></template> | ||||
|       <template #value>{{ formatNumber(balance) }} {{ symbol }}</template> | ||||
|     </SidebarSectionValueWithIcon> | ||||
| 
 | ||||
|     <div class="bg-[#C5CCE1] bg-opacity-[0.15] mt-10 p-8 h-full"> | ||||
|       <h3 class="text-primary-gray text-xs font-semibold mb-2.5"> | ||||
|         Amount to supply | ||||
|       </h3> | ||||
| 
 | ||||
|       <input-numeric | ||||
|         v-model="amount" | ||||
|         placeholder="Amount to supply" | ||||
|         :error="errors.amount.message" | ||||
|       > | ||||
|         <template v-if="!isMaxAmount" #suffix> | ||||
|           <div class="absolute mt-2 top-0 right-0 mr-4"> | ||||
|             <button | ||||
|               type="button" | ||||
|               class="text-primary-blue-dark font-semibold text-sm hover:text-primary-blue-hover" | ||||
|               @click="toggle" | ||||
|             > | ||||
|               Max | ||||
|             </button> | ||||
|           </div> | ||||
|         </template> | ||||
|       </input-numeric> | ||||
| 
 | ||||
|       <div class="flex flex-shrink-0 mt-10"> | ||||
|         <ButtonCTA | ||||
|           class="w-full" | ||||
|           :disabled="!isValid || pending" | ||||
|           :loading="pending" | ||||
|           @click="cast" | ||||
|         > | ||||
|           Supply | ||||
|         </ButtonCTA> | ||||
|       </div> | ||||
| 
 | ||||
|       <ValidationErrors :error-messages="errorMessages" class="mt-6" /> | ||||
|     </div> | ||||
|   </SidebarContextRootContainer> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, ref } from "@nuxtjs/composition-api"; | ||||
| import InputNumeric from "~/components/common/input/InputNumeric.vue"; | ||||
| import { useBalances } from "~/composables/useBalances"; | ||||
| import { useNotification } from "~/composables/useNotification"; | ||||
| import { useBigNumber } from "~/composables/useBigNumber"; | ||||
| import { useFormatting } from "~/composables/useFormatting"; | ||||
| import { useValidators } from "~/composables/useValidators"; | ||||
| import { useValidation } from "~/composables/useValidation"; | ||||
| import { useToken } from "~/composables/useToken"; | ||||
| import { useParsing } from "~/composables/useParsing"; | ||||
| import { useMaxAmountActive } from "~/composables/useMaxAmountActive"; | ||||
| import { useWeb3 } from "@instadapp/vue-web3"; | ||||
| import ToggleButton from "~/components/common/input/ToggleButton.vue"; | ||||
| import { useDSA } from "~/composables/useDSA"; | ||||
| import ButtonCTA from "~/components/common/input/ButtonCTA.vue"; | ||||
| import Button from "~/components/Button.vue"; | ||||
| import { useSidebar } from "~/composables/useSidebar"; | ||||
| import DSA from "dsa-connect"; | ||||
| import { useYearnV2Position } from "~/composables/protocols/useYearnV2Position"; | ||||
| export default defineComponent({ | ||||
|   components: { InputNumeric, ToggleButton, ButtonCTA, Button }, | ||||
|   props: { | ||||
|     vault: { type: String, required: true } | ||||
|   }, | ||||
|   setup(props) { | ||||
|     const { close } = useSidebar(); | ||||
|     const { account } = useWeb3(); | ||||
|     const { dsa } = useDSA(); | ||||
|     const { getTokenByKey, valInt } = useToken(); | ||||
|     const { getBalanceByKey, fetchBalances } = useBalances(); | ||||
|     const { formatNumber, formatUsdMax, formatUsd } = useFormatting(); | ||||
|     const { isZero, gt, plus } = useBigNumber(); | ||||
|     const { parseSafeFloat } = useParsing(); | ||||
|     const { | ||||
|       showPendingTransaction, | ||||
|       showWarning, | ||||
|       showConfirmedTransaction | ||||
|     } = useNotification(); | ||||
| 
 | ||||
|     const { vaults, refreshPosition } = useYearnV2Position(); | ||||
|     const selectedVault = computed(() => | ||||
|       vaults.value.find(v => v.address === props.vault) | ||||
|     ); | ||||
| 
 | ||||
|     const amount = ref(""); | ||||
|     const amountParsed = computed(() => parseSafeFloat(amount.value)); | ||||
| 
 | ||||
|     const token = computed(() => | ||||
|       selectedVault.value | ||||
|         ? getTokenByKey(selectedVault.value.token.display_name.toLowerCase()) | ||||
|         : null | ||||
|     ); | ||||
|     const symbol = computed(() => token.value?.symbol); | ||||
|     const decimals = computed(() => token.value?.decimals); | ||||
|     const balance = computed(() => getBalanceByKey(token.value?.key)); | ||||
| 
 | ||||
|     const { toggle, isMaxAmount } = useMaxAmountActive(amount, balance); | ||||
| 
 | ||||
|     const { validateAmount, validateIsLoggedIn } = useValidators(); | ||||
|     const errors = computed(() => { | ||||
|       const hasAmountValue = !isZero(amount.value); | ||||
| 
 | ||||
|       return { | ||||
|         amount: { | ||||
|           message: validateAmount(amountParsed.value, balance.value), | ||||
|           show: hasAmountValue | ||||
|         }, | ||||
|         auth: { message: validateIsLoggedIn(!!account.value), show: true } | ||||
|       }; | ||||
|     }); | ||||
|     const { errorMessages, isValid } = useValidation(errors); | ||||
| 
 | ||||
|     const pending = ref(false); | ||||
| 
 | ||||
|     async function cast() { | ||||
|       pending.value = true; | ||||
| 
 | ||||
|       const amount = isMaxAmount.value | ||||
|         ? dsa.value.maxValue | ||||
|         : valInt(amountParsed.value, decimals.value); | ||||
| 
 | ||||
|       const spells = dsa.value.Spell(); | ||||
| 
 | ||||
|       spells.add({ | ||||
|         //@ts-ignore | ||||
|         connector: "YEARN-VAULT-A", | ||||
|         method: "deposit", | ||||
|         args: [props.vault, amount, 0, 0] | ||||
|       }); | ||||
| 
 | ||||
|       try { | ||||
|         const txHash = await (dsa.value as DSA).cast({ | ||||
|           spells, | ||||
|           from: account.value, | ||||
|           onReceipt: async receipt => { | ||||
|             showConfirmedTransaction(receipt.transactionHash); | ||||
| 
 | ||||
|             await fetchBalances(true); | ||||
|             await refreshPosition(); | ||||
|           } | ||||
|         }); | ||||
| 
 | ||||
|         showPendingTransaction(txHash); | ||||
|       } catch (error) { | ||||
|         showWarning(error.message); | ||||
|       } | ||||
| 
 | ||||
|       pending.value = false; | ||||
| 
 | ||||
|       close(); | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       selectedVault, | ||||
|       pending, | ||||
|       cast, | ||||
|       errors, | ||||
|       amount, | ||||
|       token, | ||||
|       symbol, | ||||
|       balance, | ||||
|       formatNumber, | ||||
|       formatUsdMax, | ||||
|       formatUsd, | ||||
|       toggle, | ||||
|       isMaxAmount, | ||||
|       errorMessages, | ||||
|       isValid | ||||
|     }; | ||||
|   } | ||||
| }); | ||||
| </script> | ||||
							
								
								
									
										179
									
								
								components/sidebar/context/yearn-v2/SidebarYearnV2Withdraw.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								components/sidebar/context/yearn-v2/SidebarYearnV2Withdraw.vue
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,179 @@ | |||
| <template> | ||||
|   <SidebarContextRootContainer> | ||||
|     <template #title>Withdraw {{ symbol }}</template> | ||||
| 
 | ||||
|     <SidebarSectionValueWithIcon label="Token Balance" center> | ||||
|       <template #icon | ||||
|         ><IconCurrency :currency="token.key" class="w-20 h-20" noHeight | ||||
|       /></template> | ||||
|       <template #value>{{ formatNumber(balance) }} {{ symbol }}</template> | ||||
|     </SidebarSectionValueWithIcon> | ||||
| 
 | ||||
|     <div class="bg-[#C5CCE1] bg-opacity-[0.15] mt-10 p-8  h-full"> | ||||
|       <h3 class="text-primary-gray text-xs font-semibold mb-2.5"> | ||||
|         Amount to withdraw | ||||
|       </h3> | ||||
| 
 | ||||
|       <input-numeric | ||||
|         v-model="amount" | ||||
|         placeholder="Amount to withdraw" | ||||
|         :error="errors.amount.message" | ||||
|       > | ||||
|         <template v-if="!isMaxAmount" #suffix> | ||||
|           <div class="absolute mt-2 top-0 right-0 mr-4"> | ||||
|             <button | ||||
|               type="button" | ||||
|               class="text-primary-blue-dark font-semibold text-sm hover:text-primary-blue-hover" | ||||
|               @click="toggle" | ||||
|             > | ||||
|               Max | ||||
|             </button> | ||||
|           </div> | ||||
|         </template> | ||||
|       </input-numeric> | ||||
| 
 | ||||
|       <div class="flex flex-shrink-0 mt-10"> | ||||
|         <ButtonCTA | ||||
|           class="w-full" | ||||
|           :disabled="!isValid || pending" | ||||
|           :loading="pending" | ||||
|           @click="cast" | ||||
|         > | ||||
|           Withdraw | ||||
|         </ButtonCTA> | ||||
|       </div> | ||||
| 
 | ||||
|       <ValidationErrors :error-messages="errorMessages" class="mt-6" /> | ||||
|     </div> | ||||
|   </SidebarContextRootContainer> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import { computed, defineComponent, onMounted, ref } from '@nuxtjs/composition-api' | ||||
| import InputNumeric from '~/components/common/input/InputNumeric.vue' | ||||
| import { useBalances } from '~/composables/useBalances' | ||||
| import { useBigNumber } from '~/composables/useBigNumber' | ||||
| import { useFormatting } from '~/composables/useFormatting' | ||||
| import { useValidators } from '~/composables/useValidators' | ||||
| import { useValidation } from '~/composables/useValidation' | ||||
| import { useToken } from '~/composables/useToken' | ||||
| import { useParsing } from '~/composables/useParsing' | ||||
| import { useMaxAmountActive } from '~/composables/useMaxAmountActive' | ||||
| import { useWeb3 } from '@instadapp/vue-web3' | ||||
| import ToggleButton from '~/components/common/input/ToggleButton.vue' | ||||
| import { useDSA } from '~/composables/useDSA' | ||||
| import ButtonCTA from '~/components/common/input/ButtonCTA.vue' | ||||
| import { useNotification } from '~/composables/useNotification' | ||||
| import Button from '~/components/Button.vue' | ||||
| import { useSidebar } from '~/composables/useSidebar' | ||||
| import { useYearnV2Position } from '~/composables/protocols/useYearnV2Position' | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   components: { InputNumeric, ToggleButton, ButtonCTA, Button }, | ||||
|   props: { | ||||
|     vault: { type: String, required: true } | ||||
|   }, | ||||
|   setup(props) { | ||||
|     const { close } = useSidebar() | ||||
|     const { account } = useWeb3() | ||||
|     const { dsa } = useDSA() | ||||
|     const { getTokenByKey, valInt } = useToken() | ||||
|     const { formatNumber, formatUsdMax, formatUsd } = useFormatting() | ||||
|     const { isZero, gt, plus, max, minus } = useBigNumber() | ||||
|     const { parseSafeFloat } = useParsing() | ||||
|     const { showPendingTransaction, showConfirmedTransaction, showWarning } = useNotification() | ||||
|     const { fetchBalances } = useBalances(); | ||||
| 
 | ||||
|     const { vaults, refreshPosition } = useYearnV2Position(); | ||||
|     const selectedVault = computed(() => | ||||
|       vaults.value.find(v => v.address === props.vault) | ||||
|     ); | ||||
| 
 | ||||
|     const balance = computed( | ||||
|       () => selectedVault.value ? selectedVault.value.position.supply : '0' | ||||
|     ) | ||||
| 
 | ||||
|     const amount = ref('') | ||||
|     const amountParsed = computed(() => parseSafeFloat(amount.value)) | ||||
| 
 | ||||
| 
 | ||||
|     const token = computed(() => | ||||
|       selectedVault.value | ||||
|         ? getTokenByKey(selectedVault.value.token.display_name.toLowerCase()) | ||||
|         : null | ||||
|     ); | ||||
|     const symbol = computed(() => token.value?.symbol) | ||||
|     const decimals = computed(() => token.value?.decimals) | ||||
| 
 | ||||
| 
 | ||||
|     const { toggle, isMaxAmount } = useMaxAmountActive(amount, balance) | ||||
| 
 | ||||
|     const { validateAmount, validateIsLoggedIn } = useValidators() | ||||
| 
 | ||||
|     const errors = computed(() => { | ||||
|       const hasAmountValue = !isZero(amount.value) | ||||
| 
 | ||||
|       return { | ||||
|         amount: { message: validateAmount(amountParsed.value, balance.value), show: hasAmountValue }, | ||||
|         auth: { message: validateIsLoggedIn(!!account.value), show: true }, | ||||
|       } | ||||
|     }) | ||||
|     const { errorMessages, isValid } = useValidation(errors) | ||||
| 
 | ||||
|     const pending = ref(false) | ||||
| 
 | ||||
|     async function cast() { | ||||
|       pending.value = true | ||||
| 
 | ||||
|       const amount = isMaxAmount.value ? dsa.value.maxValue : valInt(amountParsed.value, decimals.value) | ||||
| 
 | ||||
|       const spells = dsa.value.Spell() | ||||
| 
 | ||||
|       spells.add({ | ||||
|         //@ts-ignore | ||||
|         connector: "YEARN-VAULT-A", | ||||
|         method: 'withdraw', | ||||
|         args: [props.vault, amount, 0, 0], | ||||
|       }) | ||||
| 
 | ||||
|       try { | ||||
|         const txHash = await dsa.value.cast({ | ||||
|           spells, | ||||
|           from: account.value, | ||||
|           onReceipt: async receipt => { | ||||
|             showConfirmedTransaction(receipt.transactionHash); | ||||
| 
 | ||||
|             await fetchBalances(true); | ||||
|             await refreshPosition(); | ||||
|           } | ||||
|         }) | ||||
| 
 | ||||
|         showPendingTransaction(txHash) | ||||
|       } catch (error) { | ||||
|         showWarning(error.message) | ||||
|       } | ||||
| 
 | ||||
|       pending.value = false | ||||
| 
 | ||||
|       close() | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       pending, | ||||
|       cast, | ||||
|       errors, | ||||
|       amount, | ||||
|       token, | ||||
|       symbol, | ||||
|       balance, | ||||
|       formatNumber, | ||||
|       formatUsdMax, | ||||
|       formatUsd, | ||||
|       toggle, | ||||
|       isMaxAmount, | ||||
|       errorMessages, | ||||
|       isValid | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
| </script> | ||||
|  | @ -347,7 +347,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import { computed, defineComponent, reactive, ref, watch } from '@nuxtjs/composition-api' | ||||
| import { computed, defineComponent, onMounted, reactive, ref, watch } from '@nuxtjs/composition-api' | ||||
| import { useNetwork } from '~/composables/useNetwork' | ||||
| import tokens from '~/constant/tokens' | ||||
| import Button from '../Button.vue' | ||||
|  | @ -404,6 +404,10 @@ export default defineComponent({ | |||
|       decimals: 18, | ||||
|     }) | ||||
| 
 | ||||
|     onMounted(() => { | ||||
|       selectToken1(allTokens.value[1]) | ||||
|     }) | ||||
| 
 | ||||
|     const slippagePerc = computed(() => { | ||||
| 
 | ||||
|       const sellAmountUsd = toBN(token0.amountUSD); | ||||
|  |  | |||
							
								
								
									
										138
									
								
								composables/protocols/useYearnV2Position.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								composables/protocols/useYearnV2Position.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,138 @@ | |||
| import { useWeb3 } from "@instadapp/vue-web3"; | ||||
| import { ref, useContext, watch } from "@nuxtjs/composition-api"; | ||||
| import addresses from "~/constant/addresses"; | ||||
| import tokens from "~/constant/tokens"; | ||||
| import { useDSA } from "../useDSA"; | ||||
| import yearnV2ABI from "~/abis/read/yearnV2.json"; | ||||
| import useEventBus from "../useEventBus"; | ||||
| import BigNumber from "bignumber.js"; | ||||
| import { useBigNumber } from "../useBigNumber"; | ||||
| 
 | ||||
| const resolver = addresses.mainnet.resolver.yearnV2; | ||||
| 
 | ||||
| const allTokens = tokens.mainnet.allTokens.map(token => token.address); | ||||
| 
 | ||||
| const wantAddresses = allTokens; | ||||
| 
 | ||||
| const vaults = ref([]); | ||||
| 
 | ||||
| export function useYearnV2Position() { | ||||
|   const { $axios } = useContext(); | ||||
|   const { times } = useBigNumber(); | ||||
|   const { library } = useWeb3(); | ||||
|   const { activeAccount } = useDSA(); | ||||
|   const { onEvent } = useEventBus(); | ||||
| 
 | ||||
|   const fetchPosition = async () => { | ||||
|     const availableVaults = await $axios | ||||
|       .$get("https://api.yearn.finance/v1/chains/1/vaults/all") | ||||
|       .then(vs => vs.filter(v => v.type === "v2")); | ||||
| 
 | ||||
|     if (!library.value) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     if (!activeAccount.value) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const resolverInstance = new library.value.eth.Contract( | ||||
|       yearnV2ABI as any, | ||||
|       resolver | ||||
|     ); | ||||
| 
 | ||||
|     // const tokensArr = wantAddresses;
 | ||||
|      | ||||
|     // allow user to add custom tokens
 | ||||
|     const tokensArr = [ | ||||
|       ...new Set( | ||||
|         availableVaults.filter(v => v.type === "v2").map(v => v.token.address) | ||||
|         .filter(a => allTokens.includes(a)) | ||||
|       ) | ||||
|     ]; | ||||
|      | ||||
| 
 | ||||
|     const rawData = await resolverInstance.methods | ||||
|       .getPositionsForLatest(activeAccount.value.address, tokensArr) | ||||
|       .call(); | ||||
| 
 | ||||
|     const newVaults = []; | ||||
| 
 | ||||
|     rawData.forEach( | ||||
|       ([ | ||||
|         vaultLatestVersion, | ||||
|         vault, | ||||
|         want, | ||||
|         pricePerShare, | ||||
|         availableDepositLimit, | ||||
|         totalAssets, | ||||
|         balanceOf, | ||||
|         wantBalanceOf, | ||||
|         expectedShareValue, | ||||
|         decimals, | ||||
|         isDeprecated, | ||||
|         emergencyShutdown | ||||
|       ]) => { | ||||
|         const v = availableVaults.find(v => v.address === vault); | ||||
|         if (v) { | ||||
|           const supply = new BigNumber(balanceOf) | ||||
|             .dividedBy(10 ** decimals) | ||||
|             .toFixed(); | ||||
| 
 | ||||
|           newVaults.push({ | ||||
|             ...v, | ||||
|             priceInUsd: v.tvl.price.toString(), | ||||
|             position: { | ||||
|               vaultLatestVersion, | ||||
|               vault, | ||||
|               want, | ||||
|               pricePerShare, | ||||
|               availableDepositLimit, | ||||
|               totalAssets, | ||||
|               balanceOf, | ||||
|               wantBalanceOf, | ||||
|               expectedShareValue, | ||||
|               decimals, | ||||
|               isDeprecated, | ||||
|               emergencyShutdown, | ||||
|               supply, | ||||
|               supplyUsd: times(supply, v.tvl.price).toFixed() | ||||
|             } | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|     ); | ||||
|     vaults.value = newVaults; | ||||
|   }; | ||||
| 
 | ||||
|   const refreshPosition = async () => { | ||||
|     await fetchPosition(); | ||||
|   }; | ||||
| 
 | ||||
|   onEvent("protocol::compound::refresh", refreshPosition); | ||||
| 
 | ||||
|   watch( | ||||
|     library, | ||||
|     async val => { | ||||
|       if (val) { | ||||
|         refreshPosition(); | ||||
|       } | ||||
|     }, | ||||
|     { immediate: true } | ||||
|   ); | ||||
| 
 | ||||
|   watch( | ||||
|     activeAccount, | ||||
|     async val => { | ||||
|       if (val) { | ||||
|         refreshPosition(); | ||||
|       } | ||||
|     }, | ||||
|     { immediate: true } | ||||
|   ); | ||||
| 
 | ||||
|   return { | ||||
|     vaults, | ||||
|     refreshPosition | ||||
|   }; | ||||
| } | ||||
|  | @ -22,24 +22,27 @@ import { useSorting } from "./useSorting"; | |||
| const balances = reactive({ | ||||
|   user: { | ||||
|     mainnet: {}, | ||||
|     polygon: {} | ||||
|     polygon: {}, | ||||
|     arbitrum: {} | ||||
|   }, | ||||
|   dsa: { | ||||
|     mainnet: {}, | ||||
|     polygon: {} | ||||
|     polygon: {}, | ||||
|     arbitrum: {} | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| const prices = reactive({ | ||||
|   mainnet: {}, | ||||
|   polygon: {} | ||||
|   polygon: {}, | ||||
|   arbitrum: {} | ||||
| }); | ||||
| 
 | ||||
| export function useBalances() { | ||||
|   const { $axios } = useContext(); | ||||
|   const { times, plus, ensureValue } = useBigNumber(); | ||||
|   const { account, library } = useWeb3(); | ||||
|   const { activeNetworkId } = useNetwork() | ||||
|   const { activeNetworkId } = useNetwork(); | ||||
|   const { activeAccount } = useDSA(); | ||||
|   const { getTokenByKey } = useToken(); | ||||
|   const { by } = useSorting(); | ||||
|  | @ -49,6 +52,9 @@ export function useBalances() { | |||
|     prices.polygon = await $axios.$get( | ||||
|       "https://api.instadapp.io/defi/polygon/prices" | ||||
|     ); | ||||
|     prices.arbitrum = await $axios.$get( | ||||
|       "https://api.instadapp.io/defi/arbitrum/prices" | ||||
|     ); | ||||
|   }); | ||||
|   const fetchBalances = async (refresh = false) => { | ||||
|     if (!balances.user || refresh) { | ||||
|  | @ -61,6 +67,10 @@ export function useBalances() { | |||
|         polygon: | ||||
|           activeNetworkId.value === Network.Polygon | ||||
|             ? await getBalances(account.value, Network.Polygon, library.value) | ||||
|             : {}, | ||||
|         arbitrum: | ||||
|           activeNetworkId.value === Network.Arbitrum | ||||
|             ? await getBalances(account.value, Network.Arbitrum, library.value) | ||||
|             : {} | ||||
|       }; | ||||
|     } | ||||
|  | @ -84,6 +94,14 @@ export function useBalances() { | |||
|                 Network.Polygon, | ||||
|                 library.value | ||||
|               ) | ||||
|             : {}, | ||||
|         arbitrum: | ||||
|           activeNetworkId.value === Network.Arbitrum | ||||
|             ? await getBalances( | ||||
|                 activeAccount.value.address, | ||||
|                 Network.Arbitrum, | ||||
|                 library.value | ||||
|               ) | ||||
|             : {} | ||||
|       }; | ||||
|     } | ||||
|  | @ -95,7 +113,8 @@ export function useBalances() { | |||
| 
 | ||||
|   const getBalanceByAddress = (address, network = null, type = "dsa") => { | ||||
|     return ( | ||||
|       balances[type]?.[network || activeNetworkId.value][address]?.balance || "0" | ||||
|       balances[type]?.[network || activeNetworkId.value][address]?.balance || | ||||
|       "0" | ||||
|     ); | ||||
|   }; | ||||
| 
 | ||||
|  | @ -126,7 +145,11 @@ export function useBalances() { | |||
|     return tokens[activeNetworkId.value].allTokens | ||||
|       .map(token => ({ | ||||
|         ...token, | ||||
|         balance: getBalanceByAddress(token.address, activeNetworkId.value, type), | ||||
|         balance: getBalanceByAddress( | ||||
|           token.address, | ||||
|           activeNetworkId.value, | ||||
|           type | ||||
|         ), | ||||
|         netWorth: netWorth(token.address, type) | ||||
|       })) | ||||
|       .sort(by("-netWorth")); | ||||
|  |  | |||
|  | @ -8,6 +8,9 @@ export function useLink() { | |||
|     if (activeNetworkId.value === "polygon") { | ||||
|       return "https://polygonscan.com/address"; | ||||
|     } | ||||
|     if (activeNetworkId.value === "arbitrum") { | ||||
|       return "https://arbiscan.io/address"; | ||||
|     } | ||||
| 
 | ||||
|     return "https://etherscan.io/address"; | ||||
|   }); | ||||
|  | @ -21,5 +24,7 @@ export const getMaticLink = transactionHash => | |||
|   `https://polygonscan.com/tx/${transactionHash}`; | ||||
| export const getPolygonLink = transactionHash => | ||||
|   `https://polygonscan.com/tx/${transactionHash}`; | ||||
| export const getArbitrumLink = transactionHash => | ||||
|   `https://arbiscan.io/tx/${transactionHash}`; | ||||
| export const getTenderlyLink = simulationId => | ||||
|   `https://dashboard.tenderly.co/public/InstaDApp/dsa-simulations/fork-simulation/${simulationId}?hideSidebar=true`; | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ import { computed, watchEffect, ref, watch } from "@nuxtjs/composition-api"; | |||
| 
 | ||||
| import MainnetSVG from "~/assets/icons/mainnet.svg?inline"; | ||||
| import PolygonSVG from "~/assets/icons/polygon.svg?inline"; | ||||
| import ArbitrumSVG from "~/assets/icons/arbitrum.svg?inline"; | ||||
| 
 | ||||
| import { useModal } from "./useModal"; | ||||
| import { useNotification } from "./useNotification"; | ||||
| import { useWeb3 } from "@instadapp/vue-web3"; | ||||
|  | @ -9,12 +11,14 @@ import { useCookies } from "./useCookies"; | |||
| 
 | ||||
| export enum Network { | ||||
|   Mainnet = "mainnet", | ||||
|   Polygon = "polygon" | ||||
|   Polygon = "polygon", | ||||
|   Arbitrum = "arbitrum" | ||||
| } | ||||
| 
 | ||||
| export const networks = [ | ||||
|   { id: "mainnet", chainId: 1, name: "Mainnet", icon: MainnetSVG }, | ||||
|   { id: "polygon", chainId: 137, name: "Polygon", icon: PolygonSVG } | ||||
|   { id: "polygon", chainId: 137, name: "Polygon", icon: PolygonSVG }, | ||||
|   { id: "arbitrum", chainId: 42161, name: "Arbitrum", icon: ArbitrumSVG } | ||||
| ]; | ||||
| 
 | ||||
| export const activeNetworkId = ref<Network>(); | ||||
|  | @ -93,10 +97,50 @@ export function useNetwork() { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async function switchToArbitrum() { | ||||
|     if (window.ethereum) { | ||||
|       const chainId = "0xa4b1"; | ||||
| 
 | ||||
|       try { | ||||
|         await window.ethereum.request({ | ||||
|           method: "wallet_switchEthereumChain", | ||||
|           params: [{ chainId }] | ||||
|         }); | ||||
|       } catch (switchError) { | ||||
|         // 4902 error code indicates that the chain has not been added to MetaMask.
 | ||||
|         if (switchError.code === 4902) { | ||||
|           try { | ||||
|             const chainData = { | ||||
|               chainId, | ||||
|               chainName: 'Arbitrum One', | ||||
|               nativeCurrency: { | ||||
|                 name: 'Ethereum', | ||||
|                 symbol: 'ETH', | ||||
|                 decimals: 18, | ||||
|               }, | ||||
|               rpcUrls: ['https://arb1.arbitrum.io/rpc'], | ||||
|               blockExplorerUrls: ['https://arbiscan.io'], | ||||
|             }; | ||||
|             await window.ethereum.request({ | ||||
|               method: "wallet_addEthereumChain", | ||||
|               params: [chainData, account.value] | ||||
|             }); | ||||
|           } catch (addError) { | ||||
|             return Promise.reject(addError); | ||||
|           } | ||||
|         } else { | ||||
|           return Promise.reject(switchError); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async function switchNetwork() { | ||||
|     try { | ||||
|       if (activeNetworkId.value === "mainnet") { | ||||
|         await switchToMainnet(); | ||||
|       } else if (activeNetworkId.value === "arbitrum") { | ||||
|         await switchToArbitrum(); | ||||
|       } else { | ||||
|         await switchToPolygon(); | ||||
|       } | ||||
|  |  | |||
|  | @ -1,6 +1,11 @@ | |||
| import { ref } from "@nuxtjs/composition-api"; | ||||
| import { useFormatting } from "@/composables/useFormatting"; | ||||
| import { getEtherscanLink, getMaticLink, getTenderlyLink } from "./useLink"; | ||||
| import { | ||||
|   getArbitrumLink, | ||||
|   getEtherscanLink, | ||||
|   getMaticLink, | ||||
|   getTenderlyLink | ||||
| } from "./useLink"; | ||||
| import { useRandom } from "./useRandom"; | ||||
| import { Network, activeNetworkId } from "./useNetwork"; | ||||
| const { makeid } = useRandom(); | ||||
|  | @ -92,6 +97,8 @@ export function useNotification() { | |||
|     let href; | ||||
|     if (network === Network.Polygon) { | ||||
|       href = getMaticLink(transactionHash); | ||||
|     }else if (network === Network.Arbitrum) { | ||||
|       href = getArbitrumLink(transactionHash); | ||||
|     } else { | ||||
|       href = getEtherscanLink(transactionHash); | ||||
|     } | ||||
|  | @ -113,6 +120,8 @@ export function useNotification() { | |||
|     let href; | ||||
|     if (network === Network.Polygon) { | ||||
|       href = getMaticLink(transactionHash); | ||||
|     } else if (network === Network.Arbitrum) { | ||||
|       href = getArbitrumLink(transactionHash); | ||||
|     } else { | ||||
|       href = getEtherscanLink(transactionHash); | ||||
|     } | ||||
|  |  | |||
|  | @ -46,6 +46,9 @@ import SidebarReflexerWithdraw from '~/components/sidebar/context/reflexer/Sideb | |||
| import SidebarReflexerBorrow from '~/components/sidebar/context/reflexer/SidebarReflexerBorrow.vue' | ||||
| import SidebarReflexerPayback from '~/components/sidebar/context/reflexer/SidebarReflexerPayback.vue' | ||||
| 
 | ||||
| import SidebarYearnV2Supply from "~/components/sidebar/context/yearn-v2/SidebarYearnV2Supply.vue"; | ||||
| import SidebarYearnV2Withdraw from '~/components/sidebar/context/yearn-v2/SidebarYearnV2Withdraw.vue' | ||||
| 
 | ||||
| import SidebarStrategySelection from '~/components/sidebar/context/strategy/SidebarStrategySelection.vue' | ||||
| import SidebarStrategy from '~/components/sidebar/context/strategy/SidebarStrategy.vue' | ||||
| 
 | ||||
|  | @ -92,6 +95,11 @@ const sidebars = { | |||
|   "/mainnet/reflexer#withdraw": { component: SidebarReflexerWithdraw }, | ||||
|   "/mainnet/reflexer#borrow": { component: SidebarReflexerBorrow }, | ||||
|   "/mainnet/reflexer#payback": { component: SidebarReflexerPayback }, | ||||
| 
 | ||||
| 
 | ||||
|   "/mainnet/yearn-v2": { component: null }, | ||||
|   "/mainnet/yearn-v2#supply": { component: SidebarYearnV2Supply }, | ||||
|   "/mainnet/yearn-v2#withdraw": { component: SidebarYearnV2Withdraw }, | ||||
| }; | ||||
| 
 | ||||
| const sidebar = ref(null); | ||||
|  |  | |||
|  | @ -9,9 +9,10 @@ const forkId = ref(null); | |||
| export function useTenderly() { | ||||
|   const { $config } = useContext(); | ||||
|   const { activate, deactivate, connector, library } = useWeb3(); | ||||
|   const { activeNetworkId } = useNetwork(); | ||||
|   const { accounts, refreshAccounts } = useDSA(); | ||||
|   const canSimulate = computed( | ||||
|     () => $config.TENDERLY_FORK_PATH && $config.TENDERLY_KEY | ||||
|     () => activeNetworkId.value !== "arbitrum" && $config.TENDERLY_FORK_PATH && $config.TENDERLY_KEY | ||||
|   ); | ||||
|   const loading = ref(false); | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,15 +14,16 @@ import { SafeAppConnector } from "@gnosis.pm/safe-apps-web3-react/dist/connector | |||
| setWeb3LibraryCallback(provider => new Web3(provider)); | ||||
| 
 | ||||
| export const injected = new InjectedConnector({ | ||||
|   supportedChainIds: [1, 137] | ||||
|   supportedChainIds: [1, 137, 42161] | ||||
| }); | ||||
| 
 | ||||
| export const walletconnect = new WalletConnectConnector({ | ||||
|   rpc: { | ||||
|     1: `https://mainnet.infura.io/v3/${process.env.INFURA_ID}`, | ||||
|     137: "https://rpc-mainnet.maticvigil.com" | ||||
|     137: "https://rpc-mainnet.maticvigil.com", | ||||
|     42161: "https://arb1.arbitrum.io/rpc" | ||||
|   }, | ||||
|   supportedChainIds: [1, 137] | ||||
|   supportedChainIds: [1, 137, 42161] | ||||
| }); | ||||
| 
 | ||||
| // mainnet only
 | ||||
|  | @ -41,7 +42,7 @@ let gnosisSafe = null; | |||
| 
 | ||||
| if (process.client) { | ||||
|   gnosisSafe = new SafeAppConnector({ | ||||
|     supportedChainIds: [1, 137] | ||||
|     supportedChainIds: [1, 137, 42161] | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,7 +12,8 @@ const addresses = { | |||
|       unipool: "0x22bddA39D14eD0aafeee36B6e784602fdDE64723", | ||||
|       liquity: "0xDAf2A39503463B0F41f899EDD82213b3c96b6Cf8", | ||||
|       reflexer: "0x016ca8d0993d1a7073b01802a2e22fd0df7e633a", | ||||
|       bprotocol: "0x3843019c19259117ed473947007bcafc5c0c7129" | ||||
|       bprotocol: "0x3843019c19259117ed473947007bcafc5c0c7129", | ||||
|       yearnV2: "0x3f6DCA8a0b7d04737BC3B2aEAbeB1C09431581f0" | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|  | @ -30,7 +31,21 @@ const addresses = { | |||
|       }, | ||||
|       weth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" | ||||
|     } | ||||
|   } | ||||
|   }, | ||||
|   arbitrum: { | ||||
|     core: { | ||||
|       instaIndex: '0x1eE00C305C51Ff3bE60162456A9B533C07cD9288', | ||||
|       instaConnectorsV2: '0x67fCE99Dd6d8d659eea2a1ac1b8881c57eb6592B' | ||||
|     }, | ||||
|     resolver: { | ||||
|       accounts: '0xdF19Da523DA64bBE82eE0E4DFf00d676A8386474', | ||||
|       balance: '0x29572b16D306acd7ca0CBCA0F08C3EFF131fFDA5', | ||||
|       uniswap_v3: '0x04F8a41be023f839E709eeEaA0725FD766139A4d', | ||||
|       // uniswap_v3_staker: '0x1a96af80ED8753a77E23074De78480675049A3c9',
 | ||||
|       nonfungiblePositionManager: '0xC36442b4a4522E871399CD717aBDD847Ab11FE88', | ||||
|     }, | ||||
|     uniswapV3Staker: '0x1f98407aaB862CdDeF78Ed252D6f557aA5b0f00d', | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| export default addresses; | ||||
|  |  | |||
|  | @ -59,6 +59,15 @@ export default { | |||
|     { key: 'wmatic', type: 'token', symbol: 'WMATIC', name: 'Wrapped MATIC', address: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', decimals: 18, isStableCoin: false}, | ||||
|     { key: 'wbtc', type: 'token', symbol: 'WBTC', name: 'Wrapped BTC', address: '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', decimals: 8, isStableCoin: false}, | ||||
|     { key: 'aave', type: 'token', symbol: 'AAVE', name: 'Aave Token', address: '0xD6DF932A45C0f255f85145f286eA0b292B21C90B', decimals: 18, isStableCoin: false }, | ||||
|   ]) | ||||
|   ]), | ||||
| 
 | ||||
|   arbitrum: createTokenUtils([ | ||||
|     { key: 'eth', type: 'token', symbol: 'ETH', name: 'Ethereum', address: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', decimals: 18, isStableCoin: false }, | ||||
|     { key: 'weth', type: 'token', symbol: 'WETH', name: 'Wrapped Ethereum', address: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', decimals: 18, isStableCoin: false }, | ||||
|     { key: 'usdc', type: 'token', symbol: 'USDC', name: 'USD Coin', address: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', decimals: 6, isStableCoin: true }, | ||||
|     { key: 'usdt', type: 'token', symbol: 'USDT', name: 'Tether USD Coin', address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', decimals: 6, isStableCoin: true }, | ||||
|     { key: 'link', type: 'token', symbol: 'LINK', name: 'ChainLink Token', address: '0xf97f4df75117a78c1A5a0DBb814Af92458539FB4', decimals: 18, isStableCoin: false }, | ||||
|     { key: 'uni', type: 'token', symbol: 'UNI', name: 'Uniswap Token', address: '0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0', decimals: 18, isStableCoin: false }, | ||||
|     { key: 'wbtc', type: 'token', symbol: 'WBTC', name: 'Wrapped BTC', address: '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f', decimals: 8, isStableCoin: false }, | ||||
|   ]) | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,17 @@ | |||
|           class="px-8 md:px-4 max-w-6xl mx-auto" | ||||
|           :class="{ 'text-center': !active, 'py-12': active }" | ||||
|         > | ||||
|           <Nuxt v-if="active" /> | ||||
|           <div v-if="active && activeAccount && activeAccount.version === '1'" class="text-center w-full my-16"> | ||||
|             <h3 class="font-semibold text-2xl"> | ||||
|               Assembly doesn't support DSA v1 | ||||
|             </h3> | ||||
|             <p | ||||
|               class="mt-4 font-medium leading-normal text-grey-pure text-base" | ||||
|             > | ||||
|               Please create or switch to DSA v2. | ||||
|             </p> | ||||
|           </div> | ||||
|           <Nuxt v-else-if="active" /> | ||||
| 
 | ||||
|           <web-3-modal slim v-else /> | ||||
|         </div> | ||||
|  | @ -95,6 +105,7 @@ import { useNetwork } from "~/composables/useNetwork"; | |||
| import { useModal } from "~/composables/useModal"; | ||||
| import { useEagerConnect } from "~/composables/useEagerConnect"; | ||||
| import Web3Modal from "~/components/modal/web3/Web3Modal.vue"; | ||||
| import { useDSA } from "~/composables/useDSA"; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   components: { | ||||
|  | @ -105,6 +116,7 @@ export default defineComponent({ | |||
|   }, | ||||
|   setup() { | ||||
|     const { active, activate, deactivate, chainId } = useWeb3(); | ||||
|     const { activeAccount } = useDSA(); | ||||
|     const { activeNetworkId, activeNetwork, checkForNetworkMismatch } = useNetwork(); | ||||
|     const { isShown: isBackdropShown, close: closeBackdrop } = useBackdrop() | ||||
|     const { redirect } = useContext() | ||||
|  | @ -133,14 +145,14 @@ export default defineComponent({ | |||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         if (route.value.path.includes(['mainnet', 'polygon']) && route.value.path.includes(activeNetwork.value.id)) { | ||||
|         if (route.value.path.includes(['mainnet', 'polygon', "arbitrum"]) && route.value.path.includes(activeNetwork.value.id)) { | ||||
|           redirect('/') | ||||
|         } | ||||
|       }, { immediate: true }) | ||||
| 
 | ||||
|     watch(chainId, (val) => { | ||||
|       if (val) { | ||||
|         if ([1, 137].includes(val)) { | ||||
|         if ([1, 137, 42161].includes(val)) { | ||||
|           checkForNetworkMismatch() | ||||
|         } else { | ||||
|           showNetworksMismatchDialog(); | ||||
|  | @ -154,6 +166,7 @@ export default defineComponent({ | |||
|     }) | ||||
| 
 | ||||
|     return { | ||||
|       activeAccount, | ||||
|       active, | ||||
|       activate, | ||||
|       deactivate, | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
|     "bignumber.js": "^9.0.1", | ||||
|     "core-js": "^3.15.1", | ||||
|     "css-color-function": "^1.3.3", | ||||
|     "dsa-connect": "^0.4.9", | ||||
|     "dsa-connect": "^0.5.0", | ||||
|     "nuxt": "^2.15.7", | ||||
|     "qrcode": "^1.4.4", | ||||
|     "slugify": "^1.6.0", | ||||
|  |  | |||
|  | @ -131,7 +131,7 @@ | |||
| 
 | ||||
|                 <div class="ml-2"><Info text="Debt/Collateral ratio" /></div> | ||||
|               </div> | ||||
|               <span>Max - {{ formatPercent(position.maxLiquidation) }}</span> | ||||
|               <span>Max - {{ formatPercent(maxLiquidation) }}</span> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|  | @ -207,7 +207,8 @@ export default defineComponent({ | |||
|       totalSupply, | ||||
|       totalBorrow, | ||||
|       status, | ||||
|       liquidation | ||||
|       liquidation, | ||||
|       maxLiquidation, | ||||
|     } = useAaveV2Position(); | ||||
| 
 | ||||
|     const { div } = useBigNumber(); | ||||
|  | @ -236,7 +237,8 @@ export default defineComponent({ | |||
|       formatUsd, | ||||
|       formatPercent, | ||||
|       color, | ||||
|       text | ||||
|       text, | ||||
|       maxLiquidation, | ||||
|     }; | ||||
|   } | ||||
| }); | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ import OneInchIcon from "~/assets/icons/1inch.svg?inline"; | |||
| import LiquityIcon from "~/assets/icons/liquity.svg?inline"; | ||||
| import BprotocolIcon from "~/assets/icons/b-protocol.svg?inline"; | ||||
| import ReflexerIcon from "~/assets/icons/reflexer.svg?inline"; | ||||
| import YearnIcon from "~/assets/icons/yearn.svg?inline"; | ||||
| 
 | ||||
| const appsPerNetwork = { | ||||
|   mainnet: [ | ||||
|  | @ -90,6 +91,13 @@ const appsPerNetwork = { | |||
|       name: "Reflexer Finance", | ||||
|       url: "/mainnet/reflexer", | ||||
|       description: "Collateralized RAI Debt" | ||||
|     }, | ||||
|     { | ||||
|       id: "yearn-v2", | ||||
|       icon: YearnIcon, | ||||
|       name: "Yearn", | ||||
|       url: "/mainnet/yearn-v2", | ||||
|       description: "Automated Yield Strategies" | ||||
|     } | ||||
|   ], | ||||
|   polygon: [ | ||||
|  | @ -107,6 +115,15 @@ const appsPerNetwork = { | |||
|       url: "/1inch", | ||||
|       description: "DEX Aggregator" | ||||
|     } | ||||
|   ], | ||||
|   arbitrum: [ | ||||
|     { | ||||
|       id: "1inch", | ||||
|       icon: OneInchIcon, | ||||
|       name: "1inch", | ||||
|       url: "/1inch", | ||||
|       description: "DEX Aggregator" | ||||
|     } | ||||
|   ] | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -131,7 +131,7 @@ | |||
| 
 | ||||
|                 <div class="ml-2"><Info text="Debt/Collateral ratio" /></div> | ||||
|               </div> | ||||
|               <span>Max - {{ formatPercent(position.maxLiquidation) }}</span> | ||||
|               <span>Max - {{ formatPercent(liquidation) }}</span> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|  | @ -205,7 +205,7 @@ export default defineComponent({ | |||
|       totalSupply, | ||||
|       totalBorrow, | ||||
|       status, | ||||
|       liquidation | ||||
|       liquidation, | ||||
|     } = useCompoundPosition(); | ||||
| 
 | ||||
|     const { div } = useBigNumber(); | ||||
|  | @ -234,7 +234,8 @@ export default defineComponent({ | |||
|       formatUsd, | ||||
|       formatPercent, | ||||
|       color, | ||||
|       text | ||||
|       text, | ||||
|       liquidation, | ||||
|     }; | ||||
|   } | ||||
| }); | ||||
|  |  | |||
							
								
								
									
										100
									
								
								pages/mainnet/yearn-v2.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								pages/mainnet/yearn-v2.vue
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| <template> | ||||
|   <div> | ||||
|     <div> | ||||
|       <nuxt-link | ||||
|         to="/" | ||||
|         class="text-[#C0C5D7] text-lg font-semibold flex items-center" | ||||
|       > | ||||
|         <BackIcon class="w-4 h-4 mr-3" /> | ||||
|         Apps | ||||
|       </nuxt-link> | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="mt-10 flex items-center justify-between"> | ||||
|       <div class="flex items-center"> | ||||
|         <div | ||||
|           style="background: radial-gradient(42.15% 42.15% at 48.94% 48.94%, #D6DAE0 75.67%, #F0F3F9 100%), #C4C4C4;" | ||||
|           class="w-16 h-16 rounded-full flex items-center justify-center border border-[#CCDCF3]" | ||||
|         > | ||||
|           <div | ||||
|             class="w-12 h-12 rounded-full flex items-center justify-center bg-[#1874FF]" | ||||
|           > | ||||
|             <YearnIcon class="w-8 h-8 text-white" /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <h1 class="ml-4 text-primary-black text-2xl font-semibold">Yearn</h1> | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="mt-[60px]"> | ||||
|       <div | ||||
|         class="w-full flex flex-col mt-6 sm:flex-row sm:items-center sm:justify-between xl:mt-4" | ||||
|       > | ||||
|         <h2 class="text-primary-gray text-lg font-semibold">Your Positions</h2> | ||||
| 
 | ||||
|         <div class="mt-4 sm:mt-0 sm:mr-1"> | ||||
|           <SearchInput | ||||
|             v-model.trim="search" | ||||
|             dense | ||||
|             class="w-[200px]" | ||||
|             placeholder="Search positions" | ||||
|           /> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div | ||||
|         class="mt-3 grid w-full grid-cols-1 gap-4 sm:grid-cols-2 xxl:gap-6 min-w-max-content px-1" | ||||
|       > | ||||
|         <div v-for="item in filteredVaults" :key="item.symbol"> | ||||
|           <card-yearn | ||||
|             :vault="item.address" | ||||
|             :token-key="item.token.display_name.toLowerCase()" | ||||
|             :supply="item.position.supply" | ||||
|             :supply-usd="item.position.supplyUsd" | ||||
|             :type="item.type" | ||||
|             :price-in-usd="item.priceInUsd" | ||||
|             :netAPY="item.apy.net_apy" | ||||
| 
 | ||||
|           /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, computed } from "@nuxtjs/composition-api"; | ||||
| import BackIcon from "~/assets/icons/back.svg?inline"; | ||||
| import { useYearnV2Position } from "~/composables/protocols/useYearnV2Position"; | ||||
| import { useFormatting } from "~/composables/useFormatting"; | ||||
| import { useSearchFilter } from "~/composables/useSearchFilter"; | ||||
| import CardYearn from "~/components/protocols/yearn-v2/CardYearn.vue"; | ||||
| import YearnIcon from "~/assets/icons/yearn.svg?inline"; | ||||
| import ButtonCTAOutlined from "~/components/common/input/ButtonCTAOutlined.vue"; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   components: { | ||||
|     BackIcon, | ||||
|     CardYearn, | ||||
|     YearnIcon, | ||||
|     ButtonCTAOutlined, | ||||
|   }, | ||||
|   setup() { | ||||
|     const { vaults } = useYearnV2Position(); | ||||
| 
 | ||||
|     const { formatUsd, formatPercent } = useFormatting(); | ||||
| 
 | ||||
|     const { filtered: filteredVaults, search } = useSearchFilter( | ||||
|       vaults, | ||||
|       "key", | ||||
|       "display_name" | ||||
|     ); | ||||
| 
 | ||||
|     return { | ||||
|       filteredVaults, | ||||
|       search, | ||||
|       formatUsd, | ||||
|       formatPercent | ||||
|     }; | ||||
|   } | ||||
| }); | ||||
| </script> | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 shmuel
						shmuel