Skip to content

Commit c335e4f

Browse files
committed
feat: migration service added
1 parent dc9f5b1 commit c335e4f

File tree

4 files changed

+137
-35
lines changed

4 files changed

+137
-35
lines changed

pages/v3-migration.page.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect } from 'react';
12
import { StakeModal } from 'src/components/transactions/Stake/StakeModal';
23
import { StakeCooldownModal } from 'src/components/transactions/StakeCooldown/StakeCooldownModal';
34
import { StakeRewardClaimModal } from 'src/components/transactions/StakeRewardClaim/StakeRewardClaimModal';
@@ -9,10 +10,11 @@ import { useRootStore } from 'src/store/root';
910
export default function V3Migration() {
1011
const { user, borrowPositions } = useUserReserves();
1112
const toggleSelectedSupplyPosition = useRootStore((state) => state.toggleMigrationSelectedAsset);
12-
const migrate = useRootStore((state) => state.migrateSelectedPositions);
13-
13+
const testMigration = useRootStore((state) => state._testMigration);
14+
// const migrate = useRootStore((state) => state.migrateSelectedPositions);
1415
return (
1516
<div>
17+
<div onClick={testMigration}>test migration</div>
1618
<div>supply</div>
1719
{user.userReservesData.map((reserve) => (
1820
<div
@@ -26,7 +28,7 @@ export default function V3Migration() {
2628
{borrowPositions.map((reserve) => (
2729
<div key={reserve.underlyingAsset}>{reserve.variableBorrowsUSD}</div>
2830
))}
29-
<button onClick={migrate}>Migrate positions</button>
31+
{/* <button onClick={migrate}>Migrate positions</button> */}
3032
</div>
3133
);
3234
}
Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
import { useTransactionHandler } from 'src/helpers/useTransactionHandler';
2+
import { useRootStore } from 'src/store/root';
3+
14
export const MigrateV3Actions = () => {
2-
// const migratorAddress = ;
5+
const migrate = useRootStore((store) => store.migrate);
6+
const getApprovePermitsForSelectedAssets = useRootStore(
7+
(store) => store.getApprovePermitsForSelectedAssets
8+
);
9+
const { approval, action } = useTransactionHandler({
10+
handleGetTxns: async () => {
11+
return [];
12+
},
13+
handleGetPermitTxns: async (signatures, deadline) => migrate(signatures, deadline),
14+
tryPermit: true,
15+
});
16+
17+
return (
18+
<div>
19+
<button onClick={() => approval(getApprovePermitsForSelectedAssets())}>Approve</button>
20+
<button onClick={action}>Migrate</button>
21+
</div>
22+
);
323
};

src/helpers/useTransactionHandler.tsx

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const useTransactionHandler = ({
5656
(state) => state.generatePermitPayloadForMigrationAsset
5757
);
5858

59-
const [approvalTx, setApprovalTx] = useState<EthereumTransactionTypeExtended | undefined>();
59+
const [approvalTxes, setApprovalTxes] = useState<EthereumTransactionTypeExtended[] | undefined>();
6060
const [actionTx, setActionTx] = useState<EthereumTransactionTypeExtended | undefined>();
6161
const mounted = useRef(false);
6262

@@ -112,7 +112,7 @@ export const useTransactionHandler = ({
112112
};
113113

114114
const approval = async (approvals?: Approval[]) => {
115-
if (approvalTx) {
115+
if (approvalTxes) {
116116
if (usePermit && approvals && approvals?.length > 0) {
117117
setApprovalTxState({ ...approvalTxState, loading: true });
118118
try {
@@ -179,28 +179,60 @@ export const useTransactionHandler = ({
179179
} else {
180180
try {
181181
setApprovalTxState({ ...approvalTxState, loading: true });
182-
const params = await approvalTx.tx();
183-
delete params.gasPrice;
184-
await processTx({
185-
tx: () => sendTx(params),
186-
successCallback: (txnResponse: TransactionResponse) => {
187-
setApprovalTxState({
188-
txHash: txnResponse.hash,
189-
loading: false,
190-
success: true,
191-
});
192-
setTxError(undefined);
193-
},
194-
errorCallback: (error, hash) => {
195-
const parsedError = getErrorTextFromError(error, TxAction.APPROVAL, false);
196-
setTxError(parsedError);
197-
setApprovalTxState({
198-
txHash: hash,
199-
loading: false,
200-
});
201-
},
202-
action: TxAction.APPROVAL,
182+
const params = await Promise.all(approvalTxes.map((approvalTx) => approvalTx.tx()));
183+
const approvalResponses = await Promise.all(
184+
params.map(
185+
(param) =>
186+
new Promise<TransactionResponse>((resolve, reject) => {
187+
processTx({
188+
tx: () => sendTx(param),
189+
successCallback: (txnResponse: TransactionResponse) => {
190+
resolve(txnResponse);
191+
},
192+
errorCallback: (error, hash) => {
193+
const parsedError = getErrorTextFromError(error, TxAction.APPROVAL, false);
194+
setTxError(parsedError);
195+
setApprovalTxState({
196+
txHash: hash,
197+
loading: false,
198+
});
199+
reject();
200+
},
201+
// TODO: add error callback
202+
action: TxAction.APPROVAL,
203+
});
204+
})
205+
)
206+
);
207+
208+
setApprovalTxState({
209+
txHash: approvalResponses[0].hash,
210+
loading: false,
211+
success: true,
203212
});
213+
214+
// const params = await approvalTx.tx();
215+
// delete params.gasPrice;
216+
// await processTx({
217+
// tx: () => sendTx(params),
218+
// successCallback: (txnResponse: TransactionResponse) => {
219+
// setApprovalTxState({
220+
// txHash: txnResponse.hash,
221+
// loading: false,
222+
// success: true,
223+
// });
224+
// setTxError(undefined);
225+
// },
226+
// errorCallback: (error, hash) => {
227+
// const parsedError = getErrorTextFromError(error, TxAction.APPROVAL, false);
228+
// setTxError(parsedError);
229+
// setApprovalTxState({
230+
// txHash: hash,
231+
// loading: false,
232+
// });
233+
// },
234+
// action: TxAction.APPROVAL,
235+
// });
204236
} catch (error) {
205237
if (!mounted.current) return;
206238
const parsedError = getErrorTextFromError(error, TxAction.GAS_ESTIMATION, false);
@@ -215,7 +247,7 @@ export const useTransactionHandler = ({
215247
};
216248

217249
const action = async () => {
218-
if (approvalTx && usePermit && handleGetPermitTxns) {
250+
if (approvalTxes && usePermit && handleGetPermitTxns) {
219251
if (!signatures.length || !signatureDeadline) throw new Error('signature needed');
220252
try {
221253
setMainTxState({ ...mainTxState, loading: true });
@@ -251,7 +283,7 @@ export const useTransactionHandler = ({
251283
});
252284
}
253285
}
254-
if ((!usePermit || !approvalTx) && actionTx) {
286+
if ((!usePermit || !approvalTxes) && actionTx) {
255287
try {
256288
setMainTxState({ ...mainTxState, loading: true });
257289
const params = await actionTx.tx();
@@ -297,7 +329,11 @@ export const useTransactionHandler = ({
297329
return handleGetTxns()
298330
.then(async (data) => {
299331
if (!mounted.current) return;
300-
setApprovalTx(data.find((tx) => tx.txType === 'ERC20_APPROVAL'));
332+
// setApprovalTxes(data.filte((tx) => tx.txType === 'ERC20_APPROVAL'));
333+
const approvals = data.filter((tx) => tx.txType == 'ERC20_APPROVAL');
334+
if (approvals.length > 0) {
335+
setApprovalTxes(approvals);
336+
}
301337
setActionTx(
302338
data.find((tx) =>
303339
[
@@ -336,7 +372,7 @@ export const useTransactionHandler = ({
336372
}, 1000);
337373
return () => clearTimeout(timeout);
338374
} else {
339-
setApprovalTx(undefined);
375+
setApprovalTxes(undefined);
340376
setActionTx(undefined);
341377
}
342378
}, [skip, ...deps]);
@@ -346,11 +382,11 @@ export const useTransactionHandler = ({
346382
action,
347383
loadingTxns,
348384
setUsePermit,
349-
requiresApproval: !!approvalTx,
385+
requiresApproval: !!approvalTxes,
350386
approvalTxState,
351387
mainTxState,
352388
usePermit,
353389
actionTx,
354-
approvalTx,
390+
// approvalTx,
355391
};
356392
};

src/store/v3MigrationSlice.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
import { ERC20_2612Service, ERC20Service, valueToWei } from '@aave/contract-helpers';
1+
import {
2+
// ERC20_2612Service,
3+
ERC20Service,
4+
EthereumTransactionTypeExtended,
5+
V3MigrationHelperService,
6+
valueToWei,
7+
} from '@aave/contract-helpers';
8+
import { SignatureLike } from '@ethersproject/bytes';
29
import dayjs from 'dayjs';
10+
import { BigNumberish } from 'ethers';
311
import { produce } from 'immer';
412
import { Approval } from 'src/helpers/useTransactionHandler';
513
import { StateCreator } from 'zustand';
@@ -10,6 +18,7 @@ import { selectedUserReservesForMigration } from './v3MigrationSelectors';
1018
export type V3MigrationSlice = {
1119
//STATE
1220
selectedMigrationAssets: Record<string, boolean>;
21+
timestamp: number;
1322
// ACTIONS
1423
generatePermitPayloadForMigrationAsset: (
1524
approval: Approval & {
@@ -19,6 +28,12 @@ export type V3MigrationSlice = {
1928
getApprovePermitsForSelectedAssets: () => Approval[];
2029
toggleMigrationSelectedAsset: (assetName: string) => void;
2130
getMigratorAddress: () => string;
31+
getMigrationServiceInstance: () => V3MigrationHelperService;
32+
migrate: (
33+
signature: SignatureLike[],
34+
deadline: BigNumberish
35+
) => EthereumTransactionTypeExtended[];
36+
_testMigration: () => void;
2237
// migrateSelectedPositions: () => void;
2338
};
2439

@@ -30,6 +45,7 @@ export const createV3MigrationSlice: StateCreator<
3045
> = (set, get) => {
3146
return {
3247
selectedMigrationAssets: {},
48+
timestamp: 0,
3349
generatePermitPayloadForMigrationAsset: async ({ amount, underlyingAsset, deadline }) => {
3450
const user = get().account;
3551
const { getTokenData } = new ERC20Service(get().jsonRpcProvider());
@@ -90,18 +106,46 @@ export const createV3MigrationSlice: StateCreator<
90106
},
91107
getApprovePermitsForSelectedAssets: () => {
92108
const timestamp = dayjs().unix();
109+
set({ timestamp });
93110
return selectedUserReservesForMigration(get(), timestamp).map(({ reserve }): Approval => {
94111
reserve.name;
95112
return {
113+
// TODO: should we allow spending of exact ammount of the reserver?
96114
amount: reserve.totalLiquidity,
97115
underlyingAsset: reserve.aTokenAddress,
98116
permitType: 'MIGRATOR',
99117
};
100118
});
101119
},
120+
migrate: (signatures: SignatureLike[], deadline: BigNumberish) => {
121+
const selectedReservers = selectedUserReservesForMigration(get(), get().timestamp);
122+
const permits = selectedReservers.map(({ reserve }, index) => ({
123+
aToken: reserve.aTokenAddress,
124+
value: reserve.totalLiquidity,
125+
deadline,
126+
signedPermit: signatures[index],
127+
}));
128+
// branch out into flashloan or migrate no borrow
129+
// move that to separate instance and save cache the Migrator instance
130+
const migratorHelperInstance = get().getMigrationServiceInstance();
131+
const user = get().account;
132+
const assets = permits.map((permit) => permit.aToken);
133+
return migratorHelperInstance.migrateNoBorrowWithPermits({
134+
user,
135+
assets,
136+
signedPermits: permits,
137+
});
138+
},
102139
getMigratorAddress: () => {
103140
// TODO: map migrator addresses for each chain after deployment
104-
return '0x0000000000';
141+
return '0x01ce9bbcc0418614a8bba983fe79cf77211996f2';
142+
},
143+
getMigrationServiceInstance: () => {
144+
return new V3MigrationHelperService(get().jsonRpcProvider(), get().getMigratorAddress());
145+
},
146+
_testMigration: async () => {
147+
const someAddress = await get().getMigrationServiceInstance().testDeployment();
148+
console.log(someAddress, 'someAddress');
105149
},
106150
};
107151
};

0 commit comments

Comments
 (0)