Skip to content

Commit

Permalink
Merge pull request #23 from lidofinance/feature/si-771-withdrawals-claim
Browse files Browse the repository at this point in the history
Withdrawals claim
  • Loading branch information
DiRaiks authored Sep 11, 2023
2 parents bc477cd + 447170f commit bd2dd1f
Show file tree
Hide file tree
Showing 23 changed files with 718 additions and 526 deletions.
1 change: 1 addition & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node
uses: actions/setup-node@v3
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"scripts": {
"dev": "yarn playground:dev",
"w-info": "yarn workspaces info",
"build": "yarn workspaces foreach -pt run build",
"build:packages": "yarn workspaces foreach --no-private run build",
"build": "yarn workspaces foreach -pt run build",
"build:packages": "yarn workspaces foreach --no-private run build",
"types": "yarn workspaces foreach -pt run types",
"test": "yarn workspaces foreach -pt run test",
"prepare": "husky install"
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ const callback: RequestStageCallback = ({ stage, payload }) => {
};

try {
const requestResult = await lidoSDK.withdrawals.request({
const requestResult = await lidoSDK.withdrawals.request.requestByToken({
amount,
requests,
token, // 'stETH' | 'wstETH'
Expand Down Expand Up @@ -510,7 +510,7 @@ const callback: RequestStageCallback = ({ stage, payload }) => {
};

try {
const requestResult = await lidoSDK.withdrawals.requestWithoutPermit({
const requestResult = await lidoSDK.withdrawals.request.requestWithoutPermit({
requests,
token, // 'stETH' | 'wstETH'
callback,
Expand Down
4 changes: 3 additions & 1 deletion packages/sdk/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export type LidoSDKCoreProps =
| LidoSDKCorePropsRpcProvider;

export enum TransactionCallbackStage {
'PERMIT' = 'permit',
'GAS_LIMIT' = 'gas_limit',
'SIGN' = 'sign',
'RECEIPT' = 'receipt',
Expand All @@ -37,8 +38,9 @@ export enum TransactionCallbackStage {
}

export type TransactionCallbackProps =
| { stage: TransactionCallbackStage.PERMIT; payload?: undefined }
| { stage: TransactionCallbackStage.GAS_LIMIT; payload?: undefined }
| { stage: TransactionCallbackStage.SIGN; payload?: undefined }
| { stage: TransactionCallbackStage.SIGN; payload?: bigint }
| { stage: TransactionCallbackStage.RECEIPT; payload: Hash }
| {
stage: TransactionCallbackStage.CONFIRMATION;
Expand Down
16 changes: 10 additions & 6 deletions packages/sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
export { LidoSDK } from './sdk.js';
export { type SDKError } from './common/utils/SDKError.js';
export * from './common/decorators/index.js';
export { StakeProps } from './staking/index.js';
export {
RequestCallbackStages,
RequestStageCallback,
RequestProps,
RequestWithPermitProps,
TransactionCallbackStage,
type TransactionCallback,
} from './core/index.js';
export { type StakeProps } from './staking/index.js';
export {
type ClaimRequestsProps,
type RequestProps,
type RequestWithPermitProps,
ApproveCallbackStages,
ApproveStageCallback,
type ApproveStageCallback,
} from './withdrawals/index.js';
export { LIDO_CONTRACT_NAMES } from './common/constants.js';
export { type WrapProps } from './wrap/index.js';
27 changes: 9 additions & 18 deletions packages/sdk/src/staking/staking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from 'viem';
import invariant from 'tiny-invariant';
import { LidoSDKCore } from '../core/index.js';
import { Logger, Cache } from '../common/decorators/index.js';
import { Logger, Cache, ErrorHandler } from '../common/decorators/index.js';

import {
SUBMIT_EXTRA_GAS_TRANSACTION_RATIO,
Expand Down Expand Up @@ -76,26 +76,15 @@ export class LidoSDKStaking {
// Calls

@Logger('Call:')
@ErrorHandler('Error:')
public async stake(props: StakeProps): Promise<StakeResult> {
invariant(this.core.web3Provider, 'Web3 provider is not defined');
const { account } = props;

const { callback, account } = props;
try {
const isContract = await this.core.isContract(account);

if (isContract) return await this.stakeMultisig(props);
else return await this.stakeEOA(props);
} catch (error) {
const { message, code } = this.core.getErrorMessage(error);
const txError = this.core.error({
message,
error,
code,
});
callback?.({ stage: TransactionCallbackStage.ERROR, payload: txError });
const isContract = await this.core.isContract(account);

throw txError;
}
if (isContract) return await this.stakeMultisig(props);
else return await this.stakeEOA(props);
}

@Logger('LOG:')
Expand All @@ -119,7 +108,7 @@ export class LidoSDKStaking {
referralAddress,
);

callback({ stage: TransactionCallbackStage.SIGN });
callback({ stage: TransactionCallbackStage.SIGN, payload: gasLimit });

const contract = await this.getContractStETH();
const transaction = await contract.write.submit([referralAddress], {
Expand Down Expand Up @@ -177,6 +166,7 @@ export class LidoSDKStaking {
}

@Logger('Call:')
@ErrorHandler('Error:')
public async stakeSimulateTx(
props: StakeProps,
): Promise<WriteContractParameters> {
Expand All @@ -199,6 +189,7 @@ export class LidoSDKStaking {

@Logger('Views:')
@Cache(30 * 1000, ['core.chain.id'])
@ErrorHandler('Error:')
public async getStakeLimitInfo() {
const contract = await this.getContractStETH();

Expand Down
40 changes: 39 additions & 1 deletion packages/sdk/src/withdrawals/bus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { LidoSDKCore } from '../core/index.js';
import { LidoSDKWithdrawalsContract } from './withdrawalsContract.js';
import { LidoSDKWithdrawalsViews } from './withdrawalsViews.js';
import { LidoSDKWithdrawalsRequestsInfo } from './withdrawalsRequestsInfo.js';
import { LidoSDKWithdrawalsApprove } from './withdrawalsApprove.js';
import { LidoSDKWithdrawalsApprove } from './request/approve.js';
import { LidoSDKWithdrawalsClaim } from './claim/claim.js';
import { LidoSDKWithdrawalsRequest } from './request/request.js';
import { type LidoSDKWithdrawalsProps } from './types.js';

export class Bus {
Expand All @@ -15,6 +17,8 @@ export class Bus {
private viewsInstance: LidoSDKWithdrawalsViews | undefined;
private requestsInfoInstance: LidoSDKWithdrawalsRequestsInfo | undefined;
private approvalInstance: LidoSDKWithdrawalsApprove | undefined;
private claimInstance: LidoSDKWithdrawalsClaim | undefined;
private requestInstance: LidoSDKWithdrawalsRequest | undefined;

constructor(props: LidoSDKWithdrawalsProps, version?: string) {
this.props = props;
Expand Down Expand Up @@ -104,4 +108,38 @@ export class Bus {
set approval(approve: LidoSDKWithdrawalsApprove) {
this.approvalInstance = approve;
}

// Claim

get claim(): LidoSDKWithdrawalsClaim {
if (!this.claimInstance) {
this.claimInstance = new LidoSDKWithdrawalsClaim({
...this.props,
bus: this,
});
return this.claimInstance;
}
return this.claimInstance;
}

set claim(approve: LidoSDKWithdrawalsClaim) {
this.claimInstance = approve;
}

// Request

get request(): LidoSDKWithdrawalsRequest {
if (!this.requestInstance) {
this.requestInstance = new LidoSDKWithdrawalsRequest({
...this.props,
bus: this,
});
return this.requestInstance;
}
return this.requestInstance;
}

set request(approve: LidoSDKWithdrawalsRequest) {
this.requestInstance = approve;
}
}
124 changes: 124 additions & 0 deletions packages/sdk/src/withdrawals/claim/claim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import invariant from 'tiny-invariant';

import { type LidoSDKCoreProps } from '../../core/index.js';
import { Logger, Cache, ErrorHandler } from '../../common/decorators/index.js';
import { TransactionCallbackStage } from '../../core/types.js';
import { version } from '../../version.js';

import { Bus } from '../bus.js';

import { ClaimRequestsProps } from './types.js';

export class LidoSDKWithdrawalsClaim {
private readonly bus: Bus;

constructor(props: LidoSDKCoreProps & { bus?: Bus }) {
if (props.bus) this.bus = props.bus;
else this.bus = new Bus(props, version);
}

// Calls

@Logger('Call:')
@ErrorHandler('Error:')
public async claimRequests(props: ClaimRequestsProps) {
const { account } = props;
invariant(this.bus.core.web3Provider, 'Web3 provider is not defined');
invariant(this.bus.core.rpcProvider, 'RPC provider is not defined');

const isContract = await this.bus.core.isContract(account);

if (isContract) return this.claimRequestsMultisig(props);
else return this.claimRequestsEOA(props);
}

@Logger('Call:')
@ErrorHandler('Error:')
public async claimRequestsEOA(props: ClaimRequestsProps) {
const { account, requestsIds, hints, callback } = props;

const contract = await this.bus.contract.getContractWithdrawalsQueue();

callback?.({ stage: TransactionCallbackStage.GAS_LIMIT });

const feeData = await this.bus.core.getFeeData();
const gasLimit = await this.claimGasLimit(props);
const overrides = {
account,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas ?? undefined,
maxFeePerGas: feeData.maxFeePerGas ?? undefined,
};

callback?.({ stage: TransactionCallbackStage.SIGN, payload: gasLimit });

const params = [requestsIds, hints] as const;
const transaction = await contract.write.claimWithdrawals(params, {
...overrides,
gas: gasLimit,
chain: this.bus.core.chain,
});

callback?.({
stage: TransactionCallbackStage.RECEIPT,
payload: transaction,
});

const transactionReceipt =
await this.bus.core.rpcProvider.waitForTransactionReceipt({
hash: transaction,
});

callback?.({
stage: TransactionCallbackStage.CONFIRMATION,
payload: transactionReceipt,
});

const confirmations =
await this.bus.core.rpcProvider.getTransactionConfirmations({
hash: transactionReceipt.transactionHash,
});

callback?.({
stage: TransactionCallbackStage.DONE,
payload: confirmations,
});

return { hash: transaction, receipt: transactionReceipt, confirmations };
}

@Logger('Call:')
@ErrorHandler('Error:')
public async claimRequestsMultisig(props: ClaimRequestsProps) {
const { account, requestsIds, hints, callback } = props;

const contract = await this.bus.contract.getContractWithdrawalsQueue();

callback?.({ stage: TransactionCallbackStage.SIGN });

const params = [requestsIds, hints] as const;
const transaction = await contract.write.claimWithdrawals(params, {
account,
chain: this.bus.core.chain,
});

callback?.({ stage: TransactionCallbackStage.MULTISIG_DONE });

return { hash: transaction };
}

@Logger('Utils:')
@Cache(30 * 1000, ['core.chain.id'])
private async claimGasLimit(props: ClaimRequestsProps): Promise<bigint> {
const { account, requestsIds, hints } = props;
invariant(this.bus.core.rpcProvider, 'RPC provider is not defined');

const contract = await this.bus.contract.getContractWithdrawalsQueue();

const params = [requestsIds, hints] as const;
const gasLimit = await contract.estimateGas.claimWithdrawals(params, {
account,
});

return gasLimit;
}
}
1 change: 1 addition & 0 deletions packages/sdk/src/withdrawals/claim/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { LidoSDKWithdrawalsClaim } from './claim.js';
10 changes: 10 additions & 0 deletions packages/sdk/src/withdrawals/claim/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { type Address } from 'viem';

import { TransactionCallback } from '../../core/index.js';

export type ClaimRequestsProps = {
account: Address;
requestsIds: bigint[];
hints: bigint[];
callback?: TransactionCallback;
};
5 changes: 2 additions & 3 deletions packages/sdk/src/withdrawals/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
export { LidoSDKWithdrawals } from './withdrawals.js';
export { ClaimRequestsProps } from './claim/types.js';
export {
type RequestCallbackStages,
type RequestStageCallback,
type RequestProps,
type RequestWithPermitProps,
type ApproveCallbackStages,
type ApproveStageCallback,
} from './types.js';
} from './request/types.js';
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { parseEther, type Address } from 'viem';
import invariant from 'tiny-invariant';

import { type LidoSDKCoreProps } from '../core/index.js';
import { Logger, Cache, ErrorHandler } from '../common/decorators/index.js';
import { version } from '../version.js';
import { type LidoSDKCoreProps } from '../../core/index.js';
import { Logger, Cache, ErrorHandler } from '../../common/decorators/index.js';
import { version } from '../../version.js';

import { Bus } from './bus.js';
import { Bus } from '../bus.js';
import { type ApproveProps, ApproveCallbackStages } from './types.js';

export class LidoSDKWithdrawalsApprove {
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/src/withdrawals/request/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { LidoSDKWithdrawalsRequest } from './request.js';
Loading

0 comments on commit bd2dd1f

Please sign in to comment.