Skip to content

Commit

Permalink
Merge pull request #86 from morpho-org/feat/batch-optimization
Browse files Browse the repository at this point in the history
Feat/batch optimization
  • Loading branch information
julien-devatom committed Sep 18, 2023
2 parents aec90f7 + 6023a58 commit 3994875
Show file tree
Hide file tree
Showing 7 changed files with 666 additions and 13 deletions.
3 changes: 2 additions & 1 deletion src/fetchers/Static/StaticGlobalDataFetcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { constants, providers } from "ethers";

import { INITIAL_BLOCK_TIMESTAMP } from "../../mocks/global";
import { GlobalData } from "../../types";
import { GlobalDataFetcher } from "../fetchers.interfaces";

Expand All @@ -24,7 +25,7 @@ export class StaticGlobalDataFetcher
...this._globalData,
lastFetchTimestamp: 1679584231593,
currentBlock: {
timestamp: 1679584232,
timestamp: INITIAL_BLOCK_TIMESTAMP,
number: 16000000,
extraData: "",
_difficulty: constants.Zero,
Expand Down
1 change: 1 addition & 0 deletions src/mocks/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { GlobalData } from "../types";
import { Underlying } from "./markets";

const SECONDS_PER_WEEK = 24 * 3600 * 7; // in s
export const INITIAL_BLOCK_TIMESTAMP = 1679584232;

export const GLOBAL_DATA: Omit<
GlobalData,
Expand Down
156 changes: 145 additions & 11 deletions src/txHandler/batch/BaseBatch.TxHandler.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { BigNumber, constants } from "ethers";
import { getAddress, isAddress } from "ethers/lib/utils";
import { Subject } from "rxjs";
import { isAddress } from "ethers/lib/utils";
import { ReplaySubject, firstValueFrom } from "rxjs";

import { minBN } from "@morpho-labs/ethers-utils/lib/utils";

import { MorphoAaveV3Adapter } from "../../MorphoAaveV3Adapter";
import { MorphoAaveV3DataHolder } from "../../MorphoAaveV3DataHolder";
import { MorphoAaveV3Simulator } from "../../simulation/MorphoAaveV3Simulator";
import { ErrorCode } from "../../simulation/SimulationError";
import { Operation, TxOperation } from "../../simulation/simulation.types";
import {
Operation,
OperationType,
TxOperation,
} from "../../simulation/simulation.types";
import { Connectable } from "../../utils/mixins/Connectable";
import { UpdatableBehaviorSubject } from "../../utils/rxjs/UpdatableBehaviorSubject";
import { reverseTransactionType } from "../../utils/transactions";
import { IBatchTxHandler } from "../TxHandler.interface";
import { NotifierManager } from "../mixins/NotifierManager";

Expand All @@ -22,7 +29,7 @@ export default abstract class BaseBatchTxHandler
{
protected _adapter: MorphoAaveV3Adapter;

#done$?: Subject<boolean>;
#done$?: ReplaySubject<boolean>;

public readonly bulkerOperations$ = new UpdatableBehaviorSubject<
Bulker.Transactions[][]
Expand Down Expand Up @@ -55,16 +62,143 @@ export default abstract class BaseBatchTxHandler
super.reset();
}

public async addOperation(operation: Operation): Promise<void> {
this.#done$ = new Subject();
public async addOperation(
operation: Operation,
callback?: (newOperation?: Operation | null) => any
): Promise<void> {
this.#done$ = new ReplaySubject<boolean>(1);
let operations = this.simulatorOperations$.getValue();

let newOperation: Operation | undefined | null;

const [lastOperation] = operations.slice(-1);

if (lastOperation) {
switch (lastOperation.type) {
case OperationType.claimMorpho: {
break;
}
case OperationType.wrap: {
if (
lastOperation.type === operation.type &&
lastOperation.underlyingAddress === operation.underlyingAddress
) {
newOperation = {
...operation,
amount: minBN(
constants.MaxUint256,
lastOperation.amount.add(operation.amount)
),
};
}
break;
}
case OperationType.unwrap: {
if (
lastOperation.type === operation.type &&
lastOperation.underlyingAddress === operation.underlyingAddress
) {
newOperation = {
...operation,
amount: minBN(
constants.MaxUint256,
lastOperation.amount.add(operation.amount)
),
};
}
break;
}
default: {
if (operation.type === lastOperation.type) {
if (
lastOperation.underlyingAddress === operation.underlyingAddress &&
lastOperation.unwrap === operation.unwrap
) {
newOperation = {
type: operation.type,
underlyingAddress: operation.underlyingAddress,
unwrap: operation.unwrap,
amount: minBN(
constants.MaxUint256,
lastOperation.amount.add(operation.amount)
),
};
}
}
if (operation.type === reverseTransactionType(lastOperation.type)) {
if (
lastOperation.underlyingAddress === operation.underlyingAddress
) {
if (operation.amount.eq(constants.MaxUint256)) {
if (
lastOperation.formattedAmount &&
this.getUserMaxCapacity(
operation.underlyingAddress,
operation.type
)
?.amount.sub(lastOperation.formattedAmount)
.gt(0)
) {
newOperation = operation;
} else {
newOperation = null;
}
} else if (lastOperation.amount.eq(operation.amount)) {
newOperation = null;
} else {
const mainOperation = lastOperation.formattedAmount?.lte(
operation.amount
)
? operation
: lastOperation;

let amount: BigNumber;

if (operation.amount.eq(constants.MaxUint256)) {
amount = constants.MaxUint256;
} else if (lastOperation.amount.eq(constants.MaxUint256)) {
if (!lastOperation.formattedAmount) {
amount = constants.MaxUint256;
} else {
amount = lastOperation.formattedAmount
.sub(operation.amount)
.abs();
}
} else {
amount = lastOperation.amount.sub(operation.amount).abs();
}

if (amount.isZero()) {
newOperation = null;
} else {
newOperation = {
type: mainOperation.type,
amount,
underlyingAddress: mainOperation.underlyingAddress,
unwrap: mainOperation.unwrap,
};
}
}
}
}
break;
}
}
}
if (newOperation !== undefined) {
operations = operations.slice(0, -1);
if (newOperation) {
operations.push(newOperation);
}
} else {
operations.push(operation);
}

await new Promise((resolve) => {
this.#done$?.subscribe(resolve);
await callback?.(newOperation);

const operations = this.simulatorOperations$.getValue();
this.simulatorOperations$.next(operations);

this.simulatorOperations$.next([...operations, operation]);
});
await firstValueFrom(this.#done$);
}

/**
Expand Down
19 changes: 18 additions & 1 deletion src/txHandler/batch/Bulker.TxHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import addresses from "../../contracts/addresses";
import { safeSignTypedData } from "../../helpers/signatures";
import { Underlying } from "../../mocks/markets";
import { ErrorCode } from "../../simulation/SimulationError";
import { TxOperation } from "../../simulation/simulation.types";
import { Operation, TxOperation } from "../../simulation/simulation.types";
import { MaxCapacityLimiter, TransactionType, UserData } from "../../types";
import { getManagerApprovalMessage } from "../../utils/signatures/manager";
import { getPermit2Message } from "../../utils/signatures/permit2";
Expand Down Expand Up @@ -55,6 +55,23 @@ export default class BulkerTxHandler extends BaseBatchTxHandler {
return operationIndex;
}

public async addOperation(operation: Operation) {
await super.addOperation(operation, (newOperation) => {
if (newOperation !== undefined) {
this.signatures$.next(
this.signatures$
.getValue()
.filter(
(s) =>
s.transactionIndex !==
this.simulatorOperations$.getValue().length -
(!!newOperation ? 1 : 0)
)
);
}
});
}

protected _askForSignature(signature: BulkerSignature<false>) {
const oldSignatures = [...this.signatures$.getValue()];
const existingSignature = oldSignatures.find((sig) => {
Expand Down
18 changes: 18 additions & 0 deletions src/utils/transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { TransactionType } from "../types";

export const reverseTransactionType = (txType: TransactionType) => {
switch (txType) {
case TransactionType.borrow:
return TransactionType.repay;
case TransactionType.supply:
return TransactionType.withdraw;
case TransactionType.supplyCollateral:
return TransactionType.withdrawCollateral;
case TransactionType.repay:
return TransactionType.borrow;
case TransactionType.withdraw:
return TransactionType.supply;
case TransactionType.withdrawCollateral:
return TransactionType.supplyCollateral;
}
};

0 comments on commit 3994875

Please sign in to comment.