diff --git a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/dai.aave-v2.cy.ts b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/dai.aave-v2.cy.ts
index 1eb495a42c..e87dac8cae 100644
--- a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/dai.aave-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/dai.aave-v2.cy.ts
@@ -59,14 +59,13 @@ const testData = {
hasApproval: true,
repayOption: constants.repayType.default,
},
- // {
- // asset: assets.aaveMarket.DAI,
- // apyType: constants.apyType.stable,
- // amount: 10,
- // hasApproval: false,
- // repayOption: constants.repayType.collateral,
- // assetForRepay: assets.aaveMarket.BAT,
- // },
+ {
+ asset: assets.aaveMarket.DAI,
+ apyType: constants.apyType.stable,
+ amount: 10,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
],
withdraw: {
asset: assets.aaveMarket.DAI,
@@ -81,7 +80,6 @@ const testData = {
type: constants.dashboardTypes.deposit,
assetName: assets.aaveMarket.DAI.shortName,
wrapped: assets.aaveMarket.DAI.wrapped,
- // amount: 30,
amount: 40,
collateralType: constants.collateralType.isCollateral,
isCollateral: true,
@@ -90,8 +88,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.aaveMarket.DAI.shortName,
wrapped: assets.aaveMarket.DAI.wrapped,
- // amount: 80,
- amount: 90,
+ amount: 80,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/ren.aave-v2.cy.ts b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/ren.aave-v2.cy.ts
index 7d8c3b2988..f811b984b5 100644
--- a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/ren.aave-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/ren.aave-v2.cy.ts
@@ -59,14 +59,13 @@ const testData = {
hasApproval: true,
repayOption: constants.repayType.default,
},
- // {
- // asset: assets.aaveMarket.REN,
- // apyType: constants.apyType.stable,
- // amount: 20,
- // hasApproval: false,
- // repayOption: constants.repayType.collateral,
- // assetForRepay: assets.aaveMarket.BAT,
- // },
+ {
+ asset: assets.aaveMarket.REN,
+ apyType: constants.apyType.stable,
+ amount: 20,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
],
withdraw: {
asset: assets.aaveMarket.REN,
@@ -81,7 +80,6 @@ const testData = {
type: constants.dashboardTypes.deposit,
assetName: assets.aaveMarket.REN.shortName,
wrapped: assets.aaveMarket.REN.wrapped,
- // amount: 60,
amount: 80,
collateralType: constants.collateralType.isCollateral,
isCollateral: true,
@@ -90,8 +88,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.aaveMarket.REN.shortName,
wrapped: assets.aaveMarket.REN.wrapped,
- // amount: 160,
- amount: 180,
+ amount: 160,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/tusd.aave-v2.cy.ts b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/tusd.aave-v2.cy.ts
index a932392319..3900460d95 100644
--- a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/tusd.aave-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/tusd.aave-v2.cy.ts
@@ -59,14 +59,13 @@ const testData = {
hasApproval: true,
repayOption: constants.repayType.default,
},
- // {
- // asset: assets.aaveMarket.TUSD,
- // apyType: constants.apyType.stable,
- // amount: 10,
- // hasApproval: false,
- // repayOption: constants.repayType.collateral,
- // assetForRepay: assets.aaveMarket.TUSD,
- // },
+ {
+ asset: assets.aaveMarket.TUSD,
+ apyType: constants.apyType.stable,
+ amount: 10,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
],
withdraw: {
asset: assets.aaveMarket.TUSD,
@@ -81,7 +80,6 @@ const testData = {
type: constants.dashboardTypes.deposit,
assetName: assets.aaveMarket.TUSD.shortName,
wrapped: assets.aaveMarket.TUSD.wrapped,
- // amount: 30,
amount: 40,
collateralType: constants.collateralType.isCollateral,
isCollateral: true,
@@ -90,8 +88,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.aaveMarket.TUSD.shortName,
wrapped: assets.aaveMarket.TUSD.wrapped,
- // amount: 80,
- amount: 90,
+ amount: 80,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdc.aave-v2.cy.ts b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdc.aave-v2.cy.ts
index c5d22718f7..6d1ce859fb 100644
--- a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdc.aave-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdc.aave-v2.cy.ts
@@ -59,14 +59,13 @@ const testData = {
hasApproval: true,
repayOption: constants.repayType.default,
},
- // {
- // asset: assets.aaveMarket.USDC,
- // apyType: constants.apyType.stable,
- // amount: 10,
- // hasApproval: false,
- // repayOption: constants.repayType.collateral,
- // assetForRepay: assets.aaveMarket.USDC,
- // },
+ {
+ asset: assets.aaveMarket.USDC,
+ apyType: constants.apyType.stable,
+ amount: 10,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
],
withdraw: {
asset: assets.aaveMarket.USDC,
@@ -81,7 +80,6 @@ const testData = {
type: constants.dashboardTypes.deposit,
assetName: assets.aaveMarket.USDC.shortName,
wrapped: assets.aaveMarket.USDC.wrapped,
- // amount: 30,
amount: 40,
collateralType: constants.collateralType.isCollateral,
isCollateral: true,
@@ -90,8 +88,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.aaveMarket.USDC.shortName,
wrapped: assets.aaveMarket.USDC.wrapped,
- // amount: 80,
- amount: 90,
+ amount: 80,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdt.aave-v2.cy.ts b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdt.aave-v2.cy.ts
index 90779a4569..d55c05c2b2 100644
--- a/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdt.aave-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/0-main-v2-market/0-assets/usdt.aave-v2.cy.ts
@@ -62,14 +62,13 @@ const testData = {
hasApproval: true,
repayOption: constants.repayType.default,
},
- // {
- // asset: assets.aaveMarket.USDT,
- // apyType: constants.apyType.stable,
- // amount: 10,
- // hasApproval: false,
- // repayOption: constants.repayType.collateral,
- // assetForRepay: assets.aaveMarket.USDT,
- // },
+ {
+ asset: assets.aaveMarket.USDT,
+ apyType: constants.apyType.stable,
+ amount: 10,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
],
withdraw: {
asset: assets.aaveMarket.USDT,
@@ -88,7 +87,6 @@ const testData = {
type: constants.dashboardTypes.deposit,
assetName: assets.aaveMarket.USDT.shortName,
wrapped: assets.aaveMarket.USDT.wrapped,
- // amount: 30,
amount: 40,
collateralType: constants.collateralType.isCollateral,
isCollateral: false,
@@ -97,8 +95,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.aaveMarket.USDT.shortName,
wrapped: assets.aaveMarket.USDT.wrapped,
- // amount: 80,
- amount: 90,
+ amount: 80,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdc.polygon-v2.cy.ts b/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdc.polygon-v2.cy.ts
index edbcbfc6e1..8aa9ab3003 100644
--- a/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdc.polygon-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdc.polygon-v2.cy.ts
@@ -22,13 +22,22 @@ const testData = {
amount: 10,
hasApproval: false,
},
- repay: {
- asset: assets.polygonMarket.USDC,
- apyType: constants.apyType.variable,
- amount: 2,
- hasApproval: true,
- repayOption: constants.repayType.default,
- },
+ repay: [
+ {
+ asset: assets.polygonMarket.USDC,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: true,
+ repayOption: constants.repayType.default,
+ },
+ {
+ asset: assets.polygonMarket.USDC,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
+ ],
withdraw: {
asset: assets.polygonMarket.USDC,
isCollateral: true,
@@ -50,7 +59,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.polygonMarket.USDC.shortName,
wrapped: assets.polygonMarket.USDC.wrapped,
- amount: 23.0,
+ amount: 21.0,
apyType: constants.borrowAPYType.variable,
},
],
@@ -64,7 +73,9 @@ describe('USDC INTEGRATION SPEC, POLYGON V2 MARKET', () => {
supply(testData.depositBaseAmount, skipTestState, true);
borrow(testData.testCases.borrow, skipTestState, true);
supply(testData.testCases.deposit, skipTestState, true);
- repay(testData.testCases.repay, skipTestState, false);
+ testData.testCases.repay.forEach((repayCase) => {
+ repay(repayCase, skipTestState, false);
+ });
withdraw(testData.testCases.withdraw, skipTestState, false);
dashboardAssetValuesVerification(testData.verifications.finalDashboard, skipTestState);
});
diff --git a/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdt.polygon-v2.cy.ts b/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdt.polygon-v2.cy.ts
index bda9fd6c8e..68ccca77a0 100644
--- a/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdt.polygon-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/2-polygon-v2-market/0-assets/usdt.polygon-v2.cy.ts
@@ -25,13 +25,22 @@ const testData = {
amount: 10,
hasApproval: false,
},
- repay: {
- asset: assets.polygonMarket.USDT,
- apyType: constants.apyType.variable,
- amount: 2,
- hasApproval: true,
- repayOption: constants.repayType.default,
- },
+ repay: [
+ {
+ asset: assets.polygonMarket.USDT,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: true,
+ repayOption: constants.repayType.default,
+ },
+ {
+ asset: assets.polygonMarket.USDT,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
+ ],
withdraw: {
asset: assets.polygonMarket.USDT,
isCollateral: false,
@@ -57,7 +66,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.polygonMarket.USDT.shortName,
wrapped: assets.polygonMarket.USDT.wrapped,
- amount: 23.0,
+ amount: 21.0,
apyType: constants.borrowAPYType.variable,
},
],
@@ -71,7 +80,9 @@ describe('USDT INTEGRATION SPEC, POLYGON MARKET', () => {
supply(testData.depositBaseAmount, skipTestState, true);
borrow(testData.testCases.borrow, skipTestState, true);
supply(testData.testCases.deposit, skipTestState, true);
- repay(testData.testCases.repay, skipTestState, false);
+ testData.testCases.repay.forEach((repayCase) => {
+ repay(repayCase, skipTestState, false);
+ });
withdraw(testData.testCases.withdraw, skipTestState, false);
changeBorrowTypeBlocked(testData.testCases.checkDisabledCollateral, skipTestState);
dashboardAssetValuesVerification(testData.verifications.finalDashboard, skipTestState);
diff --git a/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdc.avalanche-v2.cy.ts b/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdc.avalanche-v2.cy.ts
index 44ef49fec1..a8e8d585b0 100644
--- a/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdc.avalanche-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdc.avalanche-v2.cy.ts
@@ -25,13 +25,22 @@ const testData = {
amount: 10,
hasApproval: false,
},
- repay: {
- asset: assets.avalancheMarket.USDC,
- apyType: constants.apyType.variable,
- amount: 2,
- hasApproval: true,
- repayOption: constants.repayType.default,
- },
+ repay: [
+ {
+ asset: assets.avalancheMarket.USDC,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: true,
+ repayOption: constants.repayType.default,
+ },
+ {
+ asset: assets.avalancheMarket.USDC,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
+ ],
withdraw: {
asset: assets.avalancheMarket.USDC,
isCollateral: true,
@@ -57,7 +66,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.avalancheMarket.USDC.shortName,
wrapped: assets.avalancheMarket.USDC.wrapped,
- amount: 23.0,
+ amount: 21.0,
apyType: constants.borrowAPYType.variable,
},
],
@@ -71,7 +80,9 @@ describe('USDC INTEGRATION SPEC, AVALANCHE V2 MARKET', () => {
supply(testData.depositBaseAmount, skipTestState, true);
borrow(testData.testCases.borrow, skipTestState, true);
supply(testData.testCases.deposit, skipTestState, true);
- repay(testData.testCases.repay, skipTestState, false);
+ testData.testCases.repay.forEach((repayCase) => {
+ repay(repayCase, skipTestState, false);
+ });
withdraw(testData.testCases.withdraw, skipTestState, false);
switchApyBlocked(testData.testCases.checkDisabledApy, skipTestState);
dashboardAssetValuesVerification(testData.verifications.finalDashboard, skipTestState);
diff --git a/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdt.avalanche-v2.cy.ts b/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdt.avalanche-v2.cy.ts
index 792537669f..78ea09759d 100644
--- a/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdt.avalanche-v2.cy.ts
+++ b/cypress/e2e/0-v2-markets/3-avalanche-v2-market/0-assets/usdt.avalanche-v2.cy.ts
@@ -26,13 +26,22 @@ const testData = {
amount: 10,
hasApproval: false,
},
- repay: {
- asset: assets.avalancheMarket.USDT,
- apyType: constants.apyType.variable,
- amount: 2,
- hasApproval: true,
- repayOption: constants.repayType.default,
- },
+ repay: [
+ {
+ asset: assets.avalancheMarket.USDT,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: true,
+ repayOption: constants.repayType.default,
+ },
+ {
+ asset: assets.avalancheMarket.USDT,
+ apyType: constants.apyType.variable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
+ ],
withdraw: {
asset: assets.avalancheMarket.USDT,
isCollateral: false,
@@ -62,7 +71,7 @@ const testData = {
type: constants.dashboardTypes.borrow,
assetName: assets.avalancheMarket.USDT.shortName,
wrapped: assets.avalancheMarket.USDT.wrapped,
- amount: 23.0,
+ amount: 21.0,
apyType: constants.borrowAPYType.variable,
},
],
@@ -76,7 +85,9 @@ describe('USDT INTEGRATION SPEC, AVALANCHE V2 MARKET', () => {
supply(testData.depositBaseAmount, skipTestState, true);
borrow(testData.testCases.borrow, skipTestState, true);
supply(testData.testCases.deposit, skipTestState, true);
- repay(testData.testCases.repay, skipTestState, false);
+ testData.testCases.repay.forEach((repayCase) => {
+ repay(repayCase, skipTestState, false);
+ });
withdraw(testData.testCases.withdraw, skipTestState, false);
switchApyBlocked(testData.testCases.checkDisabledApy, skipTestState);
changeBorrowTypeBlocked(testData.testCases.checkBorrowTypeBlocked, skipTestState);
diff --git a/cypress/e2e/1-v3-markets/1-arbitrum-v3-market/0-assets/usdc.arbitrum-v3.cy.ts b/cypress/e2e/1-v3-markets/1-arbitrum-v3-market/0-assets/usdc.arbitrum-v3.cy.ts
index 01592b4272..58bdeb7f71 100644
--- a/cypress/e2e/1-v3-markets/1-arbitrum-v3-market/0-assets/usdc.arbitrum-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/1-arbitrum-v3-market/0-assets/usdc.arbitrum-v3.cy.ts
@@ -52,12 +52,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.arbitrumMarket.USDC,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.arbitrumMarket.USDC,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.arbitrumMarket.USDC,
@@ -87,7 +94,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.arbitrumMarket.USDC.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdc.avalanche-v3.cy.ts b/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdc.avalanche-v3.cy.ts
index eb69809d30..100048498c 100644
--- a/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdc.avalanche-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdc.avalanche-v3.cy.ts
@@ -52,12 +52,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.avalancheV3Market.USDC,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.avalancheV3Market.USDC,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.avalancheV3Market.USDC,
@@ -87,7 +94,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.avalancheV3Market.USDC.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdt.avalacnhe-v3.cy.ts b/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdt.avalacnhe-v3.cy.ts
index e9cc302a5a..22bb45e68b 100644
--- a/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdt.avalacnhe-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/2-avalanche-v3-market/0-assets/usdt.avalacnhe-v3.cy.ts
@@ -70,6 +70,13 @@ const testData = {
hasApproval: true,
repayOption: constants.repayType.default,
},
+ {
+ asset: assets.avalancheV3Market.USDT,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
],
withdraw: {
asset: assets.avalancheV3Market.USDT,
@@ -94,7 +101,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.avalancheV3Market.USDT.shortName,
- amount: 16.0,
+ amount: 14.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdc.polygon-v3.cy.ts b/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdc.polygon-v3.cy.ts
index 279af0965a..7bbfc030ad 100644
--- a/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdc.polygon-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdc.polygon-v3.cy.ts
@@ -52,12 +52,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.polygonV3Market.USDC,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.polygonV3Market.USDC,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.polygonV3Market.USDC,
@@ -87,7 +94,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.polygonV3Market.USDC.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdt.polygon-v3.cy.ts b/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdt.polygon-v3.cy.ts
index fdce66bf7c..2fd46c4a50 100644
--- a/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdt.polygon-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/3-polygon-v3-market/0-assets/usdt.polygon-v3.cy.ts
@@ -55,12 +55,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.polygonV3Market.USDT,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.polygonV3Market.USDT,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.polygonV3Market.USDT,
@@ -94,7 +101,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.polygonV3Market.USDT.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/3-polygon-v3-market/e-mode.polygon-v3.cy.ts b/cypress/e2e/1-v3-markets/3-polygon-v3-market/e-mode.polygon-v3.cy.ts
index 7edac00438..9a87334ece 100644
--- a/cypress/e2e/1-v3-markets/3-polygon-v3-market/e-mode.polygon-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/3-polygon-v3-market/e-mode.polygon-v3.cy.ts
@@ -45,7 +45,6 @@ const testData = {
assets.polygonV3Market.EURS,
assets.polygonV3Market.jEUR,
assets.polygonV3Market.agEUR,
- assets.polygonV3Market.miMATIC,
],
},
};
diff --git a/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdc.optimism-v3.cy.ts b/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdc.optimism-v3.cy.ts
index bb4d57065b..d61c2d7a2a 100644
--- a/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdc.optimism-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdc.optimism-v3.cy.ts
@@ -52,12 +52,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.optimismMarket.USDC,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.optimismMarket.USDC,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.optimismMarket.USDC,
@@ -87,7 +94,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.optimismMarket.USDC.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdt.optimism-v3.cy.ts b/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdt.optimism-v3.cy.ts
index 29ff2b2a73..067f6f13c6 100644
--- a/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdt.optimism-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/4-optimism-v3-market/0-assets/usdt.optimism-v3.cy.ts
@@ -55,12 +55,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.optimismMarket.USDT,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.optimismMarket.USDT,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.optimismMarket.USDT,
@@ -94,7 +101,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.optimismMarket.USDT.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/1-v3-markets/5-fantom-v3-market/0-assets/usdc.fantom-v3.cy.ts b/cypress/e2e/1-v3-markets/5-fantom-v3-market/0-assets/usdc.fantom-v3.cy.ts
index 216acb955e..156aab5193 100644
--- a/cypress/e2e/1-v3-markets/5-fantom-v3-market/0-assets/usdc.fantom-v3.cy.ts
+++ b/cypress/e2e/1-v3-markets/5-fantom-v3-market/0-assets/usdc.fantom-v3.cy.ts
@@ -52,12 +52,19 @@ const testData = {
hasApproval: false,
},
repay: [
+ {
+ asset: assets.fantomMarket.USDC,
+ apyType: constants.apyType.stable,
+ amount: 2,
+ hasApproval: false,
+ repayOption: constants.repayType.collateral,
+ },
{
asset: assets.fantomMarket.USDC,
apyType: constants.apyType.stable,
amount: 2,
hasApproval: true,
- repayOption: constants.repayType.default,
+ repayOption: constants.repayType.wallet,
},
{
asset: assets.fantomMarket.USDC,
@@ -87,7 +94,7 @@ const testData = {
{
type: constants.dashboardTypes.borrow,
assetName: assets.fantomMarket.USDC.shortName,
- amount: 46.0,
+ amount: 44.0,
apyType: constants.borrowAPYType.stable,
},
],
diff --git a/cypress/e2e/2-settings/wallet-connect.cy.ts b/cypress/e2e/2-settings/wallet-connect.cy.ts
index 097231c1b5..61b37cab9f 100644
--- a/cypress/e2e/2-settings/wallet-connect.cy.ts
+++ b/cypress/e2e/2-settings/wallet-connect.cy.ts
@@ -11,21 +11,22 @@ export const closeModal = (selector: string) => {
cy.get(selector).click();
};
+const walletButtonlocator = '#wallet-button';
+
describe('Manipulation on the wallet connect', () => {
describe('CASE1: Disconnect and connect wallet using Wallet connect option', () => {
configEnvWithTenderlyMainnetFork({});
- const walletButton = '#wallet-button';
it('step1:Disconnect wallet', () => {
cy.wait(1000);
- cy.get(walletButton).click();
- cy.wait(6000);
+ cy.get(walletButtonlocator).click();
+ cy.wait(3000);
cy.contains('Disconnect').click();
cy.contains('Please, connect your wallet').should('be.visible');
});
it('step2:Connect wallet using wallet connect', () => {
- cy.get(walletButton).click();
+ cy.get(walletButtonlocator).click();
optionOnConnectionModal('WalletConnect');
checkElementsOnModal(
'#walletconnect-qrcode-text',
@@ -39,6 +40,9 @@ describe('Manipulation on the wallet connect', () => {
describe('CASE2:Connect and disconnect wallet over Coinbase', () => {
it('step1:Connect wallet over Coinbase', () => {
+ cy.wait(1000);
+ cy.get(walletButtonlocator).click();
+ cy.wait(3000);
optionOnConnectionModal('Coinbase');
checkElementsOnModal('.-cbwsdk-extension-dialog-box', 'Try the Coinbase Wallet extension');
closeModal('.-cbwsdk-extension-dialog-box-cancel');
diff --git a/cypress/fixtures/assets.json b/cypress/fixtures/assets.json
index 74e2239e1a..43e37bd5d7 100644
--- a/cypress/fixtures/assets.json
+++ b/cypress/fixtures/assets.json
@@ -287,6 +287,11 @@
"fullName": "AAVE/ETH BPT",
"shortName": "ABPT",
"address": "0x41A08648C3766F9F9d85598fF102a08f4ef84F84"
+ },
+ "MKR": {
+ "fullName": "MKR",
+ "shortName": "MKR",
+ "address": "0x7deB5e830be29F91E298ba5FF1356BB7f8146998"
}
},
"fantomMarket": {
diff --git a/cypress/support/steps/main.steps.ts b/cypress/support/steps/main.steps.ts
index 24a72b0839..fb9e99e6c6 100644
--- a/cypress/support/steps/main.steps.ts
+++ b/cypress/support/steps/main.steps.ts
@@ -176,6 +176,7 @@ export const repay = (
repayOption,
hasApproval = false,
repayableAsset,
+ assetForCollateralRepay,
isMaxAmount = false,
}: {
asset: { shortName: string; fullName: string };
@@ -184,6 +185,7 @@ export const repay = (
repayOption: string;
hasApproval: boolean;
repayableAsset?: { shortName: string };
+ assetForCollateralRepay?: { shortName: string };
isMaxAmount?: boolean;
},
skip: SkipType,
@@ -192,8 +194,15 @@ export const repay = (
const _shortName = asset.shortName;
const _actionName = constants.actionTypes.repay;
- return describe(`Repay by ${repayOption} process for ${_shortName} by ${
- repayableAsset ? repayableAsset.shortName : _shortName
+ return describe(`Repay by ${repayOption} process for ${_shortName} by
+ ${
+ repayOption == constants.repayType.collateral
+ ? assetForCollateralRepay
+ ? assetForCollateralRepay.shortName
+ : 'default asset'
+ : repayableAsset
+ ? repayableAsset.shortName
+ : _shortName
}`, () => {
skipSetup({ skip, updateSkipStatus });
it(`Open ${_shortName} repay popup view`, () => {
diff --git a/package.json b/package.json
index c6357199b6..4b8ecc524e 100644
--- a/package.json
+++ b/package.json
@@ -31,8 +31,8 @@
"test:ci": "jest --ci"
},
"dependencies": {
- "@aave/contract-helpers": "1.9.1-d6df625bf33ae6be0ed1a122ca941e3015691c6a.0",
- "@aave/math-utils": "1.9.0",
+ "@aave/contract-helpers": "1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0+7a35ce0",
+ "@aave/math-utils": "1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0+7a35ce0",
"@emotion/cache": "11.10.3",
"@emotion/react": "11.10.4",
"@emotion/server": "latest",
diff --git a/public/icons/other/paraswap.svg b/public/icons/other/paraswap.svg
new file mode 100644
index 0000000000..8803b657b1
--- /dev/null
+++ b/public/icons/other/paraswap.svg
@@ -0,0 +1 @@
+
diff --git a/scripts/populate-cache.js b/scripts/populate-cache.js
index 94bb0de26b..81294d964c 100644
--- a/scripts/populate-cache.js
+++ b/scripts/populate-cache.js
@@ -35725,6 +35725,8 @@ var require_types2 = __commonJS({
ProtocolAction2['repayCollateral'] = 'repayCollateral';
ProtocolAction2['withdrawETH'] = 'withdrawETH';
ProtocolAction2['borrowETH'] = 'borrwoETH';
+ ProtocolAction2['supplyWithPermit'] = 'supplyWithPermit';
+ ProtocolAction2['repayWithPermit'] = 'repayWithPermit';
})((ProtocolAction = exports2.ProtocolAction || (exports2.ProtocolAction = {})));
var GovernanceVote;
(function (GovernanceVote2) {
@@ -37479,6 +37481,14 @@ var require_utils6 = __commonJS({
limit: '700000',
recommended: '700000',
},
+ [types_1.ProtocolAction.supplyWithPermit]: {
+ limit: '350000',
+ recommended: '350000',
+ },
+ [types_1.ProtocolAction.repayWithPermit]: {
+ limit: '350000',
+ recommended: '350000',
+ },
};
exports2.mintAmountsPerToken = {
AAVE: (0, exports2.valueToWei)('100', 18),
@@ -75829,8 +75839,8 @@ var networkConfigs = {
// src/utils/rotationProvider.ts
var import_providers = __toESM(require_lib30());
var import_ethers = __toESM(require_lib31());
-var DEFAULT_ROTATION_DELAY = 5e3;
var DEFAULT_FALL_FORWARD_DELAY = 6e4;
+var MAX_RETRIES = 1;
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
@@ -75871,8 +75881,10 @@ var RotationProvider = class extends import_providers.BaseProvider {
super(chainId);
this.currentProviderIndex = 0;
this.firstRotationTimestamp = 0;
+ this.maxRetries = 0;
+ this.retries = 0;
this.providers = urls.map((url) => new import_providers.StaticJsonRpcProvider(url, chainId));
- this.rotationDelay = (config == null ? void 0 : config.rotationDelay) || DEFAULT_ROTATION_DELAY;
+ this.maxRetries = (config == null ? void 0 : config.maxRetries) || MAX_RETRIES;
this.fallForwardDelay =
(config == null ? void 0 : config.fallFowardDelay) || DEFAULT_FALL_FORWARD_DELAY;
}
@@ -75894,7 +75906,11 @@ var RotationProvider = class extends import_providers.BaseProvider {
this.firstRotationTimestamp = new Date().getTime();
this.fallForwardRotation();
} else if (this.currentProviderIndex === this.providers.length - 1) {
- yield sleep(this.rotationDelay);
+ this.retries += 1;
+ if (this.retries > this.maxRetries) {
+ this.retries = 0;
+ throw new Error('RotationProvider exceeded max number of retries');
+ }
this.currentProviderIndex = 0;
} else {
this.currentProviderIndex += 1;
diff --git a/src/components/AddressBlocked.tsx b/src/components/AddressBlocked.tsx
index 92649e50be..1f11fea062 100644
--- a/src/components/AddressBlocked.tsx
+++ b/src/components/AddressBlocked.tsx
@@ -6,8 +6,9 @@ import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import { AddressBlockedModal } from './AddressBlockedModal';
export const AddressBlocked = ({ children }: { children: ReactNode }) => {
- const { currentAccount, disconnectWallet } = useWeb3Context();
- const { isAllowed } = useAddressAllowed(currentAccount);
+ const { currentAccount, disconnectWallet, watchModeOnly } = useWeb3Context();
+ const screenAddress = watchModeOnly ? '' : currentAccount;
+ const { isAllowed } = useAddressAllowed(screenAddress);
if (!isAllowed) {
return (
diff --git a/src/components/TextWithTooltip.tsx b/src/components/TextWithTooltip.tsx
index 49829d37e6..4704457804 100644
--- a/src/components/TextWithTooltip.tsx
+++ b/src/components/TextWithTooltip.tsx
@@ -9,6 +9,7 @@ export interface TextWithTooltipProps extends TypographyProps {
text?: ReactNode;
icon?: ReactNode;
iconSize?: number;
+ iconMargin?: number;
color?: string;
// eslint-disable-next-line
children?: ReactElement>;
@@ -18,6 +19,7 @@ export const TextWithTooltip = ({
text,
icon,
iconSize = 14,
+ iconMargin,
color,
children,
...rest
@@ -39,7 +41,7 @@ export const TextWithTooltip = ({
borderRadius: '50%',
p: 0,
minWidth: 0,
- ml: 0.5,
+ ml: iconMargin || 0.5,
}}
>
{
- return (
- Approval}>
-
-
- Before supplying, you need to approve its usage by the Aave protocol. You can learn more
- in our{' '}
-
- FAQ
-
-
-
-
- );
-};
diff --git a/src/components/infoModalContents/RetryWithApprovalInfoContent.tsx b/src/components/infoModalContents/RetryWithApprovalInfoContent.tsx
deleted file mode 100644
index 900103a0a4..0000000000
--- a/src/components/infoModalContents/RetryWithApprovalInfoContent.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Trans } from '@lingui/macro';
-import Typography from '@mui/material/Typography';
-
-import { InfoContentWrapper } from './InfoContentWrapper';
-
-export const RetryWithApprovalInfoContent = () => {
- return (
- Retry with Approval}>
-
- Define Retry with Approval text
-
-
- );
-};
diff --git a/src/components/infoTooltips/ApprovalTooltip.tsx b/src/components/infoTooltips/ApprovalTooltip.tsx
new file mode 100644
index 0000000000..11715b2013
--- /dev/null
+++ b/src/components/infoTooltips/ApprovalTooltip.tsx
@@ -0,0 +1,19 @@
+import { Trans } from '@lingui/macro';
+
+import { Link } from '../primitives/Link';
+import { TextWithTooltip, TextWithTooltipProps } from '../TextWithTooltip';
+
+export const ApprovalTooltip = ({ ...rest }: TextWithTooltipProps) => {
+ return (
+
+
+ To continue, you need to grant Aave smart contracts permission to move your funds from your
+ wallet. Depending on the asset and wallet you use, it is done by signing the permission
+ message (gas free), or by submitting an approval transaction (requires gas).{' '}
+
+ Learn more
+
+
+
+ );
+};
diff --git a/src/components/infoTooltips/PriceImpactTooltip.tsx b/src/components/infoTooltips/PriceImpactTooltip.tsx
new file mode 100644
index 0000000000..a78f20d0da
--- /dev/null
+++ b/src/components/infoTooltips/PriceImpactTooltip.tsx
@@ -0,0 +1,50 @@
+import { Trans } from '@lingui/macro';
+import { Box, Skeleton } from '@mui/material';
+
+import { FormattedNumber } from '../primitives/FormattedNumber';
+import { TextWithTooltip, TextWithTooltipProps } from '../TextWithTooltip';
+
+interface PriceImpactTooltipProps extends TextWithTooltipProps {
+ loading: boolean;
+ priceImpact: string;
+}
+
+export const PriceImpactTooltip = ({ loading, priceImpact, ...rest }: PriceImpactTooltipProps) => {
+ return (
+
+
+ Price impact{' '}
+ {loading ? (
+
+ ) : (
+
+ )}
+ %
+
+
+ }
+ {...rest}
+ >
+
+ Price impact is the spread between the total value of the entry tokens swapped and the
+ destination tokens obtained (in USD), which results from the limited liquidity of the
+ trading pair.
+
+
+ );
+};
diff --git a/src/components/infoTooltips/SlippageTooltip.tsx b/src/components/infoTooltips/SlippageTooltip.tsx
new file mode 100644
index 0000000000..76ba3d73d0
--- /dev/null
+++ b/src/components/infoTooltips/SlippageTooltip.tsx
@@ -0,0 +1,14 @@
+import { Trans } from '@lingui/macro';
+
+import { TextWithTooltip, TextWithTooltipProps } from '../TextWithTooltip';
+
+export const SlippageTooltip = ({ ...rest }: TextWithTooltipProps) => {
+ return (
+
+
+ Slippage is the difference between the quoted and received amounts from changing market
+ conditions between the moment the transaction is submitted and its verification.
+
+
+ );
+};
diff --git a/src/components/transactions/AssetInput.tsx b/src/components/transactions/AssetInput.tsx
index f2c7620c3c..aaa4fdb9d5 100644
--- a/src/components/transactions/AssetInput.tsx
+++ b/src/components/transactions/AssetInput.tsx
@@ -3,6 +3,7 @@ import { Trans } from '@lingui/macro';
import {
Box,
Button,
+ CircularProgress,
FormControl,
IconButton,
InputBase,
@@ -74,7 +75,8 @@ export interface AssetInputProps {
maxValue?: string;
isMaxSelected?: boolean;
inputTitle?: ReactNode;
- balanceText?: ReactNode; // Support translated text
+ balanceText?: ReactNode;
+ loading?: boolean;
}
export const AssetInput = ({
@@ -91,6 +93,7 @@ export const AssetInput = ({
isMaxSelected,
inputTitle,
balanceText,
+ loading = false,
}: AssetInputProps) => {
const handleSelect = (event: SelectChangeEvent) => {
const newAsset = assets.find((asset) => asset.symbol === event.target.value) as T;
@@ -121,35 +124,41 @@ export const AssetInput = ({
})}
>
- {
- if (!onChange) return;
- if (Number(e.target.value) > Number(maxValue)) {
- onChange('-1');
- } else {
- onChange(e.target.value);
- }
- }}
- inputProps={{
- 'aria-label': 'amount input',
- style: {
- fontSize: '21px',
- lineHeight: '28,01px',
- padding: 0,
- height: '28px',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- overflow: 'hidden',
- },
- }}
- // eslint-disable-next-line
- inputComponent={NumberFormatCustom as any}
- />
+ {loading ? (
+
+
+
+ ) : (
+ {
+ if (!onChange) return;
+ if (Number(e.target.value) > Number(maxValue)) {
+ onChange('-1');
+ } else {
+ onChange(e.target.value);
+ }
+ }}
+ inputProps={{
+ 'aria-label': 'amount input',
+ style: {
+ fontSize: '21px',
+ lineHeight: '28,01px',
+ padding: 0,
+ height: '28px',
+ textOverflow: 'ellipsis',
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ },
+ }}
+ // eslint-disable-next-line
+ inputComponent={NumberFormatCustom as any}
+ />
+ )}
{value !== '' && !disableInput && (
({
'&.AssetInput__select .MuiOutlinedInput-notchedOutline': { display: 'none' },
'&.AssetInput__select .MuiSelect-icon': {
color: 'text.primary',
+ right: '0%',
},
}}
renderValue={(symbol) => {
@@ -245,15 +255,19 @@ export const AssetInput = ({
-
+ {loading ? (
+
+ ) : (
+
+ )}
{asset.balance && onChange && (
<>
@@ -267,14 +281,16 @@ export const AssetInput = ({
symbolsColor="text.disabled"
/>
-
+ {!disableInput && (
+
+ )}
>
)}
diff --git a/src/components/transactions/Borrow/BorrowModalContent.tsx b/src/components/transactions/Borrow/BorrowModalContent.tsx
index 6dd39395f2..99fd5bfd0f 100644
--- a/src/components/transactions/Borrow/BorrowModalContent.tsx
+++ b/src/components/transactions/Borrow/BorrowModalContent.tsx
@@ -74,7 +74,7 @@ const BorrowModeSwitch = ({
value={interestRateMode}
exclusive
onChange={(_, value) => setInterestRateMode(value)}
- sx={{ width: '100%', mt: 0.5 }}
+ sx={{ width: '100%', height: '36px', p: '2px', mt: 0.5 }}
>
void;
+}
+
+export const ApprovalMethodToggleButton = ({
+ currentMethod,
+ setMethod,
+}: ApprovalMethodToggleButtonProps) => {
+ const [anchorEl, setAnchorEl] = React.useState(null);
+ const open = Boolean(anchorEl);
+ const handleClick = (event: React.MouseEvent) => {
+ setAnchorEl(event.currentTarget);
+ };
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ return (
+ <>
+
+
+ {currentMethod}
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/src/components/transactions/FlowCommons/LeftHelperText.tsx b/src/components/transactions/FlowCommons/LeftHelperText.tsx
deleted file mode 100644
index 1d34488358..0000000000
--- a/src/components/transactions/FlowCommons/LeftHelperText.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import { CheckIcon } from '@heroicons/react/outline';
-import { Trans } from '@lingui/macro';
-import { Box, Typography, useTheme } from '@mui/material';
-
-import { ApprovalInfoContent } from '../../infoModalContents/ApprovalInfoContent';
-import { RetryWithApprovalInfoContent } from '../../infoModalContents/RetryWithApprovalInfoContent';
-import { TextWithModal } from '../../TextWithModal';
-
-export type LeftHelperTextProps = {
- error?: string;
- approvalHash?: string;
- amount?: string;
-};
-
-export const LeftHelperText = ({ error, approvalHash, amount }: LeftHelperTextProps) => {
- const theme = useTheme();
-
- return (
-
- {approvalHash && (
- <>
-
-
- Approve confirmed
-
- >
- )}
-
- {error && (
- Retry What?}
- iconSize={13}
- iconColor={theme.palette.text.secondary}
- withContentButton
- variant="helperText"
- color="text.secondary"
- >
-
-
- )}
-
- {!approvalHash && !error && amount && (
- Why do I need to approve?}
- iconSize={13}
- iconColor={theme.palette.text.secondary}
- withContentButton
- variant="helperText"
- color="text.secondary"
- >
-
-
- )}
-
- );
-};
diff --git a/src/components/transactions/FlowCommons/RightHelperText.tsx b/src/components/transactions/FlowCommons/RightHelperText.tsx
index 1fc34fcaa9..d950dff498 100644
--- a/src/components/transactions/FlowCommons/RightHelperText.tsx
+++ b/src/components/transactions/FlowCommons/RightHelperText.tsx
@@ -1,11 +1,15 @@
import { ExternalLinkIcon } from '@heroicons/react/outline';
import { Trans } from '@lingui/macro';
-import { Box, Link, SvgIcon } from '@mui/material';
+import { Box, Link, SvgIcon, Typography } from '@mui/material';
+import { ApprovalMethodToggleButton } from 'src/components/transactions/FlowCommons/ApprovalMethodToggleButton';
import { MOCK_SIGNED_HASH } from 'src/helpers/useTransactionHandler';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
+import { useRootStore } from 'src/store/root';
+import { ApprovalMethod } from 'src/store/walletSlice';
export type RightHelperTextProps = {
approvalHash?: string;
+ tryPermit?: boolean;
};
const ExtLinkIcon = () => (
@@ -14,32 +18,48 @@ const ExtLinkIcon = () => (
);
-export const RightHelperText = ({ approvalHash }: RightHelperTextProps) => {
+export const RightHelperText = ({ approvalHash, tryPermit }: RightHelperTextProps) => {
+ const { walletApprovalMethodPreference, setWalletApprovalMethodPreference } = useRootStore();
+ const usingPermit = tryPermit && walletApprovalMethodPreference;
const { currentNetworkConfig } = useProtocolDataContext();
const isSigned = approvalHash === MOCK_SIGNED_HASH;
- // a signature will not be reviewable on etherscan
- if (!approvalHash || isSigned) return null;
- return (
-
- {approvalHash && (
-
- Review approval tx details
-
-
- )}
-
- );
+ // a signature is not submitted on-chain so there is no link to review
+ if (!approvalHash && !isSigned && tryPermit)
+ return (
+
+
+ Approve with
+
+ setWalletApprovalMethodPreference(method)}
+ />
+
+ );
+ if (approvalHash && !usingPermit)
+ return (
+
+ {approvalHash && (
+
+ Review approval tx details
+
+
+ )}
+
+ );
+ return <>>;
};
diff --git a/src/components/transactions/FlowCommons/TxModalDetails.tsx b/src/components/transactions/FlowCommons/TxModalDetails.tsx
index bd83563e7b..7fd4c0bdc8 100644
--- a/src/components/transactions/FlowCommons/TxModalDetails.tsx
+++ b/src/components/transactions/FlowCommons/TxModalDetails.tsx
@@ -2,7 +2,7 @@ import { ReserveIncentiveResponse } from '@aave/math-utils/dist/esm/formatters/i
import { CheckIcon, ExclamationIcon } from '@heroicons/react/outline';
import { ArrowNarrowRightIcon } from '@heroicons/react/solid';
import { Trans } from '@lingui/macro';
-import { Box, FormControlLabel, SvgIcon, Switch, Typography } from '@mui/material';
+import { Box, FormControlLabel, Skeleton, SvgIcon, Switch, Typography } from '@mui/material';
import { parseUnits } from 'ethers/lib/utils';
import React, { ReactNode } from 'react';
import { CollateralType } from 'src/helpers/types';
@@ -16,9 +16,20 @@ import { GasStation } from '../GasStation/GasStation';
export interface TxModalDetailsProps {
gasLimit?: string;
+ slippageSelector?: ReactNode;
}
-export const TxModalDetails: React.FC = ({ gasLimit, children }) => {
+const ArrowRightIcon = (
+
+
+
+);
+
+export const TxModalDetails: React.FC = ({
+ gasLimit,
+ slippageSelector,
+ children,
+}) => {
return (
@@ -37,8 +48,10 @@ export const TxModalDetails: React.FC = ({ gasLimit, childr
>
{children}
-
-
+
+
+ {slippageSelector}
+
);
};
@@ -49,6 +62,7 @@ interface DetailsNumberLineProps extends FormattedNumberProps {
futureValue?: FormattedNumberProps['value'];
numberPrefix?: ReactNode;
iconSymbol?: string;
+ loading?: boolean;
}
export const DetailsNumberLine = ({
@@ -57,20 +71,25 @@ export const DetailsNumberLine = ({
futureValue,
numberPrefix,
iconSymbol,
+ loading = false,
...rest
}: DetailsNumberLineProps) => {
return (
- {iconSymbol && }
- {numberPrefix && {numberPrefix}}
-
- {futureValue && (
+ {loading ? (
+
+ ) : (
<>
-
-
-
-
+ {iconSymbol && }
+ {numberPrefix && {numberPrefix}}
+
+ {futureValue && (
+ <>
+ {ArrowRightIcon}
+
+ >
+ )}
>
)}
@@ -87,6 +106,8 @@ interface DetailsNumberLineWithSubProps {
futureValueUSD: string;
hideSymbolSuffix?: boolean;
color?: string;
+ tokenIcon?: string;
+ loading?: boolean;
}
export const DetailsNumberLineWithSub = ({
@@ -98,42 +119,55 @@ export const DetailsNumberLineWithSub = ({
futureValueUSD,
hideSymbolSuffix,
color,
+ tokenIcon,
+ loading = false,
}: DetailsNumberLineWithSubProps) => {
return (
-
- {value && (
- <>
-
+ {loading ? (
+ <>
+
+
+ >
+ ) : (
+ <>
+
+ {value && (
+ <>
+
+ {!hideSymbolSuffix && (
+
+ {symbol}
+
+ )}
+ {ArrowRightIcon}
+ >
+ )}
+ {tokenIcon && }
+
{!hideSymbolSuffix && (
{symbol}
)}
-
-
-
- >
- )}
-
- {!hideSymbolSuffix && (
-
- {symbol}
-
- )}
-
-
- {valueUSD && (
- <>
-
-
-
-
- >
- )}
-
-
+
+
+ {valueUSD && (
+ <>
+
+ {ArrowRightIcon}
+ >
+ )}
+
+
+ >
+ )}
);
@@ -198,6 +232,7 @@ interface DetailsIncentivesLineProps {
incentives?: ReserveIncentiveResponse[];
// the token yielding the incentive, not the incentive itself
symbol: string;
+ loading?: boolean;
}
export const DetailsIncentivesLine = ({
@@ -205,19 +240,31 @@ export const DetailsIncentivesLine = ({
symbol,
futureIncentives,
futureSymbol,
+ loading = false,
}: DetailsIncentivesLineProps) => {
if (!incentives || incentives.filter((i) => i.incentiveAPR !== '0').length === 0) return null;
return (
Rewards APR} captionVariant="description" mb={4} minHeight={24}>
-
- {futureSymbol && (
- <>
-
-
-
-
- >
- )}
+
+ {loading ? (
+
+ ) : (
+ <>
+
+ {futureSymbol && (
+ <>
+ {ArrowRightIcon}
+
+ {futureIncentives && futureIncentives.length === 0 && (
+
+ None
+
+ )}
+ >
+ )}
+ >
+ )}
+
);
};
@@ -226,12 +273,14 @@ export interface DetailsHFLineProps {
healthFactor: string;
futureHealthFactor: string;
visibleHfChange: boolean;
+ loading?: boolean;
}
export const DetailsHFLine = ({
healthFactor,
futureHealthFactor,
visibleHfChange,
+ loading = false,
}: DetailsHFLineProps) => {
if (healthFactor === '-1' && futureHealthFactor === '-1') return null;
return (
@@ -243,18 +292,22 @@ export const DetailsHFLine = ({
>
-
-
- {visibleHfChange && (
+ {loading ? (
+
+ ) : (
<>
-
-
-
+
+
+ {visibleHfChange && (
+ <>
+ {ArrowRightIcon}
-
+
+ >
+ )}
>
)}
diff --git a/src/components/transactions/MigrateV3/MigrateV3Actions.tsx b/src/components/transactions/MigrateV3/MigrateV3Actions.tsx
index ddfb3432e9..ab0e5f1fed 100644
--- a/src/components/transactions/MigrateV3/MigrateV3Actions.tsx
+++ b/src/components/transactions/MigrateV3/MigrateV3Actions.tsx
@@ -1,3 +1,4 @@
+import { ProtocolAction } from '@aave/contract-helpers';
import { Trans } from '@lingui/macro';
import { useTransactionHandler } from 'src/helpers/useTransactionHandler';
import { useRootStore } from 'src/store/root';
@@ -20,6 +21,7 @@ export const MigrateV3Actions = ({ isWrongNetwork, blocked }: MigrateV3ActionsPr
handleGetTxns: async () => migrateWithoutPermits(),
handleGetPermitTxns: async (signatures, deadline) => migrateWithPermits(signatures, deadline),
tryPermit: true,
+ permitAction: ProtocolAction.migrateV3,
});
const handleApproval = async () => {
@@ -39,6 +41,7 @@ export const MigrateV3Actions = ({ isWrongNetwork, blocked }: MigrateV3ActionsPr
blocked={blocked}
actionText={Migrate}
actionInProgressText={Migrating}
+ tryPermit
/>
);
};
diff --git a/src/components/transactions/Repay/CollateralRepayActions.tsx b/src/components/transactions/Repay/CollateralRepayActions.tsx
index f7a08f5220..044c53df9a 100644
--- a/src/components/transactions/Repay/CollateralRepayActions.tsx
+++ b/src/components/transactions/Repay/CollateralRepayActions.tsx
@@ -1,14 +1,19 @@
-import { InterestRate } from '@aave/contract-helpers';
+import {
+ API_ETH_MOCK_ADDRESS,
+ gasLimitRecommendations,
+ InterestRate,
+ ProtocolAction,
+} from '@aave/contract-helpers';
import { Trans } from '@lingui/macro';
import { BoxProps } from '@mui/material';
-import { OptimalRate } from 'paraswap-core';
-import { useTransactionHandler } from 'src/helpers/useTransactionHandler';
+import { useParaSwapTransactionHandler } from 'src/helpers/useParaSwapTransactionHandler';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
+import { SwapTransactionParams } from 'src/hooks/paraswap/common';
import { useRootStore } from 'src/store/root';
import { TxActionsWrapper } from '../TxActionsWrapper';
-export interface RepayActionProps extends BoxProps {
+interface CollateralRepayBaseProps extends BoxProps {
rateMode: InterestRate;
repayAmount: string;
repayWithAmount: string;
@@ -17,65 +22,79 @@ export interface RepayActionProps extends BoxProps {
isWrongNetwork: boolean;
customGasPrice?: string;
symbol: string;
- priceRoute: OptimalRate | null;
repayAllDebt: boolean;
useFlashLoan: boolean;
blocked: boolean;
- maxSlippage: number;
+ loading?: boolean;
+}
+
+// Used in poolSlice
+export interface CollateralRepayActionProps extends CollateralRepayBaseProps {
+ augustus: string;
+ swapCallData: string;
}
export const CollateralRepayActions = ({
repayAmount,
- repayWithAmount,
poolReserve,
fromAssetData,
isWrongNetwork,
sx,
symbol,
rateMode,
- priceRoute,
repayAllDebt,
useFlashLoan,
blocked,
- maxSlippage,
+ loading,
+ repayWithAmount,
+ buildTxFn,
...props
-}: RepayActionProps) => {
+}: CollateralRepayBaseProps & { buildTxFn: () => Promise }) => {
const paraswapRepayWithCollateral = useRootStore((state) => state.paraswapRepayWithCollateral);
const { approval, action, requiresApproval, loadingTxns, approvalTxState, mainTxState } =
- useTransactionHandler({
+ useParaSwapTransactionHandler({
handleGetTxns: async () => {
+ const route = await buildTxFn();
+ return paraswapRepayWithCollateral({
+ repayAllDebt,
+ repayAmount: route.outputAmount,
+ rateMode,
+ repayWithAmount: route.inputAmount,
+ fromAssetData,
+ poolReserve,
+ isWrongNetwork,
+ symbol,
+ useFlashLoan,
+ blocked,
+ swapCallData: route.swapCallData,
+ augustus: route.augustus,
+ });
+ },
+ handleGetApprovalTxns: async () => {
return paraswapRepayWithCollateral({
repayAllDebt,
repayAmount,
- maxSlippage,
rateMode,
repayWithAmount,
fromAssetData,
poolReserve,
isWrongNetwork,
symbol,
- priceRoute,
useFlashLoan,
blocked,
+ swapCallData: '0x',
+ augustus: API_ETH_MOCK_ADDRESS,
});
},
- skip: !repayAmount || parseFloat(repayAmount) === 0 || blocked,
- deps: [
- repayWithAmount,
- repayAmount,
- priceRoute,
- poolReserve.underlyingAsset,
- fromAssetData.underlyingAsset,
- repayAllDebt,
- useFlashLoan,
- ],
+ gasLimitRecommendation: gasLimitRecommendations[ProtocolAction.repayCollateral].limit,
+ skip: loading || !repayAmount || parseFloat(repayAmount) === 0 || blocked,
});
return (
Repay {symbol}}
actionInProgressText={Repaying {symbol}}
+ fetchingData={loading}
+ errorParams={{
+ loading: false,
+ disabled: blocked,
+ content: Repay {symbol},
+ handleClick: action,
+ }}
/>
);
};
diff --git a/src/components/transactions/Repay/CollateralRepayModalContent.tsx b/src/components/transactions/Repay/CollateralRepayModalContent.tsx
index 35f40899fe..b9cd6a1f0f 100644
--- a/src/components/transactions/Repay/CollateralRepayModalContent.tsx
+++ b/src/components/transactions/Repay/CollateralRepayModalContent.tsx
@@ -1,22 +1,22 @@
import { InterestRate } from '@aave/contract-helpers';
-import { USD_DECIMALS, valueToBigNumber } from '@aave/math-utils';
+import { valueToBigNumber } from '@aave/math-utils';
+import { ArrowDownIcon } from '@heroicons/react/outline';
import { Trans } from '@lingui/macro';
-import { Box, Typography } from '@mui/material';
+import { Box, SvgIcon, Typography } from '@mui/material';
import BigNumber from 'bignumber.js';
import { useRef, useState } from 'react';
-import { FormattedNumber } from 'src/components/primitives/FormattedNumber';
-import { Row } from 'src/components/primitives/Row';
-import StyledToggleButton from 'src/components/StyledToggleButton';
-import StyledToggleButtonGroup from 'src/components/StyledToggleButtonGroup';
+import { PriceImpactTooltip } from 'src/components/infoTooltips/PriceImpactTooltip';
import {
ComputedReserveData,
ComputedUserReserveData,
useAppDataContext,
} from 'src/hooks/app-data-provider/useAppDataProvider';
+import { SwapVariant } from 'src/hooks/paraswap/common';
+import { useCollateralRepaySwap } from 'src/hooks/paraswap/useCollateralRepaySwap';
import { useModalContext } from 'src/hooks/useModal';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
-import { useSwap } from 'src/hooks/useSwap';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
+import { ListSlippageButton } from 'src/modules/dashboard/lists/SlippageList';
import { calculateHFAfterRepay } from 'src/utils/hfUtils';
import { Asset, AssetInput } from '../AssetInput';
@@ -38,11 +38,12 @@ export function CollateralRepayModalContent({
userReserve,
isWrongNetwork,
}: ModalWrapperProps & { debtType: InterestRate }) {
- const { user, marketReferencePriceInUsd, reserves, userReserves } = useAppDataContext();
+ const { user, reserves, userReserves } = useAppDataContext();
const { gasLimit, txError, mainTxState } = useModalContext();
const { currentChainId, currentNetworkConfig } = useProtocolDataContext();
const { currentAccount } = useWeb3Context();
+ // List of tokens eligble to repay with, ordered by USD value
const repayTokens = user.userReservesData
.filter(
(userReserve) =>
@@ -52,69 +53,104 @@ export function CollateralRepayModalContent({
.map((userReserve) => ({
address: userReserve.underlyingAsset,
balance: userReserve.underlyingBalance,
+ balanceUSD: userReserve.underlyingBalanceUSD,
symbol: userReserve.reserve.symbol,
iconSymbol: userReserve.reserve.iconSymbol,
- aToken: true,
- }));
+ }))
+ .sort((a, b) => Number(b.balanceUSD) - Number(a.balanceUSD));
const [tokenToRepayWith, setTokenToRepayWith] = useState(repayTokens[0]);
+ const tokenToRepayWithBalance = tokenToRepayWith.balance || '0';
- const fromAssetData = reserves.find(
- (reserve) => reserve.underlyingAsset === tokenToRepayWith.address
- ) as ComputedReserveData;
-
- const repayWithUserReserve = userReserves.find(
- (userReserve) => userReserve.underlyingAsset === tokenToRepayWith.address
- ) as ComputedUserReserveData;
-
- const [_amount, setAmount] = useState('');
+ const [swapVariant, setSwapVariant] = useState('exactOut');
+ const [amount, setAmount] = useState('');
const [maxSlippage, setMaxSlippage] = useState('0.5');
const amountRef = useRef('');
+ const collateralReserveData = reserves.find(
+ (reserve) => reserve.underlyingAsset === tokenToRepayWith.address
+ ) as ComputedReserveData;
+
const debt =
debtType === InterestRate.Stable
? userReserve?.stableBorrows || '0'
: userReserve?.variableBorrows || '0';
const safeAmountToRepayAll = valueToBigNumber(debt).multipliedBy('1.0025');
- const isMaxSelected = _amount === '-1';
- const amount = isMaxSelected ? safeAmountToRepayAll.toString() : _amount;
- const usdValue = valueToBigNumber(amount).multipliedBy(poolReserve.priceInUSD);
+ const isMaxSelected = amount === '-1';
+ const repayAmount = isMaxSelected ? safeAmountToRepayAll.toString() : amount;
+ const repayAmountUsdValue = valueToBigNumber(repayAmount)
+ .multipliedBy(poolReserve.priceInUSD)
+ .toString();
+
+ // The slippage is factored into the collateral amount because when we swap for 'exactOut', positive slippage is applied on the collateral amount.
+ const collateralAmountRequiredToCoverDebt = safeAmountToRepayAll
+ .multipliedBy(poolReserve.priceInUSD)
+ .multipliedBy(100 + Number(maxSlippage))
+ .dividedBy(100)
+ .dividedBy(collateralReserveData.priceInUSD);
- const { priceRoute, inputAmountUSD, inputAmount, outputAmount, outputAmountUSD } = useSwap({
+ const swapIn = { ...collateralReserveData, amount: tokenToRepayWithBalance };
+ const swapOut = { ...poolReserve, amount: amountRef.current };
+ if (swapVariant === 'exactIn') {
+ swapIn.amount = tokenToRepayWithBalance;
+ swapOut.amount = '0';
+ }
+
+ const repayAllDebt =
+ isMaxSelected &&
+ valueToBigNumber(tokenToRepayWithBalance).gte(collateralAmountRequiredToCoverDebt);
+
+ const {
+ inputAmountUSD,
+ inputAmount,
+ outputAmount,
+ outputAmountUSD,
+ loading: routeLoading,
+ error,
+ buildTxFn,
+ } = useCollateralRepaySwap({
chainId: currentNetworkConfig.underlyingChainId || currentChainId,
- userId: currentAccount,
- variant: 'exactOut',
- swapIn: { ...fromAssetData, amount: '0' },
- swapOut: { ...poolReserve, amount: amountRef.current },
- max: isMaxSelected,
- skip: mainTxState.loading,
+ userAddress: currentAccount,
+ swapVariant: swapVariant,
+ swapIn,
+ swapOut,
+ max: repayAllDebt,
+ skip: mainTxState.loading || false,
+ maxSlippage: Number(maxSlippage),
});
- // Calculations to get the max repayable debt depending on the balance and value of the
- // selected collateral
- const maxCollateral = valueToBigNumber(tokenToRepayWith?.balance || 0).multipliedBy(
- fromAssetData.priceInMarketReferenceCurrency
- );
- const maxDebtThatCanBeRepaidWithSelectedCollateral = maxCollateral.dividedBy(
- poolReserve.priceInMarketReferenceCurrency
- );
- const maxRepayableDebt = BigNumber.min(
- maxDebtThatCanBeRepaidWithSelectedCollateral,
- safeAmountToRepayAll
- );
- const handleChange = (value: string) => {
+ const loadingSkeleton = routeLoading && inputAmountUSD === '0';
+
+ const handleRepayAmountChange = (value: string) => {
const maxSelected = value === '-1';
- amountRef.current = maxSelected ? maxRepayableDebt.toString(10) : value;
- setAmount(value);
+
+ if (
+ maxSelected &&
+ valueToBigNumber(tokenToRepayWithBalance).lt(collateralAmountRequiredToCoverDebt)
+ ) {
+ // The selected collateral amount is not enough to pay the full debt. We'll try to do a swap using the exact amount of collateral.
+ // The amount won't be known until we fetch the swap data, so we'll clear it out. Once the swap data is fetched, we'll set the amount.
+ amountRef.current = '';
+ setAmount('');
+ setSwapVariant('exactIn');
+ } else {
+ amountRef.current = maxSelected ? safeAmountToRepayAll.toString(10) : value;
+ setAmount(value);
+ setSwapVariant('exactOut');
+ }
};
+
// for v3 we need hf after withdraw collateral, because when removing collateral to repay
// debt, hf could go under 1 then it would fail. If that is the case then we need
// to use flashloan path
+ const repayWithUserReserve = userReserves.find(
+ (userReserve) => userReserve.underlyingAsset === tokenToRepayWith.address
+ ) as ComputedUserReserveData;
const { hfAfterSwap, hfEffectOfFromAmount } = calculateHFAfterRepay({
amountToReceiveAfterSwap: outputAmount,
amountToSwap: inputAmount,
- fromAssetData,
+ fromAssetData: collateralReserveData,
user,
toAssetData: poolReserve,
repayWithUserReserve,
@@ -134,24 +170,26 @@ export function CollateralRepayModalContent({
// a safe amount to repay all. When this happens amountAfterRepay would be < 0 and
// this would show as certain amount left to repay when we are actually repaying all debt
const amountAfterRepay = valueToBigNumber(debt).minus(BigNumber.min(outputAmount, debt));
- const displayAmountAfterRepayInUsd = amountAfterRepay
- .multipliedBy(poolReserve.formattedPriceInMarketReferenceCurrency)
- .multipliedBy(marketReferencePriceInUsd)
- .shiftedBy(-USD_DECIMALS);
+ const displayAmountAfterRepayInUsd = amountAfterRepay.multipliedBy(poolReserve.priceInUSD);
+ const collateralAmountAfterRepay = tokenToRepayWithBalance
+ ? valueToBigNumber(tokenToRepayWithBalance).minus(inputAmount)
+ : valueToBigNumber('0');
+ const collateralAmountAfterRepayUSD = collateralAmountAfterRepay.multipliedBy(
+ collateralReserveData.priceInUSD
+ );
// calculate impact based on $ difference
- const priceImpact =
+ let priceImpact =
outputAmountUSD && outputAmountUSD !== '0'
- ? new BigNumber(1)
- .minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD))
- .toString(10)
+ ? new BigNumber(1).minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD)).toFixed(2)
: '0';
+ if (priceImpact === '-0.00') {
+ priceImpact = '0.00';
+ }
let blockingError: ErrorType | undefined = undefined;
- const tokenToRepayWithUsdValue = valueToBigNumber(tokenToRepayWith?.balance || '0').multipliedBy(
- fromAssetData.priceInUSD
- );
- if (Number(usdValue) > Number(tokenToRepayWithUsdValue.toString(10))) {
+
+ if (valueToBigNumber(tokenToRepayWithBalance).lt(inputAmount)) {
blockingError = ErrorType.NOT_ENOUGH_COLLATERAL_TO_REPAY_WITH;
} else if (disableFlashLoan) {
blockingError = ErrorType.FLASH_LOAN_NOT_AVAILABLE;
@@ -176,18 +214,17 @@ export function CollateralRepayModalContent({
if (mainTxState.success)
return (
repaid}
- amount={amountRef.current}
+ action={Repaid}
+ amount={swapVariant === 'exactIn' ? outputAmount : repayAmount}
symbol={poolReserve.symbol}
/>
);
-
return (
<>
Debt amount to repay}
+ inputTitle={Expected amount to repay}
balanceText={Borrow balance}
/>
+
+
+
+
+
+
+
Collateral amount to repay with}
+ onChange={handleRepayAmountChange}
+ inputTitle={Collateral to repay with}
balanceText={Borrow balance}
+ maxValue={tokenToRepayWithBalance}
+ loading={loadingSkeleton}
disableInput
/>
+ {error && !loadingSkeleton && (
+
+ {error}
+
+ )}
{blockingError !== undefined && (
{handleBlocked()}
)}
-
+ }
>
- Price impact} captionVariant="subheader1">
-
-
- Minimum received} captionVariant="subheader1" sx={{ mt: 4 }}>
-
-
-
- Max slippage rate
-
- setMaxSlippage(value)}
- exclusive
- >
-
- 0.1%
-
-
- 0.5%
-
-
- 1%
-
-
-
-
+
Remaining debt}
+ description={Borrow balance after repay}
futureValue={amountAfterRepay.toString()}
futureValueUSD={displayAmountAfterRepayInUsd.toString()}
symbol={symbol}
+ tokenIcon={poolReserve.iconSymbol}
+ loading={loadingSkeleton}
+ hideSymbolSuffix
/>
- Collateral balance after repay}
+ futureValue={collateralAmountAfterRepay.toString()}
+ futureValueUSD={collateralAmountAfterRepayUSD.toString()}
+ symbol={tokenToRepayWith.symbol}
+ tokenIcon={tokenToRepayWith.iconSymbol}
+ loading={loadingSkeleton}
+ hideSymbolSuffix
/>
@@ -270,17 +306,17 @@ export function CollateralRepayModalContent({
>
);
diff --git a/src/components/transactions/Repay/RepayActions.tsx b/src/components/transactions/Repay/RepayActions.tsx
index 60016affba..84be4acee8 100644
--- a/src/components/transactions/Repay/RepayActions.tsx
+++ b/src/components/transactions/Repay/RepayActions.tsx
@@ -1,12 +1,9 @@
-import { InterestRate } from '@aave/contract-helpers';
+import { InterestRate, ProtocolAction } from '@aave/contract-helpers';
import { Trans } from '@lingui/macro';
import { BoxProps } from '@mui/material';
-import { utils } from 'ethers';
import { useTransactionHandler } from 'src/helpers/useTransactionHandler';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
-import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
import { useRootStore } from 'src/store/root';
-import { permitByChainAndToken } from 'src/ui-config/permitConfig';
import { TxActionsWrapper } from '../TxActionsWrapper';
@@ -34,15 +31,13 @@ export const RepayActions = ({
blocked,
...props
}: RepayActionProps) => {
- const { currentChainId: chainId, currentMarketData } = useProtocolDataContext();
- const repay = useRootStore((state) => state.repay);
- const repayWithPermit = useRootStore((state) => state.repayWithPermit);
+ const { repay, repayWithPermit, tryPermit } = useRootStore();
+ const usingPermit = tryPermit(poolAddress);
const { approval, action, requiresApproval, loadingTxns, approvalTxState, mainTxState } =
useTransactionHandler({
- // move tryPermit to store
- tryPermit:
- currentMarketData.v3 && permitByChainAndToken[chainId]?.[utils.getAddress(poolAddress)],
+ tryPermit: usingPermit,
+ permitAction: ProtocolAction.repayWithPermit,
handleGetTxns: async () => {
return repay({
amountToRepay,
@@ -88,6 +83,7 @@ export const RepayActions = ({
handleApproval={() => approval([{ amount: amountToRepay, underlyingAsset: poolAddress }])}
actionText={Repay {symbol}}
actionInProgressText={Repaying {symbol}}
+ tryPermit={usingPermit}
/>
);
};
diff --git a/src/components/transactions/Repay/RepayModal.tsx b/src/components/transactions/Repay/RepayModal.tsx
index 782cc23e7d..5ebaf5f3db 100644
--- a/src/components/transactions/Repay/RepayModal.tsx
+++ b/src/components/transactions/Repay/RepayModal.tsx
@@ -16,6 +16,7 @@ export const RepayModal = () => {
const { type, close, args, mainTxState } = useModalContext() as ModalContextType<{
underlyingAsset: string;
currentRateMode: InterestRate;
+ isFrozen: boolean;
}>;
const { userReserves } = useAppDataContext();
const { currentMarketData } = useProtocolDataContext();
@@ -25,12 +26,14 @@ export const RepayModal = () => {
// 1. on chains with paraswap deployed
// 2. when you have a different supplied(not necessarily collateral) asset then the one your debt is in
// For repaying your debt with the same assets aToken you can use repayWithAToken on aave protocol v3
+ // 3. the supplied asset is not frozen
const collateralRepayPossible =
isFeatureEnabled.collateralRepay(currentMarketData) &&
userReserves.some(
(userReserve) =>
userReserve.scaledATokenBalance !== '0' &&
- userReserve.underlyingAsset !== args.underlyingAsset
+ userReserve.underlyingAsset !== args.underlyingAsset &&
+ !args.isFrozen
);
return (
diff --git a/src/components/transactions/Repay/RepayModalContent.tsx b/src/components/transactions/Repay/RepayModalContent.tsx
index 01f0c27e5f..58abfc4152 100644
--- a/src/components/transactions/Repay/RepayModalContent.tsx
+++ b/src/components/transactions/Repay/RepayModalContent.tsx
@@ -171,13 +171,12 @@ export const RepayModalContent = ({
const amountAfterRepay = valueToBigNumber(debt)
.minus(amount || '0')
.toString(10);
- const displayAmountAfterRepay = BigNumber.min(amountAfterRepay, maxAmountToRepay);
- const displayAmountAfterRepayInUsd = displayAmountAfterRepay
+ const amountAfterRepayInUsd = new BigNumber(amountAfterRepay)
.multipliedBy(poolReserve.formattedPriceInMarketReferenceCurrency)
.multipliedBy(marketReferencePriceInUsd)
.shiftedBy(-USD_DECIMALS);
- const maxRepayWithDustRemaining = isMaxSelected && displayAmountAfterRepayInUsd.toNumber() > 0;
+ const maxRepayWithDustRemaining = isMaxSelected && amountAfterRepayInUsd.toNumber() > 0;
// health factor calculations
// we use usd values instead of MarketreferenceCurrency so it has same precision
@@ -236,7 +235,7 @@ export const RepayModalContent = ({
Remaining debt}
futureValue={amountAfterRepay}
- futureValueUSD={displayAmountAfterRepayInUsd.toString(10)}
+ futureValueUSD={amountAfterRepayInUsd.toString(10)}
value={debt}
valueUSD={debtUSD.toString()}
symbol={
diff --git a/src/components/transactions/Repay/RepayTypeSelector.tsx b/src/components/transactions/Repay/RepayTypeSelector.tsx
index fb573c6f24..97981ea306 100644
--- a/src/components/transactions/Repay/RepayTypeSelector.tsx
+++ b/src/components/transactions/Repay/RepayTypeSelector.tsx
@@ -28,7 +28,7 @@ export function RepayTypeSelector({
value={repayType}
exclusive
onChange={(_, value) => setRepayType(value)}
- sx={{ width: '100%' }}
+ sx={{ width: '100%', height: '36px', p: '2px' }}
>
diff --git a/src/components/transactions/Supply/SupplyActions.tsx b/src/components/transactions/Supply/SupplyActions.tsx
index cf1df15c67..66caf649f9 100644
--- a/src/components/transactions/Supply/SupplyActions.tsx
+++ b/src/components/transactions/Supply/SupplyActions.tsx
@@ -1,10 +1,8 @@
+import { ProtocolAction } from '@aave/contract-helpers';
import { Trans } from '@lingui/macro';
import { BoxProps } from '@mui/material';
-import { utils } from 'ethers';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
-import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
import { useRootStore } from 'src/store/root';
-import { permitByChainAndToken } from 'src/ui-config/permitConfig';
import { useTransactionHandler } from '../../../helpers/useTransactionHandler';
import { TxActionsWrapper } from '../TxActionsWrapper';
@@ -28,15 +26,13 @@ export const SupplyActions = ({
blocked,
...props
}: SupplyActionProps) => {
- const { currentChainId: chainId, currentMarketData } = useProtocolDataContext();
- const supply = useRootStore((state) => state.supply);
- const supplyWithPermit = useRootStore((state) => state.supplyWithPermit);
+ const { supply, supplyWithPermit, tryPermit } = useRootStore();
+ const usingPermit = tryPermit(poolAddress);
const { approval, action, requiresApproval, loadingTxns, approvalTxState, mainTxState } =
useTransactionHandler({
- // TODO: move tryPermit
- tryPermit:
- currentMarketData.v3 && permitByChainAndToken[chainId]?.[utils.getAddress(poolAddress)],
+ tryPermit: usingPermit,
+ permitAction: ProtocolAction.supplyWithPermit,
handleGetTxns: async () => {
return supply({
amountToSupply,
@@ -66,12 +62,14 @@ export const SupplyActions = ({
isWrongNetwork={isWrongNetwork}
requiresAmount
amount={amountToSupply}
+ symbol={symbol}
preparingTransactions={loadingTxns}
actionText={Supply {symbol}}
actionInProgressText={Supplying {symbol}}
handleApproval={() => approval([{ amount: amountToSupply, underlyingAsset: poolAddress }])}
handleAction={action}
requiresApproval={requiresApproval}
+ tryPermit={usingPermit}
sx={sx}
{...props}
/>
diff --git a/src/components/transactions/Swap/SwapActions.tsx b/src/components/transactions/Swap/SwapActions.tsx
index e12c716ec0..6f30b187c8 100644
--- a/src/components/transactions/Swap/SwapActions.tsx
+++ b/src/components/transactions/Swap/SwapActions.tsx
@@ -1,13 +1,18 @@
+import {
+ API_ETH_MOCK_ADDRESS,
+ gasLimitRecommendations,
+ ProtocolAction,
+} from '@aave/contract-helpers';
import { Trans } from '@lingui/macro';
import { BoxProps } from '@mui/material';
-import { OptimalRate } from 'paraswap-core';
+import { useParaSwapTransactionHandler } from 'src/helpers/useParaSwapTransactionHandler';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
+import { SwapTransactionParams } from 'src/hooks/paraswap/common';
import { useRootStore } from 'src/store/root';
-import { useTransactionHandler } from '../../../helpers/useTransactionHandler';
import { TxActionsWrapper } from '../TxActionsWrapper';
-export interface SwapActionProps extends BoxProps {
+interface SwapBaseProps extends BoxProps {
amountToSwap: string;
amountToReceive: string;
poolReserve: ComputedReserveData;
@@ -16,9 +21,14 @@ export interface SwapActionProps extends BoxProps {
customGasPrice?: string;
symbol: string;
blocked: boolean;
- priceRoute: OptimalRate | null;
isMaxSelected: boolean;
useFlashLoan: boolean;
+ loading?: boolean;
+}
+
+export interface SwapActionProps extends SwapBaseProps {
+ swapCallData: string;
+ augustus: string;
}
export const SwapActions = ({
@@ -28,18 +38,35 @@ export const SwapActions = ({
sx,
poolReserve,
targetReserve,
- priceRoute,
isMaxSelected,
useFlashLoan,
+ loading,
symbol,
blocked,
+ buildTxFn,
...props
-}: SwapActionProps) => {
+}: SwapBaseProps & { buildTxFn: () => Promise }) => {
const swapCollateral = useRootStore((state) => state.swapCollateral);
const { approval, action, requiresApproval, approvalTxState, mainTxState, loadingTxns } =
- useTransactionHandler({
+ useParaSwapTransactionHandler({
handleGetTxns: async () => {
+ const route = await buildTxFn();
+ return swapCollateral({
+ amountToSwap: route.inputAmount,
+ amountToReceive: route.outputAmount,
+ poolReserve,
+ targetReserve,
+ isWrongNetwork,
+ symbol,
+ blocked,
+ isMaxSelected,
+ useFlashLoan,
+ swapCallData: route.swapCallData,
+ augustus: route.augustus,
+ });
+ },
+ handleGetApprovalTxns: async () => {
return swapCollateral({
amountToSwap,
amountToReceive,
@@ -48,21 +75,14 @@ export const SwapActions = ({
isWrongNetwork,
symbol,
blocked,
- priceRoute,
isMaxSelected,
useFlashLoan,
+ swapCallData: '0x',
+ augustus: API_ETH_MOCK_ADDRESS,
});
},
- skip: !priceRoute || !amountToSwap || parseFloat(amountToSwap) === 0,
- deps: [
- amountToSwap,
- amountToReceive,
- priceRoute,
- poolReserve.underlyingAsset,
- targetReserve.underlyingAsset,
- isMaxSelected,
- useFlashLoan,
- ],
+ gasLimitRecommendation: gasLimitRecommendations[ProtocolAction.swapCollateral].limit,
+ skip: loading || !amountToSwap || parseFloat(amountToSwap) === 0,
});
return (
@@ -74,13 +94,18 @@ export const SwapActions = ({
handleAction={action}
requiresAmount
amount={amountToSwap}
- handleApproval={() =>
- approval([{ amount: amountToSwap, underlyingAsset: poolReserve.aTokenAddress }])
- }
+ handleApproval={() => approval()}
requiresApproval={requiresApproval}
actionText={Swap}
actionInProgressText={Swapping}
sx={sx}
+ fetchingData={loading}
+ errorParams={{
+ loading: false,
+ disabled: blocked,
+ content: Swap,
+ handleClick: action,
+ }}
{...props}
/>
);
diff --git a/src/components/transactions/Swap/SwapModalContent.tsx b/src/components/transactions/Swap/SwapModalContent.tsx
index fe628778ed..b7516d4ca9 100644
--- a/src/components/transactions/Swap/SwapModalContent.tsx
+++ b/src/components/transactions/Swap/SwapModalContent.tsx
@@ -1,34 +1,29 @@
+import { SwitchVerticalIcon } from '@heroicons/react/outline';
import { Trans } from '@lingui/macro';
-import { Box, Typography } from '@mui/material';
+import { Box, SvgIcon, Typography } from '@mui/material';
import BigNumber from 'bignumber.js';
import React, { useRef, useState } from 'react';
-import { FormattedNumber } from 'src/components/primitives/FormattedNumber';
-import { Row } from 'src/components/primitives/Row';
-import StyledToggleButton from 'src/components/StyledToggleButton';
-import StyledToggleButtonGroup from 'src/components/StyledToggleButtonGroup';
+import { PriceImpactTooltip } from 'src/components/infoTooltips/PriceImpactTooltip';
import { Asset, AssetInput } from 'src/components/transactions/AssetInput';
import { GasEstimationError } from 'src/components/transactions/FlowCommons/GasEstimationError';
-import {
- DetailsHFLine,
- DetailsIncentivesLine,
- DetailsNumberLine,
- TxModalDetails,
-} from 'src/components/transactions/FlowCommons/TxModalDetails';
+import { TxModalDetails } from 'src/components/transactions/FlowCommons/TxModalDetails';
+import { useCollateralSwap } from 'src/hooks/paraswap/useCollateralSwap';
import { useModalContext } from 'src/hooks/useModal';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
-import { useSwap } from 'src/hooks/useSwap';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
+import { ListSlippageButton } from 'src/modules/dashboard/lists/SlippageList';
import { remainingCap } from 'src/utils/getMaxAmountAvailableToSupply';
import { calculateHFAfterSwap } from 'src/utils/hfUtils';
import {
- ComputedReserveData,
+ ComputedUserReserveData,
useAppDataContext,
} from '../../../hooks/app-data-provider/useAppDataProvider';
import { ModalWrapperProps } from '../FlowCommons/ModalWrapper';
import { TxSuccessView } from '../FlowCommons/Success';
import { ErrorType, flashLoanNotAvailable, useFlashloan } from '../utils';
import { SwapActions } from './SwapActions';
+import { SwapModalDetails } from './SwapModalDetails';
export type SupplyProps = {
underlyingAsset: string;
@@ -58,9 +53,9 @@ export const SwapModalContent = ({
const [targetReserve, setTargetReserve] = useState(swapTargets[0]);
const [maxSlippage, setMaxSlippage] = useState('0.1');
- const swapTarget = reserves.find(
+ const swapTarget = user.userReservesData.find(
(r) => r.underlyingAsset === targetReserve.address
- ) as ComputedReserveData;
+ ) as ComputedUserReserveData;
// a user can never swap more then 100% of available as the txn would fail on withdraw step
const maxAmountToSwap = BigNumber.min(
@@ -68,26 +63,30 @@ export const SwapModalContent = ({
new BigNumber(poolReserve.availableLiquidity).multipliedBy(0.99)
).toString(10);
- const remainingCapBn = remainingCap(swapTarget);
+ const remainingCapBn = remainingCap(swapTarget.reserve);
const isMaxSelected = _amount === '-1';
const amount = isMaxSelected ? maxAmountToSwap : _amount;
- const { priceRoute, inputAmountUSD, inputAmount, outputAmount, outputAmountUSD, error } = useSwap(
- {
- chainId: currentNetworkConfig.underlyingChainId || currentChainId,
- userId: currentAccount,
- variant: 'exactIn',
- swapIn: { ...poolReserve, amount: amountRef.current },
- swapOut: { ...swapTarget, amount: '0' },
- max: isMaxSelected,
- skip: supplyTxState.loading,
- }
- );
+ const {
+ inputAmountUSD,
+ inputAmount,
+ outputAmount,
+ outputAmountUSD,
+ error,
+ loading: routeLoading,
+ buildTxFn,
+ } = useCollateralSwap({
+ chainId: currentNetworkConfig.underlyingChainId || currentChainId,
+ userAddress: currentAccount,
+ swapIn: { ...poolReserve, amount: amountRef.current },
+ swapOut: { ...swapTarget.reserve, amount: '0' },
+ max: isMaxSelected,
+ skip: supplyTxState.loading || false,
+ maxSlippage: Number(maxSlippage),
+ });
- const minimumReceived = new BigNumber(outputAmount || '0')
- .multipliedBy(new BigNumber(100).minus(maxSlippage).dividedBy(100))
- .toString(10);
+ const loadingSkeleton = routeLoading && outputAmountUSD === '0';
const handleChange = (value: string) => {
const maxSelected = value === '-1';
@@ -100,8 +99,8 @@ export const SwapModalContent = ({
fromAssetData: poolReserve,
fromAssetUserData: userReserve,
user,
- toAmountAfterSlippage: minimumReceived,
- toAssetData: swapTarget,
+ toAmountAfterSlippage: outputAmount,
+ toAssetData: swapTarget.reserve,
});
// if the hf would drop below 1 from the hf effect a flashloan should be used to mitigate liquidation
@@ -165,9 +164,7 @@ export const SwapModalContent = ({
// calculate impact based on $ difference
const priceImpact =
outputAmountUSD && outputAmountUSD !== '0'
- ? new BigNumber(1)
- .minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD))
- .toString(10)
+ ? new BigNumber(1).minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD)).toFixed(2)
: '0';
return (
@@ -189,87 +186,55 @@ export const SwapModalContent = ({
},
]}
maxValue={maxAmountToSwap}
- isMaxSelected={isMaxSelected}
+ inputTitle={Supplied asset amount}
balanceText={Supply balance}
+ isMaxSelected={isMaxSelected}
/>
+
+
+
+
+
+
+
Swap to}
balanceText={Supply balance}
disableInput
+ loading={loadingSkeleton}
/>
-
- Price impact} captionVariant="subheader1">
-
-
- Minimum received} captionVariant="subheader1" sx={{ mt: 4 }}>
-
-
-
- Max slippage rate
-
- setMaxSlippage(value)}
- exclusive
- >
-
- 0.1%
-
-
- 0.5%
-
-
- 1%
-
-
-
- {blockingError !== undefined && (
+ {error && !loadingSkeleton && (
- {handleBlocked()}
+ {error}
)}
- {error && (
+ {!error && blockingError !== undefined && (
- {error}
+ {handleBlocked()}
)}
-
- Supply apy}
- value={poolReserve.supplyAPY}
- futureValue={swapTarget.supplyAPY}
- percent
- />
-
+ }
+ >
+
- {showHealthFactor && (
-
- )}
{txError && }
@@ -278,13 +243,14 @@ export const SwapModalContent = ({
isMaxSelected={isMaxSelected}
poolReserve={poolReserve}
amountToSwap={inputAmount}
- amountToReceive={minimumReceived}
+ amountToReceive={outputAmount}
isWrongNetwork={isWrongNetwork}
- targetReserve={swapTarget}
+ targetReserve={swapTarget.reserve}
symbol={poolReserve.symbol}
- blocked={blockingError !== undefined}
- priceRoute={priceRoute}
+ blocked={blockingError !== undefined || error !== ''}
useFlashLoan={shouldUseFlashloan}
+ loading={routeLoading}
+ buildTxFn={buildTxFn}
/>
>
);
diff --git a/src/components/transactions/Swap/SwapModalDetails.tsx b/src/components/transactions/Swap/SwapModalDetails.tsx
new file mode 100644
index 0000000000..f55fbb9363
--- /dev/null
+++ b/src/components/transactions/Swap/SwapModalDetails.tsx
@@ -0,0 +1,211 @@
+import { valueToBigNumber } from '@aave/math-utils';
+import { ArrowNarrowRightIcon } from '@heroicons/react/outline';
+import { Trans } from '@lingui/macro';
+import { Box, Skeleton, SvgIcon, Typography, useTheme } from '@mui/material';
+import React from 'react';
+import { FormattedNumber } from 'src/components/primitives/FormattedNumber';
+import { Row } from 'src/components/primitives/Row';
+import { TokenIcon } from 'src/components/primitives/TokenIcon';
+import {
+ DetailsHFLine,
+ DetailsIncentivesLine,
+ DetailsNumberLine,
+} from 'src/components/transactions/FlowCommons/TxModalDetails';
+
+import { ComputedUserReserveData } from '../../../hooks/app-data-provider/useAppDataProvider';
+
+export type SupplyModalDetailsProps = {
+ showHealthFactor: boolean;
+ healthFactor: string;
+ healthFactorAfterSwap: string;
+ swapSource: ComputedUserReserveData;
+ swapTarget: ComputedUserReserveData;
+ toAmount: string;
+ fromAmount: string;
+ loading: boolean;
+};
+
+export const SwapModalDetails = ({
+ showHealthFactor,
+ healthFactor,
+ healthFactorAfterSwap,
+ swapSource,
+ swapTarget,
+ toAmount,
+ fromAmount,
+ loading,
+}: SupplyModalDetailsProps) => {
+ const { palette } = useTheme();
+
+ const parseUsageString = (usage: boolean) => {
+ if (usage) {
+ return (
+
+ Yes
+
+ );
+ } else {
+ return (
+
+ No
+
+ );
+ }
+ };
+
+ const sourceAmountAfterSwap = valueToBigNumber(swapSource.underlyingBalance).minus(
+ valueToBigNumber(fromAmount)
+ );
+
+ const targetAmountAfterSwap = valueToBigNumber(swapTarget.underlyingBalance).plus(
+ valueToBigNumber(toAmount)
+ );
+
+ const skeleton: JSX.Element = (
+ <>
+
+
+ >
+ );
+
+ return (
+ <>
+ {healthFactorAfterSwap && (
+
+ )}
+ Supply apy}
+ value={swapSource.reserve.supplyAPY}
+ futureValue={swapTarget.reserve.supplyAPY}
+ percent
+ loading={loading}
+ />
+ Can be collateral} captionVariant="description" mb={4}>
+
+ {loading ? (
+
+ ) : (
+ <>
+ {parseUsageString(swapSource.reserve.usageAsCollateralEnabled)}
+
+
+
+
+
+ {parseUsageString(swapTarget.reserve.usageAsCollateralEnabled)}
+ >
+ )}
+
+
+
+ Liquidation threshold}
+ value={swapSource.reserve.formattedReserveLiquidationThreshold}
+ futureValue={swapTarget.reserve.formattedReserveLiquidationThreshold}
+ percent
+ visibleDecimals={0}
+ loading={loading}
+ />
+
+ Supply balance after swap}
+ captionVariant="description"
+ mb={4}
+ align="flex-start"
+ >
+
+
+ {loading ? (
+ skeleton
+ ) : (
+ <>
+
+
+
+
+
+ >
+ )}
+
+
+
+ {loading ? (
+ skeleton
+ ) : (
+ <>
+
+
+
+
+
+ >
+ )}
+
+
+
+ >
+ );
+};
diff --git a/src/components/transactions/TxActionsWrapper.tsx b/src/components/transactions/TxActionsWrapper.tsx
index 26c3f0b846..fd117d2869 100644
--- a/src/components/transactions/TxActionsWrapper.tsx
+++ b/src/components/transactions/TxActionsWrapper.tsx
@@ -1,12 +1,13 @@
+import { CheckIcon } from '@heroicons/react/solid';
import { Trans } from '@lingui/macro';
-import { Box, BoxProps, Button, CircularProgress, Typography } from '@mui/material';
+import { Box, BoxProps, Button, CircularProgress, SvgIcon, Typography } from '@mui/material';
import isEmpty from 'lodash/isEmpty';
import { ReactNode } from 'react';
import { TxStateType, useModalContext } from 'src/hooks/useModal';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import { TxAction } from 'src/ui-config/errorMapping';
-import { LeftHelperText } from './FlowCommons/LeftHelperText';
+import { ApprovalTooltip } from '../infoTooltips/ApprovalTooltip';
import { RightHelperText } from './FlowCommons/RightHelperText';
interface TxActionsWrapperProps extends BoxProps {
@@ -23,6 +24,14 @@ interface TxActionsWrapperProps extends BoxProps {
requiresApproval: boolean;
symbol?: string;
blocked?: boolean;
+ fetchingData?: boolean;
+ errorParams?: {
+ loading: boolean;
+ disabled: boolean;
+ content: ReactNode;
+ handleClick: () => Promise;
+ };
+ tryPermit?: boolean;
}
export const TxActionsWrapper = ({
@@ -40,22 +49,30 @@ export const TxActionsWrapper = ({
sx,
symbol,
blocked,
+ fetchingData = false,
+ errorParams,
+ tryPermit,
...rest
}: TxActionsWrapperProps) => {
- const { txError, retryWithApproval } = useModalContext();
+ const { txError } = useModalContext();
const { watchModeOnlyAddress } = useWeb3Context();
const hasApprovalError =
- requiresApproval && txError && txError.txAction === TxAction.APPROVAL && txError.actionBlocked;
+ requiresApproval && txError?.txAction === TxAction.APPROVAL && txError?.actionBlocked;
const isAmountMissing = requiresAmount && requiresAmount && Number(amount) === 0;
function getMainParams() {
if (blocked) return { disabled: true, content: actionText };
- if (txError && txError.txAction === TxAction.GAS_ESTIMATION && txError.actionBlocked)
- return { loading: false, disabled: true, content: actionText };
- if (txError && txError.txAction === TxAction.MAIN_ACTION && txError.actionBlocked)
+ if (
+ (txError?.txAction === TxAction.GAS_ESTIMATION ||
+ txError?.txAction === TxAction.MAIN_ACTION) &&
+ txError?.actionBlocked
+ ) {
+ if (errorParams) return errorParams;
return { loading: false, disabled: true, content: actionText };
+ }
if (isWrongNetwork) return { disabled: true, content: Wrong Network };
+ if (fetchingData) return { disabled: true, content: Fetching data... };
if (isAmountMissing) return { disabled: true, content: Enter an amount };
if (preparingTransactions || isEmpty(mainTxState)) return { disabled: true, loading: true };
// if (hasApprovalError && handleRetry)
@@ -78,21 +95,40 @@ export const TxActionsWrapper = ({
return null;
if (approvalTxState?.loading)
return { loading: true, disabled: true, content: Approving {symbol}... };
- if (approvalTxState?.success) return { disabled: true, content: Approved };
- if (retryWithApproval)
- return { content: Retry with approval, handleClick: handleApproval };
- return { content: Approve to continue, handleClick: handleApproval };
+ if (approvalTxState?.success)
+ return {
+ disabled: true,
+ content: (
+ <>
+ Approve Confirmed
+
+
+
+ >
+ ),
+ };
+
+ return {
+ content: (
+ Approve {symbol} to continue}
+ />
+ ),
+ handleClick: handleApproval,
+ };
}
const { content, disabled, loading, handleClick } = getMainParams();
const approvalParams = getApprovalParams();
-
return (
{requiresApproval && !watchModeOnlyAddress && (
-
-
-
+
+
)}
@@ -100,7 +136,7 @@ export const TxActionsWrapper = ({
+ }
+ variant="secondary14"
+ />
+ }
+ disabled={false}
+ data-cy={`slippageButton_${selectedSlippage}`}
+ sx={{ mt: 6 }}
+ />
+
+
+ >
+ );
+};
diff --git a/src/static-build/ipfsFiles.json b/src/static-build/ipfsFiles.json
index 80c7c960b5..f863f0273d 100644
--- a/src/static-build/ipfsFiles.json
+++ b/src/static-build/ipfsFiles.json
@@ -1880,6 +1880,32 @@
"ipfsHash": "QmNXsuCbJNvfJBiRHg9P9snhCeWXZ9bAPVzvHPG7LBggUP",
"originalHash": "0x02e04de8258c1dca9c4c6099d8ac2142f1f2833bad5a7ca4154a12aa8f4dd548",
"id": 129
+ },
+ {
+ "title": "Set LDO, stMATIC, MaticX and SD Emission_Admin for Polygon v3 Liquidity Pool",
+ "author": "Llamax - Matthew Graham & defijesus",
+ "discussion": "https://governance.aave.com/t/arc-stmatic-maticx-emission-admin-for-polygon-v3-liquidity-pool/10632",
+ "shortDescription": "Enable Lido Commununity, Stader Labs and Polygon Foundation to distribute rewards across the Polygon v3 Liquidity Pool",
+ "created": "2022-12-06T00:00:00.000Z",
+ "preview": "# Summary\n\nAssign the Emission_Admin role for the LDO, stMATIC, …",
+ "basename": "STMATIC-MATICX-LDO-SD-EMISSION-ADMIN-UPDATE-AAVE-V3-POLYGON",
+ "description": "\n\n# Summary\n\nAssign the Emission_Admin role for the LDO, stMATIC, MaticX and SD tokens on the Polygon v3 deployment. \n\n# Abstract\n\nThe following teams seek to distribute rewards across the Polygon v3 Liquidity Pool:\n\n* LDO by the Liquidity Mining Committee to support the adoption of stMATIC\n* SD by Stader Labs to support the adoption of MaticX\n* stMATIC & MaticX by Polygon Foundation to adoption of staked MATIC receipt tokens \n\nIn order to achieve this, the EmissionManager contract needs to assign an owner to the Emission_Admin permission allowing LDO, SD, stMATIC, and MaticX rewards to be distributed.\n\n# Motivation\n\nThe motivation of the proposal is to enable rewards to be distributed on the Polygon v3 Liquidity Pool.\n\nThe Lido Liquidity Mining Committee determines the emission rate and duration at which LDO rewards are offered. Standard practice is for the council to meet and determine the next 30 days of LDO rewards on a rolling basis. This means each month, the committee will determine if to extend the LDO rewards, or change the amount of LDO being offered across the Polygon v3 Liquidity Pool.\n\nThe Stader Labs team will determine the emission rate and duration SD rewards are offered. This will likely be influenced by the Aave DAO’s ability to adjust the wMATIC and MaticX risk parameters that enable users to generate a return from leverage the MaticX / wMATIC loop.\n\nThe Polygon Foundation team will determine the emission rate and duration at which stMATIC and MaticX rewards are offered. This will likely be influenced by Aave DAO’s ability to adjust the wMATIC, stMATIC and MaticX risk parameters that enable users to generate a return from leverage the stMATIC / wMATIC and MaticX/wMATIC loop.\n\nThe Emission_Admin is not limited to a specified Reserve and is linked to the token being distributed across the Liquidity Pool. The EmissionManager determines the Emission_Admin. The Emission_Admin can distribute said token anywhere across the Aave v3 Polygon Liquidity Pool.\n\nThe respective governance forum discussion is linked below:\n\n* [stMATIC & MaticX Emission Admin for Polygon v3 Liquidity Pool](https://governance.aave.com/t/arc-stmatic-maticx-emission-admin-for-polygon-v3-liquidity-pool/10632)\n* [LDO Emission Admin for Polygon v3 Liquidity Pool](https://governance.aave.com/t/arc-ldo-emission-admin-for-polygon-v3-liquidity-pool/10575)\n* [SD Emission Admin for Polygon v3 Liquidity Pool](https://governance.aave.com/t/arc-sd-emission-admin-for-polygon-v3-liquidity-pool/10658)\n\n# Specification\n\nThis proposal assigns the Emission_Admin using the setEmissionAdmin(address reward, address admin) function.\n\nLDO Address Reward: [matic:0xC3C7d422809852031b44ab29EEC9F1EfF2A58756](https://polygonscan.com/address/0xC3C7d422809852031b44ab29EEC9F1EfF2A58756)\nLDO Address Admin: [matic:0x87D93d9B2C672bf9c9642d853a8682546a5012B5](https://polygonscan.com/address/0x87D93d9B2C672bf9c9642d853a8682546a5012B5)\n\nSD Address Reward: [matic:0x1d734A02eF1e1f5886e66b0673b71Af5B53ffA94](https://polygonscan.com/address/0x1d734A02eF1e1f5886e66b0673b71Af5B53ffA94)\nSD Address Admin: [matic:0x51358004cFe135E64453d7F6a0dC433CAba09A2a](https://polygonscan.com/address/0x51358004cFe135E64453d7F6a0dC433CAba09A2a)\n\nstMATIC Address Reward: [matic:0x3A58a54C066FdC0f2D55FC9C89F0415C92eBf3C4](https://polygonscan.com/address/0x3A58a54C066FdC0f2D55FC9C89F0415C92eBf3C4)\nstMATIC Address Admin: [matic:0x0c54a0BCCF5079478a144dBae1AFcb4FEdf7b263](https://polygonscan.com/address/0x0c54a0BCCF5079478a144dBae1AFcb4FEdf7b263)\n\nMaticX Address Reward: [matic:0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6](https://polygonscan.com/address/0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6)\nMaticX Address Admin: [matic:0x0c54a0BCCF5079478a144dBae1AFcb4FEdf7b263](https://polygonscan.com/address/0x0c54a0bccf5079478a144dbae1afcb4fedf7b263)\n\n# References\n\nTest cases can be found [here](https://github.com/defijesus/stMATIC-update-emissions-admin-aave-v3/blob/main/tests/ChangeEmissionAdminTest.sol)\n\nPayload Implementation can be found [here](https://github.com/defijesus/stMATIC-update-emissions-admin-aave-v3/blob/main/src/contracts/ChangeEmissionAdminPayload.sol)\n\nProposal Payload = [0x7E8f833D23e19E88e3781Ca913d674a2D5178FA1](https://polygonscan.com/address/0x7E8f833D23e19E88e3781Ca913d674a2D5178FA1)\n\n# Copyright\n\nCopyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).",
+ "ipfsHash": "QmWREdMqbtDJb7MxbLdVgEYFJd1tWdfik6VrRksLvFd1c7",
+ "originalHash": "0x780a2b877ea3b13c924a30d2959ea0b8f0257799f1d4d743ed58f8783f529954",
+ "id": 130
+ },
+ {
+ "title": "Aave v2 ETH Interest Rate Curve Update",
+ "author": "Llama, Matthew Graham, Fermin Carranza and Dydymoon",
+ "shortDescription": "Amend Aave v2 Ethereum ETH Interest Rate Curve",
+ "discussions": "https://governance.aave.com/t/arc-eth-interest-rate-curve-update/10580",
+ "created": "2022-12-13T00:00:00.000Z",
+ "preview": "# Simple Summary\n\nLlama recommends amending the ETH interest rate …",
+ "basename": "ETH-V2-INTEREST-RATE-UPDATE",
+ "description": "\n\n# Simple Summary\n\nLlama recommends amending the ETH interest rate parameters on the Aave Ethereum v2 and v3 Liquidity Pool.\n\n# Abstract\n\nWith Aave v3 about to be deployed and a wstETH and ETH eMode likely, the ETH Interest Rate Curve should be adjusted such that the looped recursive strategy breaks even within Slope 1, where the Interest Rate changes are less volatile.\n\nThe new interest rate curve has an Interest Rate of 5.75% at the Uoptimal point, which is 25 bps more than stETH yield at the time of writing. This proposal will lead to improved capital efficiency of the ETH Reserve and will generate more revenue for the DAO when compared to replicating the existing v2 Interest Rate curve on v3 with the introduction of an ETH eMode Category.\n\nFor the existing v2 market, Llama suggests adopting the same Interest Rate parameters that are being being proposed on v3. This will enable the ETH yields across the markets to somewhat equalize, leading to higher utilization of the ETH Reserve and more revenue for the DAO.\n\n# Motivation\n\nBy changing the Interest Rate at the Uopotimal point from 3% to 5.75%, when an eMode for ETH and wstETH is created on Aave v3, the recursive strategy will break even prior to reaching the Uoptimal utilization within the Reserve. This is a desirable feature as the volatility of the Interest Rate on Slope 1 is less than Slope 2.\n\n\nBy setting the Slope 1 parameter at 5.75% (25 bps greater than the current annual wstETH yield), utilization in the Reserve is not expected to reach the Uoptimal level for any prolonged period of time.\n\nBy reducing the Slope 2 parameter from 100 to 80, the gradient of the second part of the yield curve increases due to an increase in Uoptimal from 70% to 80%. This is subtle and can be seen in the chart below. The Base Rate for the existing Interest Rate and proposed Interest Rate is unchanged at 0%.\n\nWith the recommended new Interest Rate curve for the v3 deployment, it is reasonable to expect the yield across the v2 and v3 deployment to be arbitraged. If the yield on the v3 deployment converges to the wstETH rate, then this will shift the v2 Reserve utilization beyond the Uoptimal level set at 3%. \n\nLlama recommendeds changing the v2 Interest Rate to match the v3 deployment Interest Rate. This way, both v2 and v3 Reserves will experience utilization along the Slope 1 portion of the Interest Rate curve whilst also benefiting from improved capital efficiency.\n\nThe graphic below shows the changes in the interest rate.\n\n\n\nThis proposal increases the Reserve Factor from 10% to 15%, directing 15% of the interest paid to Aave DAO. When combined with the Interest Rate changes, the v2 deployment will generate an estimated $13.1k per day, up from around $5.5k per day. \n\nPrior to this proposal, due the implementation of AIP-68, Aave DAO is earning less revenue from the ETH Reserve post-merge despite utilization within the Reserve [increasing](https://governance.aave.com/t/optimize-rate-curve-for-eth-improve-revenue-generation/7571) significantly over that time.\n\n# Specification\n\nThe below table shows the current and proposed changes to the ETH Reserve on Ethereum v2 and Ethereum v3 when deployed.\n\n| Parameter | Current Variable (%) | Proposed Variable (%) | Current Stable (%) | Proposed Stable (%) |\n| -------------- | ----------- | ------------ | -- | -- |\n| Uoptimal | 70 | 80 | 70 | 80 |\n| Base | 0 | 0 | 3.0| 3.0|\n| Slope1 | 3.0 | 5.75 | 4.0| 4.0|\n| Slope2 | 100 | 80 |100 | 80 |\n| Reserve Factor | 10 | 15 | 10 | 15 |\n\n# Implementation\n\nTest cases can be found [here](https://github.com/llama-community/aave-interest-rate-update/blob/main/src/test/ProposalPayloadE2E.t.sol)\n\nPayload Implementation can be found [here](https://github.com/llama-community/aave-interest-rate-update/blob/main/src/ProposalPayload.sol)\n\nProposal Payload = [0x98bc9dfa3cecb37f1bdeadc6e774d39082756b19](https://etherscan.io/address/0x98bc9dfa3cecb37f1bdeadc6e774d39082756b19#code)\n\n# Copyright\n\nCopyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).\n",
+ "ipfsHash": "QmWUDsEk9x5RMTNgwDTMbHuxL9Gx2Z7YwrhpwJMyBAnpFG",
+ "originalHash": "0x78ce0d63ca0c186ca3f58e712d3f1861ced3dad15ce3ad4f0e005d1663b49caf",
+ "id": 131
}
]
}
\ No newline at end of file
diff --git a/src/static-build/proposals.json b/src/static-build/proposals.json
index 598f094923..edd9330016 100644
--- a/src/static-build/proposals.json
+++ b/src/static-build/proposals.json
@@ -5291,12 +5291,12 @@
"startBlock": 16133133,
"endBlock": 16152333,
"executionTime": 0,
- "forVotes": "253036449383371076337393",
+ "forVotes": "314412820906431160599465",
"againstVotes": "2163580248982559052",
"executed": false,
"canceled": false,
"strategy": "0xb7e383ef9B1E9189Fc0F71fb30af8aa14377429e",
- "state": "Active",
+ "state": "Failed",
"minimumQuorum": "200",
"minimumDiff": "50",
"executionTimeWithGracePeriod": 0,
@@ -5305,7 +5305,7 @@
"ipfsHash": "0x780a2b877ea3b13c924a30d2959ea0b8f0257799f1d4d743ed58f8783f529954",
"startTimestamp": 1670419823,
"creationTimestamp": 1670331863,
- "expirationTimestamp": 1670651183
+ "expirationTimestamp": 1670650223
},
{
"id": 129,
@@ -5326,12 +5326,12 @@
"startBlock": 16140168,
"endBlock": 16159368,
"executionTime": 0,
- "forVotes": "750204219839782372258",
- "againstVotes": "382000000000000000",
+ "forVotes": "182268093090254792002576",
+ "againstVotes": "1779863703681242313",
"executed": false,
"canceled": false,
"strategy": "0xb7e383ef9B1E9189Fc0F71fb30af8aa14377429e",
- "state": "Active",
+ "state": "Failed",
"minimumQuorum": "200",
"minimumDiff": "50",
"executionTimeWithGracePeriod": 0,
@@ -5340,7 +5340,77 @@
"ipfsHash": "0x02e04de8258c1dca9c4c6099d8ac2142f1f2833bad5a7ca4154a12aa8f4dd548",
"startTimestamp": 1670504675,
"creationTimestamp": 1670417843,
- "expirationTimestamp": 1670735603
+ "expirationTimestamp": 1670735075
+ },
+ {
+ "id": 130,
+ "creator": "0x55B16934C3661E1990939bC57322554d9B09f262",
+ "executor": "0xEE56e2B3D491590B5b31738cC34d5232F378a8D5",
+ "targets": [
+ "0x158a6bC04F0828318821baE797f50B0A1299d45b"
+ ],
+ "signatures": [
+ "execute(address)"
+ ],
+ "calldatas": [
+ "0x0000000000000000000000007e8f833d23e19e88e3781ca913d674a2d5178fa1"
+ ],
+ "withDelegatecalls": [
+ true
+ ],
+ "startBlock": 16176459,
+ "endBlock": 16195659,
+ "executionTime": 0,
+ "forVotes": "548867553163281922225273",
+ "againstVotes": "445913153828952719",
+ "executed": false,
+ "canceled": false,
+ "strategy": "0xb7e383ef9B1E9189Fc0F71fb30af8aa14377429e",
+ "state": "Active",
+ "minimumQuorum": "200",
+ "minimumDiff": "50",
+ "executionTimeWithGracePeriod": 0,
+ "proposalCreated": 16169259,
+ "totalVotingSupply": "16000000000000000000000000",
+ "ipfsHash": "0x780a2b877ea3b13c924a30d2959ea0b8f0257799f1d4d743ed58f8783f529954",
+ "startTimestamp": 1670942759,
+ "creationTimestamp": 1670855735,
+ "expirationTimestamp": 1671174407
+ },
+ {
+ "id": 131,
+ "creator": "0x55B16934C3661E1990939bC57322554d9B09f262",
+ "executor": "0xEE56e2B3D491590B5b31738cC34d5232F378a8D5",
+ "targets": [
+ "0x98Bc9dfA3cEcB37F1bdeadc6e774d39082756B19"
+ ],
+ "signatures": [
+ "execute()"
+ ],
+ "calldatas": [
+ "0x"
+ ],
+ "withDelegatecalls": [
+ true
+ ],
+ "startBlock": 16183841,
+ "endBlock": 16203041,
+ "executionTime": 0,
+ "forVotes": "304435755361199074845394",
+ "againstVotes": "306316243345173621",
+ "executed": false,
+ "canceled": false,
+ "strategy": "0xb7e383ef9B1E9189Fc0F71fb30af8aa14377429e",
+ "state": "Active",
+ "minimumQuorum": "200",
+ "minimumDiff": "50",
+ "executionTimeWithGracePeriod": 0,
+ "proposalCreated": 16176641,
+ "totalVotingSupply": "16000000000000000000000000",
+ "ipfsHash": "0x78ce0d63ca0c186ca3f58e712d3f1861ced3dad15ce3ad4f0e005d1663b49caf",
+ "startTimestamp": 1671031859,
+ "creationTimestamp": 1670944979,
+ "expirationTimestamp": 1671262991
}
]
}
\ No newline at end of file
diff --git a/src/store/poolSelectors.ts b/src/store/poolSelectors.ts
index f20ee7dac2..59cacbe602 100644
--- a/src/store/poolSelectors.ts
+++ b/src/store/poolSelectors.ts
@@ -23,23 +23,38 @@ export const selectCurrentChainIdV3MarketKey = (state: RootStore): CustomMarket
export const selectCurrentChainIdV2MarketData = (state: RootStore) => {
const v2MarketKey = selectCurrentChainIdV2MarketKey(state);
const marketData = marketsData[v2MarketKey];
- return state.data
- .get(state.currentChainId)
- ?.get(marketData.addresses.LENDING_POOL_ADDRESS_PROVIDER);
+ const v2MarketAddressProvider = marketData
+ ? marketData.addresses.LENDING_POOL_ADDRESS_PROVIDER
+ : undefined;
+ const currentChainId = state.currentChainId;
+ if (v2MarketAddressProvider && currentChainId) {
+ return state.data.get(state.currentChainId)?.get(v2MarketAddressProvider);
+ }
+ return undefined;
};
export const selectCurrentChainIdV3MarketData = (state: RootStore) => {
- const v3MarketKey = selectCurrentChainIdV3MarketKey(state);
+ const v3MarketKey = selectCurrentChainIdV2MarketKey(state);
const marketData = marketsData[v3MarketKey];
- return state.data
- .get(state.currentChainId)
- ?.get(marketData.addresses.LENDING_POOL_ADDRESS_PROVIDER);
+ const v3MarketAddressProvider = marketData
+ ? marketData.addresses.LENDING_POOL_ADDRESS_PROVIDER
+ : undefined;
+ const currentChainId = state.currentChainId;
+ if (v3MarketAddressProvider && currentChainId) {
+ return state.data.get(state.currentChainId)?.get(v3MarketAddressProvider);
+ }
+ return undefined;
};
export const selectCurrentUserLendingPoolData = (state: RootStore) => {
- return state.data
- .get(state.currentChainId)
- ?.get(state.currentMarketData.addresses.LENDING_POOL_ADDRESS_PROVIDER);
+ const marketAddressProvider = state.currentMarketData
+ ? state.currentMarketData.addresses.LENDING_POOL_ADDRESS_PROVIDER
+ : undefined;
+ const currentChainId = state.currentChainId;
+ if (marketAddressProvider && currentChainId) {
+ return state.data.get(state.currentChainId)?.get(marketAddressProvider);
+ }
+ return undefined;
};
export const selectFormatUserEmodeCategoryId = (reserve?: PoolReserve) => {
diff --git a/src/store/poolSlice.ts b/src/store/poolSlice.ts
index 98338296b3..f3c60680e7 100644
--- a/src/store/poolSlice.ts
+++ b/src/store/poolSlice.ts
@@ -23,17 +23,14 @@ import {
LPSignERC20ApprovalType,
LPSupplyWithPermitType,
} from '@aave/contract-helpers/dist/esm/v3-pool-contract/lendingPoolTypes';
-import { normalize } from '@aave/math-utils';
import { SignatureLike } from '@ethersproject/bytes';
import dayjs from 'dayjs';
import { produce } from 'immer';
-import { OptimalRate } from 'paraswap-core';
import { ClaimRewardsActionsProps } from 'src/components/transactions/ClaimRewards/ClaimRewardsActions';
-import { RepayActionProps as ParaswapRepayActionProps } from 'src/components/transactions/Repay/CollateralRepayActions';
+import { CollateralRepayActionProps } from 'src/components/transactions/Repay/CollateralRepayActions';
import { RepayActionProps } from 'src/components/transactions/Repay/RepayActions';
import { SupplyActionProps } from 'src/components/transactions/Supply/SupplyActions';
import { SwapActionProps } from 'src/components/transactions/Swap/SwapActions';
-import { getRepayCallData, getSwapCallData } from 'src/hooks/useSwap';
import { MarketDataType } from 'src/ui-config/marketsConfig';
import { marketsData } from 'src/utils/marketsAndNetworksConfig';
import { optimizedPath } from 'src/utils/utils';
@@ -69,7 +66,7 @@ export interface PoolSlice {
args: Omit
) => Promise;
paraswapRepayWithCollateral: (
- args: ParaswapRepayActionProps
+ args: CollateralRepayActionProps
) => Promise;
supplyWithPermit: (
args: Omit
@@ -240,34 +237,23 @@ export const createPoolSlice: StateCreator<
paraswapRepayWithCollateral: async ({
fromAssetData,
poolReserve,
- priceRoute,
- maxSlippage,
repayAmount,
+ repayWithAmount,
repayAllDebt,
useFlashLoan,
rateMode,
+ augustus,
+ swapCallData,
}) => {
const user = get().account;
const pool = getCorrectPool();
- const chainId = get().currentNetworkConfig.underlyingChainId || get().currentChainId;
-
- const { swapCallData, augustus, srcAmountWithSlippage } = await getRepayCallData({
- srcToken: fromAssetData.underlyingAsset,
- srcDecimals: fromAssetData.decimals,
- destToken: poolReserve.underlyingAsset,
- destDecimals: poolReserve.decimals,
- user,
- route: priceRoute as OptimalRate,
- chainId,
- maxSlippage,
- });
return pool.paraswapRepayWithCollateral({
user,
fromAsset: fromAssetData.underlyingAsset,
fromAToken: fromAssetData.aTokenAddress,
assetToRepay: poolReserve.underlyingAsset,
- repayWithAmount: normalize(srcAmountWithSlippage, fromAssetData.decimals),
+ repayWithAmount,
repayAmount,
repayAllDebt,
rateMode,
@@ -342,25 +328,15 @@ export const createPoolSlice: StateCreator<
swapCollateral: async ({
poolReserve,
targetReserve,
- priceRoute,
isMaxSelected,
amountToSwap,
amountToReceive,
useFlashLoan,
+ augustus,
+ swapCallData,
}) => {
const pool = getCorrectPool();
const user = get().account;
- const chainId = get().currentNetworkConfig.underlyingChainId || get().currentChainId;
-
- const { swapCallData, augustus } = await getSwapCallData({
- srcToken: poolReserve.underlyingAsset,
- srcDecimals: poolReserve.decimals,
- destToken: targetReserve.underlyingAsset,
- destDecimals: targetReserve.decimals,
- user,
- route: priceRoute as OptimalRate,
- chainId,
- });
return pool.swapCollateral({
fromAsset: poolReserve.underlyingAsset,
@@ -446,5 +422,3 @@ export const createPoolSlice: StateCreator<
},
};
};
-
-// TODO: move somewhere else
diff --git a/src/store/protocolDataSlice.ts b/src/store/protocolDataSlice.ts
index 5d33c8fdc9..3f17eaae37 100644
--- a/src/store/protocolDataSlice.ts
+++ b/src/store/protocolDataSlice.ts
@@ -1,4 +1,5 @@
-import { providers } from 'ethers';
+import { providers, utils } from 'ethers';
+import { permitByChainAndToken } from 'src/ui-config/permitConfig';
import {
availableMarkets,
getNetworkConfig,
@@ -19,6 +20,7 @@ export interface ProtocolDataSlice {
currentNetworkConfig: NetworkConfig;
jsonRpcProvider: () => providers.Provider;
setCurrentMarket: (market: CustomMarket, omitQueryParameterUpdate?: boolean) => void;
+ tryPermit: (reserveAddress: string) => boolean;
}
export const createProtocolDataSlice: StateCreator<
@@ -49,5 +51,17 @@ export const createProtocolDataSlice: StateCreator<
currentNetworkConfig: getNetworkConfig(nextMarketData.chainId),
});
},
+ tryPermit: (reserveAddress: string) => {
+ const currentNetworkConfig = get().currentNetworkConfig;
+ const currentMarketData = get().currentMarketData;
+ const underlyingChainId = currentNetworkConfig.isFork
+ ? currentNetworkConfig.underlyingChainId
+ : currentMarketData.chainId;
+ const tryPermit =
+ currentMarketData.v3 &&
+ underlyingChainId &&
+ permitByChainAndToken[underlyingChainId]?.[utils.getAddress(reserveAddress).toLowerCase()];
+ return Boolean(tryPermit);
+ },
};
};
diff --git a/src/store/walletSlice.ts b/src/store/walletSlice.ts
index 20a4cbba7c..068f920062 100644
--- a/src/store/walletSlice.ts
+++ b/src/store/walletSlice.ts
@@ -5,6 +5,11 @@ import { RootStore } from './root';
type WalletBalance = { address: string; amount: string };
+export enum ApprovalMethod {
+ APPROVE = 'Transaction',
+ PERMIT = 'Signed message',
+}
+
export interface WalletSlice {
account: string;
setAccount: (account: string | undefined) => void;
@@ -16,8 +21,20 @@ export interface WalletSlice {
};
};
refetchWalletBalances: () => Promise;
+ walletApprovalMethodPreference: ApprovalMethod;
+ setWalletApprovalMethodPreference: (method: ApprovalMethod) => void;
+ refreshWalletApprovalMethod: () => void;
}
+const getWalletPreferences = () => {
+ const walletPreference = localStorage.getItem('walletApprovalPreferences');
+ if (walletPreference) {
+ return JSON.parse(walletPreference);
+ } else {
+ return {};
+ }
+};
+
export const createWalletSlice: StateCreator<
RootStore,
[['zustand/devtools', never]],
@@ -27,11 +44,37 @@ export const createWalletSlice: StateCreator<
account: '',
setAccount(account) {
set({ account: account || '', isWalletModalOpen: false });
+ const refresh = get().refreshWalletApprovalMethod;
+ refresh();
},
isWalletModalOpen: false,
setWalletModalOpen(open) {
set({ isWalletModalOpen: open });
},
+ walletApprovalMethodPreference: ApprovalMethod.PERMIT,
+ setWalletApprovalMethodPreference: (method: ApprovalMethod) => {
+ const account = get().account;
+ if (account !== '') {
+ const walletPreferencesObject = getWalletPreferences();
+ walletPreferencesObject[account.toLowerCase()] = method;
+ localStorage.setItem('walletApprovalPreferences', JSON.stringify(walletPreferencesObject));
+ set(() => ({
+ walletApprovalMethodPreference: method,
+ }));
+ }
+ },
+ refreshWalletApprovalMethod: () => {
+ const account = get().account;
+ if (account !== '') {
+ const walletPreferencesObject = getWalletPreferences();
+ const accountPreference = walletPreferencesObject[account.toLowerCase()];
+ set(() => ({
+ walletApprovalMethodPreference: accountPreference
+ ? accountPreference
+ : ApprovalMethod.PERMIT,
+ }));
+ }
+ },
refetchWalletBalances: async () => {
const account = get().account;
if (!account) return;
diff --git a/src/ui-config/permitConfig.ts b/src/ui-config/permitConfig.ts
index 0465aac246..229a1e3fab 100644
--- a/src/ui-config/permitConfig.ts
+++ b/src/ui-config/permitConfig.ts
@@ -15,92 +15,92 @@ export const permitByChainAndToken: {
'0x2e3a2fb8473316a02b8a297b982498e661e1f6f5': true,
},
[ChainId.arbitrum_one]: {
- '0xf97f4df75117a78c1A5a0DBb814Af92458539FB4': true,
- '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8': true,
+ '0xf97f4df75117a78c1a5a0dbb814af92458539fb4': true,
+ '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8': true,
'0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f': true,
- '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1': true,
- '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9': true,
- '0xba5DdD1f9d7F570dc94a51479a000E3BCE967196': true,
- '0xD22a58f79e9481D1a88e00c343885A588b34b68B': false, // eurs
+ '0x82af49447d8a07e3bd95bd0d56f35241523fbab1': true,
+ '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9': true,
+ '0xba5ddd1f9d7f570dc94a51479a000e3bce967196': true,
+ '0xd22a58f79e9481d1a88e00c343885a588b34b68b': false, // eurs
},
[ChainId.arbitrum_goerli]: {
- '0x805aC2a202e3E217B0C9fe53908ea5e36856fD29': true,
- '0x7e752bC77eBE2225B327e6ebF09fAD7801873931': true,
- '0x569275a32682aBD8dE2eD68Dc7443724a8aD8660': true,
- '0xD0fbc05a6B234b2a6a9D65389C2ffd93Fef0527e': true,
- '0x6775842AE82BF2F0f987b10526768Ad89d79536E': true,
- '0xbAc565f93f3192D35E9106E67B9d5c9348bD9389': true,
- '0x2Df743730160059c50c6bA9E87b30876FA6Db720': true,
- '0xCDa739D69067333974cD73A722aB92E5e0ad8a4F': true,
+ '0x805ac2a202e3e217b0c9fe53908ea5e36856fd29': true,
+ '0x7e752bc77ebe2225b327e6ebf09fad7801873931': true,
+ '0x569275a32682abd8de2ed68dc7443724a8ad8660': true,
+ '0xd0fbc05a6b234b2a6a9d65389c2ffd93fef0527e': true,
+ '0x6775842ae82bf2f0f987b10526768ad89d79536e': true,
+ '0xbac565f93f3192d35e9106e67b9d5c9348bd9389': true,
+ '0x2df743730160059c50c6ba9e87b30876fa6db720': true,
+ '0xcda739d69067333974cd73a722ab92e5e0ad8a4f': true,
},
[ChainId.fantom]: {
- '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E': true,
- '0xb3654dc3D10Ea7645f8319668E8F54d2574FBdC8': true,
- '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75': true,
- '0x321162Cd933E2Be498Cd2267a90534A804051b11': true,
- '0x74b23882a30290451A17c44f4F05243b6b58C76d': true,
- '0x049d68029688eAbF473097a2fC38ef61633A3C7A': true,
- '0x6a07A792ab2965C72a5B8088d3a069A7aC3a993B': true,
- '0xae75A438b2E0cB8Bb01Ec1E1e376De11D44477CC': false, // sushi
- '0x1E4F97b9f9F913c46F1632781732927B9019C68b': true,
+ '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e': true,
+ '0xb3654dc3d10ea7645f8319668e8f54d2574fbdc8': true,
+ '0x04068da6c83afcfa0e13ba15a6696662335d5b75': true,
+ '0x321162cd933e2be498cd2267a90534a804051b11': true,
+ '0x74b23882a30290451a17c44f4f05243b6b58c76d': true,
+ '0x049d68029688eabf473097a2fc38ef61633a3c7a': true,
+ '0x6a07a792ab2965c72a5b8088d3a069a7ac3a993b': true,
+ '0xae75a438b2e0cb8bb01ec1e1e376de11d44477cc': false, // sushi
+ '0x1e4f97b9f9f913c46f1632781732927b9019c68b': true,
},
[ChainId.fantom_testnet]: {
- '0x2a6202B83Bd2562d7460F91E9298abC27a2F0a95': true,
- '0xAC1a9503D1438B56BAa99939D44555FC2dC286Fc': true,
- '0xc469ff24046779DE9B61Be7b5DF91dbFfdF1AE02': true,
- '0x42Dc50EB0d35A62eac61f4E4Bc81875db9F9366e': true,
- '0x484b87Aa284f51e71F15Eba1aEb06dFD202D5511': true,
- '0x06f0790c687A1bED6186ce3624EDD9806edf9F4E': true,
- '0x1b901d3C9D4ce153326BEeC60e0D4A2e8a9e3cE3': true,
- '0xd0404A349A76CD2a4B7AB322B9a6C993dbC3A7E7': true,
- '0x2aF63215417F90bd45608115452d86D0a1bEAE5E': true,
- '0xF7475b635EbE06d9C5178CC40D50856Fa98C7332': true,
+ '0x2a6202b83bd2562d7460f91e9298abc27a2f0a95': true,
+ '0xac1a9503d1438b56baa99939d44555fc2dc286fc': true,
+ '0xc469ff24046779de9b61be7b5df91dbffdf1ae02': true,
+ '0x42dc50eb0d35a62eac61f4e4bc81875db9f9366e': true,
+ '0x484b87aa284f51e71f15eba1aeb06dfd202d5511': true,
+ '0x06f0790c687a1bed6186ce3624edd9806edf9f4e': true,
+ '0x1b901d3c9d4ce153326beec60e0d4a2e8a9e3ce3': true,
+ '0xd0404a349a76cd2a4b7ab322b9a6c993dbc3a7e7': true,
+ '0x2af63215417f90bd45608115452d86d0a1beae5e': true,
+ '0xf7475b635ebe06d9c5178cc40d50856fa98c7332': true,
},
[ChainId.polygon]: {
- '0x4e3Decbb3645551B8A19f0eA1678079FCB33fB4c': true,
+ '0x4e3decbb3645551b8a19f0ea1678079fcb33fb4c': true,
},
[ChainId.mumbai]: {
- '0x0AB1917A0cf92cdcf7F7b637EaC3A46BBBE41409': true,
- '0xFCadBDefd30E11258559Ba239C8a5A8A8D28CB00': true,
- '0xE3981f4840843D67aF50026d34DA0f7e56A02D69': true,
- '0x3e4b51076d7e9B844B92F8c6377087f9cf8C8696': true,
- '0x9A753f0F7886C9fbF63cF59D0D4423C5eFaCE95B': true,
- '0x56e0507A53Ee252947a1E55D84Dc4032F914DD98': true,
- '0x302567472401C7c7B50ee7eb3418c375D8E3F728': true,
- '0x8AaF462990dD5CC574c94C8266208996426A47e7': true,
- '0xBaaCc99123133851Ba2D6d34952aa08CBDf5A4E4': true,
- '0xD9E7e5dd6e122dDE11244e14A60f38AbA93097f2': true,
- '0xdDc3C9B8614092e6188A86450c8D597509893E20': true,
- '0x9aa7fEc87CA69695Dd1f879567CcF49F3ba417E2': true,
- '0x21C561e551638401b937b03fE5a0a0652B99B7DD': true,
- '0x85E44420b6137bbc75a85CAB5c9A3371af976FdE': true,
- '0xd575d4047f8c667E064a4ad433D04E25187F40BB': true,
- '0xb685400156cF3CBE8725958DeAA61436727A30c3': false, // WMATIC dont have permit
+ '0x0ab1917a0cf92cdcf7f7b637eac3a46bbbe41409': true,
+ '0xfcadbdefd30e11258559ba239c8a5a8a8d28cb00': true,
+ '0xe3981f4840843d67af50026d34da0f7e56a02d69': true,
+ '0x3e4b51076d7e9b844b92f8c6377087f9cf8c8696': true,
+ '0x9a753f0f7886c9fbf63cf59d0d4423c5eface95b': true,
+ '0x56e0507a53ee252947a1e55d84dc4032f914dd98': true,
+ '0x302567472401c7c7b50ee7eb3418c375d8e3f728': true,
+ '0x8aaf462990dd5cc574c94c8266208996426a47e7': true,
+ '0xbaacc99123133851ba2d6d34952aa08cbdf5a4e4': true,
+ '0xd9e7e5dd6e122dde11244e14a60f38aba93097f2': true,
+ '0xddc3c9b8614092e6188a86450c8d597509893e20': true,
+ '0x9aa7fec87ca69695dd1f879567ccf49f3ba417e2': true,
+ '0x21c561e551638401b937b03fe5a0a0652b99b7dd': true,
+ '0x85e44420b6137bbc75a85cab5c9a3371af976fde': true,
+ '0xd575d4047f8c667e064a4ad433d04e25187f40bb': true,
+ '0xb685400156cf3cbe8725958deaa61436727a30c3': false, // wmatic dont have permit
},
[ChainId.harmony]: {},
[ChainId.avalanche]: {
- '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7': true,
+ '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7': true,
},
[ChainId.fuji]: {
- '0x407287b03D1167593AF113d32093942be13A535f': true,
- '0xFc7215C9498Fc12b22Bc0ed335871Db4315f03d3': true,
- '0x73b4C0C45bfB90FC44D9013FA213eF2C2d908D0A': true,
- '0x3E937B4881CBd500d05EeDAB7BA203f2b7B3f74f': true,
- '0x09C85Ef96e93f0ae892561052B48AE9DB29F2458': true,
- '0x28A8E6e41F84e62284970E4bc0867cEe2AAd0DA4': true,
- '0xD90db1ca5A6e9873BCD9B0279AE038272b656728': true,
- '0xCcbBaf8D40a5C34bf1c836e8dD33c7B7646706C5': true,
+ '0x407287b03d1167593af113d32093942be13a535f': true,
+ '0xfc7215c9498fc12b22bc0ed335871db4315f03d3': true,
+ '0x73b4c0c45bfb90fc44d9013fa213ef2c2d908d0a': true,
+ '0x3e937b4881cbd500d05eedab7ba203f2b7b3f74f': true,
+ '0x09c85ef96e93f0ae892561052b48ae9db29f2458': true,
+ '0x28a8e6e41f84e62284970e4bc0867cee2aad0da4': true,
+ '0xd90db1ca5a6e9873bcd9b0279ae038272b656728': true,
+ '0xccbbaf8d40a5c34bf1c836e8dd33c7b7646706c5': true,
},
[ChainId.optimism]: {
- '0x76FB31fb4af56892A25e32cFC43De717950c9278': false, // AAVE
+ '0x76fb31fb4af56892a25e32cfc43de717950c9278': false, // aave
},
[ChainId.optimism_goerli]: {
['0xdf1742fe5b0bfc12331d8eaec6b478dfdbd31464']: true,
- ['0xaA63E0C86b531E2eDFE9F91F6436dF20C301963D']: true,
- ['0xA2025B15a1757311bfD68cb14eaeFCc237AF5b43']: true,
- ['0xC2C527C0CACF457746Bd31B2a698Fe89de2b6d49']: true,
- ['0x63242B9Bd3C22f18706d5c4E627B4735973f1f07']: true,
- ['0x07C725d58437504CA5f814AE406e70E21C5e8e9e']: true,
- ['0x2e3A2fb8473316A02b8A297B982498E661E1f6f5']: true,
+ ['0xaa63e0c86b531e2edfe9f91f6436df20c301963d']: true,
+ ['0xa2025b15a1757311bfd68cb14eaefcc237af5b43']: true,
+ ['0xc2c527c0cacf457746bd31b2a698fe89de2b6d49']: true,
+ ['0x63242b9bd3c22f18706d5c4e627b4735973f1f07']: true,
+ ['0x07c725d58437504ca5f814ae406e70e21c5e8e9e']: true,
+ ['0x2e3a2fb8473316a02b8a297b982498e661e1f6f5']: true,
},
};
diff --git a/src/utils/__tests__/RotationProvider.test.ts b/src/utils/__tests__/RotationProvider.test.ts
index 8a9b1bb18c..d230aa6cde 100644
--- a/src/utils/__tests__/RotationProvider.test.ts
+++ b/src/utils/__tests__/RotationProvider.test.ts
@@ -24,28 +24,24 @@ it('rotates through providers on error', async () => {
expect(errors).toEqual([...badUrls]);
});
-it('waits for the rotation delay time after all providers have failed', (done) => {
+it('loops through provider array for maxRetries', async () => {
const badUrls = ['http://some-fake-url-1', 'http://some-fake-url-2', 'http://some-fake-url-3'];
- const rotationProvider = new RotationProvider(badUrls, ChainId.mainnet, { rotationDelay: 1000 });
+ const rotationProvider = new RotationProvider(badUrls, ChainId.mainnet, { maxRetries: 7 });
const errors: string[] = [];
- let start: number;
+ let retries = 0;
rotationProvider.on('debug', (error: { action: string; provider: StaticJsonRpcProvider }) => {
errors.push(error.provider.connection.url);
- if (start) {
- expect(Date.now() - start).toBeGreaterThan(1000);
- done();
- }
-
- // Once we've seen errors on all providers, start the timer.
- // We should see another error after the rotation delay time.
- if (errors.length === badUrls.length) {
- start = Date.now();
+ // Once we've seen errors on all providers, update retry count
+ if (errors.length % badUrls.length === 0) {
+ retries += 1;
}
});
// We don't care about the result, we just need to fire off a request
- rotationProvider.getBlock(15741825);
+ await rotationProvider.getBlock(15741825).catch(() => {
+ expect(retries).toBe(7);
+ });
});
it('rotates back to first provider after delay', (done) => {
diff --git a/src/utils/rotationProvider.ts b/src/utils/rotationProvider.ts
index 0b34346331..df8429c31f 100644
--- a/src/utils/rotationProvider.ts
+++ b/src/utils/rotationProvider.ts
@@ -1,11 +1,11 @@
import { BaseProvider, Network, StaticJsonRpcProvider } from '@ethersproject/providers';
import { logger } from 'ethers';
-const DEFAULT_ROTATION_DELAY = 5000;
const DEFAULT_FALL_FORWARD_DELAY = 60000;
+const MAX_RETRIES = 1;
interface RotationProviderConfig {
- rotationDelay?: number;
+ maxRetries?: number;
fallFowardDelay?: number;
}
@@ -66,8 +66,9 @@ export class RotationProvider extends BaseProvider {
readonly providers: StaticJsonRpcProvider[];
private currentProviderIndex = 0;
private firstRotationTimestamp = 0;
- // after completing a full rotation of the RotationProvider, delay to avoid spamming rpcs with requests
- private rotationDelay: number;
+ // number of full loops through provider array before throwing an error
+ private maxRetries = 0;
+ private retries = 0;
// if we rotate away from first rpc, return back after this delay
private fallForwardDelay: number;
@@ -75,7 +76,7 @@ export class RotationProvider extends BaseProvider {
super(chainId);
this.providers = urls.map((url) => new StaticJsonRpcProvider(url, chainId));
- this.rotationDelay = config?.rotationDelay || DEFAULT_ROTATION_DELAY;
+ this.maxRetries = config?.maxRetries || MAX_RETRIES;
this.fallForwardDelay = config?.fallFowardDelay || DEFAULT_FALL_FORWARD_DELAY;
}
@@ -104,7 +105,11 @@ export class RotationProvider extends BaseProvider {
this.firstRotationTimestamp = new Date().getTime();
this.fallForwardRotation();
} else if (this.currentProviderIndex === this.providers.length - 1) {
- await sleep(this.rotationDelay);
+ this.retries += 1;
+ if (this.retries > this.maxRetries) {
+ this.retries = 0;
+ throw new Error('RotationProvider exceeded max number of retries');
+ }
this.currentProviderIndex = 0;
} else {
this.currentProviderIndex += 1;
diff --git a/yarn.lock b/yarn.lock
index 5f4119d157..0566b1fd62 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,17 +2,17 @@
# yarn lockfile v1
-"@aave/contract-helpers@1.9.1-d6df625bf33ae6be0ed1a122ca941e3015691c6a.0":
- version "1.9.1-d6df625bf33ae6be0ed1a122ca941e3015691c6a.0"
- resolved "https://registry.yarnpkg.com/@aave/contract-helpers/-/contract-helpers-1.9.1-d6df625bf33ae6be0ed1a122ca941e3015691c6a.0.tgz#34ff5d936b926ceac2dcf1a9d3d0dbb279b8c84f"
- integrity sha512-VMCKEyV4/DWd3MaWRZ2tppneo0W4s2DLfFQZXzYEN7wYy33Dgx2FRFAuLRLyJjZyL4c6sfmCllGRTivpE/6jww==
+"@aave/contract-helpers@1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0+7a35ce0":
+ version "1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0"
+ resolved "https://registry.yarnpkg.com/@aave/contract-helpers/-/contract-helpers-1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0.tgz#bd81c87c7ed29492160bc8fca364c2fde018bee7"
+ integrity sha512-/LeAWFjxppwwJIQzg0tSgNUKnRnGPWnkzmHDp07QtbulSsx3kSS+264jJfLBW6rBSM0dvC8vHjUVTuANt+ErnA==
dependencies:
isomorphic-unfetch "^3.1.0"
-"@aave/math-utils@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@aave/math-utils/-/math-utils-1.9.0.tgz#873b6e4087559baa5ac5bfd3b0b8dbde85e054df"
- integrity sha512-6E4SUI3JwSsfmEayClrG1ipgOopVqRjxym50LvwVQrlDa863JRTq656DuQmwprNUarWM2cKAuVL7qh58SnWsOw==
+"@aave/math-utils@1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0+7a35ce0":
+ version "1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0"
+ resolved "https://registry.yarnpkg.com/@aave/math-utils/-/math-utils-1.10.1-84cac2ea132250e855317992ead7740288ff03b2.0.tgz#37ec85693944ff75fd192d17bbecf141f9ba13ba"
+ integrity sha512-jNJExrRB8fug9jazFcZ/TAO98p2gwT2PRfOqxm9MjmCPqqeK+ViCeVq6ldx5fmiLKUAIAt8rkhS+VaCjnyfemA==
dependencies:
bignumber.js "^9.0.1"
tslib "^2.4.0"