From a540f0aa2d47bfb1848137663b49d97f92a90a3c Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Wed, 20 Mar 2024 17:18:17 +0100 Subject: [PATCH 01/12] feat: added withdrawal waiting time methods, tests, playground examples, docs --- README.md | 2 +- packages/sdk/README.md | 52 +++++++++++++- .../__test__/withdraw-waiting-time.test.ts | 29 ++++++++ packages/sdk/src/withdraw/bus.ts | 14 ++++ packages/sdk/src/withdraw/types.ts | 51 ++++++++++++++ .../sdk/src/withdraw/withdraw-waiting-time.ts | 70 +++++++++++++++++++ playground/demo/withdrawals/request.tsx | 23 ++++++ 7 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 packages/sdk/src/withdraw/__test__/withdraw-waiting-time.test.ts create mode 100644 packages/sdk/src/withdraw/withdraw-waiting-time.ts diff --git a/README.md b/README.md index fdcfcf0d..b0121501 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ console.log(balanceETH.toString(), 'ETH balance'); ## Migration -For breaking changes between versions see [MIGRATION.md](MIGRATION.md) +For breaking changes between versions see [MIGRATION.md](packages/sdk/MIGRATION.md) ## Documentation diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 6de68160..95ee9f66 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -66,6 +66,9 @@ For breaking changes between versions see [MIGRATION.md](MIGRATION.md) - [Views](#views) - [Constants](#constants) - [Requests info](#requests-info) + - [Waiting time](#waiting-time) + - [get time by amount](#calculate-by-amount) + - [Get time by request ids](#get-time-by-request-ids) - [(w)stETH](#wsteth) - [unstETH NFT](#unsteth-nft) - [Shares](#shares) @@ -654,7 +657,7 @@ try { console.log( 'transaction hash, transaction receipt, confirmations', requestResult, - 'array of requests(nfts) created with ids, amounts,creator, owner' + 'array of requests(nfts) created with ids, amounts,creator, owner', request.results.requests, ); } catch (error) { @@ -1010,6 +1013,53 @@ try { - `pendingRequests` (Type: Array[RequestStatusWithId]): A list of requests pending finalization. - `pendingAmountStETH` (Type: bigint): The amount of ETH pending claiming. +### Waiting time + +#### Methods + +##### Get time by amount + +###### `getWithdrawalWaitingTimeByAmount` + +###### Input Parameters: + +- `props: { amount: bigint }` + - `amount` (Type: bigint): The amount of withdrawable eth. + +##### Output Parameters: + +- Type: Object +- Structure: + - `requestInfo` (Type: Object): Information about withdrawal request + - `finalizationIn` (Type: number): The time needed for withdrawal in milliseconds. + - `finalizationAt` (Type: string): The amount of ETH available for claiming. + - `type` (Type: WaitingTimeCalculationType): Type of final source of eth for withdrawal. + - `status` (Type: WaitingTimeStatus): Status of withdrawal request. + - `nextCalculationAt` (Type: string): Time when calculation can be + +##### Get time by request ids + +###### `getWithdrawalWaitingTimeByRequestIds` + +###### Input Parameters: + +- `props: { ids: bigint[] }` + - `ids` (ids: Array[bigint]): The ids of withdrawal requests. + +##### Output Parameters: + +- Type: Array of WithdrawalWaitingTimeRequestInfo objects +- Structure of each object: + - `requestInfo` (Type: RequestByIdInfoDto): Information about withdrawal request. + - `finalizationIn` (Type: number): The time needed for withdrawal in milliseconds. + - `finalizationAt` (Type: string): The amount of ETH available for claiming. + - `requestId` (Type: string): The request id. + - `requestedAt` (Type: string): The time when withdrawal requested. + - `type` (Type: WaitingTimeCalculationType): Type of final source of eth for withdrawal. + - `status` (Type: WaitingTimeStatus): Status of withdrawal request. + - `nextCalculationAt` (Type: string): Time when calculation can be + + ## (w)stETH stETH and wstETH tokens functionality is presented trough modules with same ERC20 interface that exposes balances, allowances, transfers and ERC2612 permits signing. diff --git a/packages/sdk/src/withdraw/__test__/withdraw-waiting-time.test.ts b/packages/sdk/src/withdraw/__test__/withdraw-waiting-time.test.ts new file mode 100644 index 00000000..edbf847c --- /dev/null +++ b/packages/sdk/src/withdraw/__test__/withdraw-waiting-time.test.ts @@ -0,0 +1,29 @@ +import { expect, describe, test } from '@jest/globals'; +import { useWithdraw } from '../../../tests/utils/fixtures/use-withdraw.js'; +import { WithdrawalWaitingTimeByRequestIdsParams } from '../types.js'; + +describe('withdraw waiting time', () => { + const withdraw = useWithdraw(); + const { waitingTime } = withdraw; + + test('can get withdrawal waiting time by amount', async () => { + const amount = 110n; + const requestInfos = await waitingTime.getWithdrawalWaitingTimeByAmount({ + amount, + }); + expect(typeof requestInfos.status).toEqual('string'); + }); + + test('can get withdrawal waiting time by request ids', async () => { + const requestsIds = [1234n, 1235n]; + + const requestInfos = await waitingTime.getWithdrawalWaitingTimeByRequestIds( + { + ids: requestsIds, + } as WithdrawalWaitingTimeByRequestIdsParams, + ); + + expect(Array.isArray(requestInfos)).toEqual(true); + expect(requestInfos.length).toEqual(requestsIds.length); + }); +}); diff --git a/packages/sdk/src/withdraw/bus.ts b/packages/sdk/src/withdraw/bus.ts index 960a44ca..03c91665 100644 --- a/packages/sdk/src/withdraw/bus.ts +++ b/packages/sdk/src/withdraw/bus.ts @@ -7,6 +7,7 @@ import { LidoSDKWithdrawApprove, } from './request/index.js'; import { LidoSDKModule } from '../common/class-primitives/sdk-module.js'; +import { LidoSDKWithdrawWaitingTime } from './withdraw-waiting-time.js'; export class Bus extends LidoSDKModule { private version: string | undefined; @@ -17,6 +18,7 @@ export class Bus extends LidoSDKModule { private approvalInstance: LidoSDKWithdrawApprove | undefined; private claimInstance: LidoSDKWithdrawClaim | undefined; private requestInstance: LidoSDKWithdrawRequest | undefined; + private waitingTimeInstance: LidoSDKWithdrawWaitingTime | undefined; // Contract @@ -89,4 +91,16 @@ export class Bus extends LidoSDKModule { } return this.requestInstance; } + + // Waiting Time + + get waitingTime(): LidoSDKWithdrawWaitingTime { + if (!this.waitingTimeInstance) { + this.waitingTimeInstance = new LidoSDKWithdrawWaitingTime({ + bus: this, + version: this.version, + }); + } + return this.waitingTimeInstance; + } } diff --git a/packages/sdk/src/withdraw/types.ts b/packages/sdk/src/withdraw/types.ts index 3da0479d..2423d5fa 100644 --- a/packages/sdk/src/withdraw/types.ts +++ b/packages/sdk/src/withdraw/types.ts @@ -51,3 +51,54 @@ export type GetWithdrawalRequestsInfoReturnType = { pendingInfo: GetPendingRequestsInfoReturnType; claimableETH: GetClaimableRequestsETHByAccountReturnType; }; + +export type WithdrawalWaitingTimeByAmountParams = { + amount: bigint; +}; + +export class RequestInfoDto { + finalizationIn: number; + finalizationAt: string; + type: WaitingTimeCalculationType; +} + +export type WithdrawalWaitingTimeByAmountResponse = { + requestInfo: RequestInfoDto; + status: WaitingTimeStatus; + nextCalculationAt: string; +}; + +export type WithdrawalWaitingTimeByRequestIdsParams = { + ids: bigint[]; +}; + +export type RequestByIdInfoDto = { + finalizationIn: number; + finalizationAt: string; + requestId?: string; + requestedAt?: string; + type: WaitingTimeCalculationType; +}; + +export class WithdrawalWaitingTimeRequestInfo { + requestInfo: RequestByIdInfoDto; + status: WaitingTimeStatus; + nextCalculationAt: string; +} + +export enum WaitingTimeStatus { + initializing = 'initializing', + calculating = 'calculating', + finalized = 'finalized', + calculated = 'calculated', +} + +export enum WaitingTimeCalculationType { + buffer = 'buffer', + bunker = 'bunker', + vaultsBalance = 'vaultsBalance', + rewardsOnly = 'rewardsOnly', + validatorBalances = 'validatorBalances', + requestTimestampMargin = 'requestTimestampMargin', + exitValidators = 'exitValidators', +} diff --git a/packages/sdk/src/withdraw/withdraw-waiting-time.ts b/packages/sdk/src/withdraw/withdraw-waiting-time.ts new file mode 100644 index 00000000..40899edb --- /dev/null +++ b/packages/sdk/src/withdraw/withdraw-waiting-time.ts @@ -0,0 +1,70 @@ +import { Logger, ErrorHandler } from '../common/decorators/index.js'; + +import { BusModule } from './bus-module.js'; +import type { + WithdrawalWaitingTimeByAmountResponse, + WithdrawalWaitingTimeRequestInfo, + WithdrawalWaitingTimeByAmountParams, + WithdrawalWaitingTimeByRequestIdsParams, +} from './types.js'; +import { CHAINS } from '../common/index.js'; +import { formatEther } from 'viem'; + +const urls = { + [CHAINS.Mainnet]: 'https://wq-api.lido.fi', + [CHAINS.Goerli]: 'https://wq-api.testnet.fi', + [CHAINS.Holesky]: 'https://wq-api-holesky.testnet.fi', +}; + +const endpoints = { + calculateByAmount: '/v2/request-time/calculate', + calculateByRequestId: '/v2/request-time', +}; + +export class LidoSDKWithdrawWaitingTime extends BusModule { + // Utils + + @Logger('Utils:') + @ErrorHandler() + public async getWithdrawalWaitingTimeByAmount( + props: WithdrawalWaitingTimeByAmountParams, + ): Promise { + const query = new URLSearchParams(); + query.set('amount', formatEther(props.amount)); + const url = + urls[this.bus.core.chainId] + + endpoints.calculateByAmount + + '?' + + query.toString(); + + const response = await fetch(url, { + headers: { + 'WQ-Request-Source': 'sdk', + }, + }); + + return response.json(); + } + + @Logger('Utils:') + @ErrorHandler() + public async getWithdrawalWaitingTimeByRequestIds( + props: WithdrawalWaitingTimeByRequestIdsParams, + ): Promise { + const query = new URLSearchParams(); + query.set('ids', props.ids.toString()); + const url = + urls[this.bus.core.chainId] + + endpoints.calculateByRequestId + + '?' + + query.toString(); + + const response = await fetch(url, { + headers: { + 'WQ-Request-Source': 'sdk', + }, + }); + + return response.json(); + } +} diff --git a/playground/demo/withdrawals/request.tsx b/playground/demo/withdrawals/request.tsx index 8e42617f..9445f97c 100644 --- a/playground/demo/withdrawals/request.tsx +++ b/playground/demo/withdrawals/request.tsx @@ -180,6 +180,29 @@ export const WithdrawalsRequestDemo = () => { }) } /> + + + withdraw.waitingTime.getWithdrawalWaitingTimeByAmount({ + amount, + }) + } + /> + + { + const ids = await withdraw.views.getWithdrawalRequestsIds({ + account, + }); + return withdraw.waitingTime.getWithdrawalWaitingTimeByRequestIds({ + ids, + }); + }} + /> ); }; From 79abdc051caed5907ef0117285b52c58a157aaca Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Thu, 21 Mar 2024 08:35:04 +0100 Subject: [PATCH 02/12] feat: docs update --- packages/sdk/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 95ee9f66..c8170ae1 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -67,7 +67,7 @@ For breaking changes between versions see [MIGRATION.md](MIGRATION.md) - [Constants](#constants) - [Requests info](#requests-info) - [Waiting time](#waiting-time) - - [get time by amount](#calculate-by-amount) + - [Get time by amount](#get-time-by-amount) - [Get time by request ids](#get-time-by-request-ids) - [(w)stETH](#wsteth) - [unstETH NFT](#unsteth-nft) From 7392dbc3abe618829ba18d5314ba8a1b08aa69ad Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Thu, 21 Mar 2024 08:38:16 +0100 Subject: [PATCH 03/12] feat: docs update --- packages/sdk/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sdk/README.md b/packages/sdk/README.md index c8170ae1..6559a0d9 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -1032,10 +1032,10 @@ try { - Structure: - `requestInfo` (Type: Object): Information about withdrawal request - `finalizationIn` (Type: number): The time needed for withdrawal in milliseconds. - - `finalizationAt` (Type: string): The amount of ETH available for claiming. + - `finalizationAt` (Type: string): The time when request finalized for withdrawal. - `type` (Type: WaitingTimeCalculationType): Type of final source of eth for withdrawal. - `status` (Type: WaitingTimeStatus): Status of withdrawal request. - - `nextCalculationAt` (Type: string): Time when calculation can be + - `nextCalculationAt` (Type: string): Time when next calculation can be changed. ##### Get time by request ids @@ -1052,12 +1052,12 @@ try { - Structure of each object: - `requestInfo` (Type: RequestByIdInfoDto): Information about withdrawal request. - `finalizationIn` (Type: number): The time needed for withdrawal in milliseconds. - - `finalizationAt` (Type: string): The amount of ETH available for claiming. + - `finalizationAt` (Type: string): The time when request finalized for withdrawal. - `requestId` (Type: string): The request id. - `requestedAt` (Type: string): The time when withdrawal requested. - `type` (Type: WaitingTimeCalculationType): Type of final source of eth for withdrawal. - `status` (Type: WaitingTimeStatus): Status of withdrawal request. - - `nextCalculationAt` (Type: string): Time when calculation can be + - `nextCalculationAt` (Type: string): Time when next calculation can be changed. ## (w)stETH From 3592dd542028a3695e951fa245164857c0ac9523 Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Thu, 21 Mar 2024 09:42:50 +0100 Subject: [PATCH 04/12] feat: update types --- packages/sdk/src/withdraw/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/withdraw/types.ts b/packages/sdk/src/withdraw/types.ts index 2423d5fa..e6202b55 100644 --- a/packages/sdk/src/withdraw/types.ts +++ b/packages/sdk/src/withdraw/types.ts @@ -56,7 +56,7 @@ export type WithdrawalWaitingTimeByAmountParams = { amount: bigint; }; -export class RequestInfoDto { +export type RequestInfoDto = { finalizationIn: number; finalizationAt: string; type: WaitingTimeCalculationType; @@ -80,7 +80,7 @@ export type RequestByIdInfoDto = { type: WaitingTimeCalculationType; }; -export class WithdrawalWaitingTimeRequestInfo { +export type WithdrawalWaitingTimeRequestInfo = { requestInfo: RequestByIdInfoDto; status: WaitingTimeStatus; nextCalculationAt: string; From d8556a58f5e83767187b9083a8931e6d5e99bc2a Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Thu, 21 Mar 2024 11:44:08 +0100 Subject: [PATCH 05/12] feat: update request by ids --- .../sdk/src/withdraw/withdraw-waiting-time.ts | 44 +++++++++++++------ playground/demo/withdrawals/request.tsx | 2 +- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/packages/sdk/src/withdraw/withdraw-waiting-time.ts b/packages/sdk/src/withdraw/withdraw-waiting-time.ts index 40899edb..b58da9be 100644 --- a/packages/sdk/src/withdraw/withdraw-waiting-time.ts +++ b/packages/sdk/src/withdraw/withdraw-waiting-time.ts @@ -51,20 +51,38 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { public async getWithdrawalWaitingTimeByRequestIds( props: WithdrawalWaitingTimeByRequestIdsParams, ): Promise { - const query = new URLSearchParams(); - query.set('ids', props.ids.toString()); - const url = - urls[this.bus.core.chainId] + - endpoints.calculateByRequestId + - '?' + - query.toString(); + const idsPages = []; + const pageSize = 20; + const baseUrl = + urls[this.bus.core.chainId] + endpoints.calculateByRequestId; - const response = await fetch(url, { - headers: { - 'WQ-Request-Source': 'sdk', - }, - }); + for (let i = 0; i < props.ids.length; i += pageSize) { + idsPages.push(props.ids.slice(i, i + pageSize)); + } - return response.json(); + const result = []; + + for (const page of idsPages) { + const query = new URLSearchParams(); + query.set('ids', page.toString()); + + const url = baseUrl + '?' + query.toString(); + + const response = await fetch(url, { + headers: { + 'WQ-Request-Source': 'sdk', + }, + }); + + const requests = await response.json(); + result.push(...requests); + + if (idsPages.length > 1) { + // avoid backend spam + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + } + + return result; } } diff --git a/playground/demo/withdrawals/request.tsx b/playground/demo/withdrawals/request.tsx index 9445f97c..906fd849 100644 --- a/playground/demo/withdrawals/request.tsx +++ b/playground/demo/withdrawals/request.tsx @@ -199,7 +199,7 @@ export const WithdrawalsRequestDemo = () => { account, }); return withdraw.waitingTime.getWithdrawalWaitingTimeByRequestIds({ - ids, + ids: ids as readonly bigint[], }); }} /> From 878e574ae2859eb689da062b1cfdb7a89c0c28ea Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Thu, 21 Mar 2024 13:01:15 +0100 Subject: [PATCH 06/12] feat: update types --- packages/sdk/src/withdraw/types.ts | 6 +++--- playground/demo/withdrawals/request.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sdk/src/withdraw/types.ts b/packages/sdk/src/withdraw/types.ts index e6202b55..7c4f727f 100644 --- a/packages/sdk/src/withdraw/types.ts +++ b/packages/sdk/src/withdraw/types.ts @@ -60,7 +60,7 @@ export type RequestInfoDto = { finalizationIn: number; finalizationAt: string; type: WaitingTimeCalculationType; -} +}; export type WithdrawalWaitingTimeByAmountResponse = { requestInfo: RequestInfoDto; @@ -69,7 +69,7 @@ export type WithdrawalWaitingTimeByAmountResponse = { }; export type WithdrawalWaitingTimeByRequestIdsParams = { - ids: bigint[]; + ids: readonly bigint[]; }; export type RequestByIdInfoDto = { @@ -84,7 +84,7 @@ export type WithdrawalWaitingTimeRequestInfo = { requestInfo: RequestByIdInfoDto; status: WaitingTimeStatus; nextCalculationAt: string; -} +}; export enum WaitingTimeStatus { initializing = 'initializing', diff --git a/playground/demo/withdrawals/request.tsx b/playground/demo/withdrawals/request.tsx index 906fd849..9445f97c 100644 --- a/playground/demo/withdrawals/request.tsx +++ b/playground/demo/withdrawals/request.tsx @@ -199,7 +199,7 @@ export const WithdrawalsRequestDemo = () => { account, }); return withdraw.waitingTime.getWithdrawalWaitingTimeByRequestIds({ - ids: ids as readonly bigint[], + ids, }); }} /> From e2f6a063a435b46b7dba987dbec1b871ffae2746 Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Fri, 22 Mar 2024 16:52:09 +0100 Subject: [PATCH 07/12] feat: added fetch options, updated types --- packages/sdk/README.md | 4 +- packages/sdk/src/common/constants.ts | 6 ++ .../sdk/src/common/decorators/constants.ts | 1 + packages/sdk/src/common/decorators/types.ts | 3 +- packages/sdk/src/withdraw/types.ts | 19 +++++-- .../sdk/src/withdraw/withdraw-waiting-time.ts | 56 ++++++++++++------- 6 files changed, 61 insertions(+), 28 deletions(-) diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 6559a0d9..b55a565d 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -1023,8 +1023,8 @@ try { ###### Input Parameters: -- `props: { amount: bigint }` - - `amount` (Type: bigint): The amount of withdrawable eth. +- `props: { amount?: bigint }` + - `amount?` (Type: bigint **optional**): The amount of withdrawable eth. In case when it is not passed, it is calculated as default information about queue. ##### Output Parameters: diff --git a/packages/sdk/src/common/constants.ts b/packages/sdk/src/common/constants.ts index e3f76e42..43897aa9 100644 --- a/packages/sdk/src/common/constants.ts +++ b/packages/sdk/src/common/constants.ts @@ -105,3 +105,9 @@ export const VIEM_CHAINS: { [key in CHAINS]: Chain } = { [CHAINS.Goerli]: goerli, [CHAINS.Holesky]: holesky, }; + +export const WQ_API_URLS: { [key in CHAINS]: string } = { + [CHAINS.Mainnet]: 'https://wq-api.lido.fi', + [CHAINS.Goerli]: 'https://wq-api.testnet.fi', + [CHAINS.Holesky]: 'https://wq-api-holesky.testnet.fi', +}; diff --git a/packages/sdk/src/common/decorators/constants.ts b/packages/sdk/src/common/decorators/constants.ts index b872cc72..59a7047c 100644 --- a/packages/sdk/src/common/decorators/constants.ts +++ b/packages/sdk/src/common/decorators/constants.ts @@ -15,6 +15,7 @@ export const ConsoleCss: Record = { 'Events:': 'color: salmon', 'Statistic:': 'color: purple', 'Rewards:': 'color: greenyellow', + 'API:': 'color: mediumpurple', 'Init:': 'color: #33F3FF;text-shadow: 0px 0px 0 #899CD5, 1px 1px 0 #8194CD, 2px 2px 0 #788BC4, 3px 3px 0 #6F82BB, 4px 4px 0 #677AB3, 5px 5px 0 #5E71AA, 6px 6px 0 #5568A1, 7px 7px 0 #4C5F98, 8px 8px 0 #445790, 9px 9px 0 #3B4E87, 10px 10px 0 #32457E, 11px 11px 0 #2A3D76, 12px 12px 0 #21346D, 13px 13px 0 #182B64, 14px 14px 0 #0F225B, 15px 15px 0 #071A53, 16px 16px 0 #02114A, 17px 17px 0 #0B0841, 18px 18px 0 #130039, 19px 19px 0 #1C0930, 20px 20px 0 #251227, 21px 21px 20px rgba(0,0,0,1), 21px 21px 1px rgba(0,0,0,0.5), 0px 0px 20px rgba(0,0,0,.2);font-size: 50px;', }; diff --git a/packages/sdk/src/common/decorators/types.ts b/packages/sdk/src/common/decorators/types.ts index fa7ab1ee..d8a31330 100644 --- a/packages/sdk/src/common/decorators/types.ts +++ b/packages/sdk/src/common/decorators/types.ts @@ -13,4 +13,5 @@ export type HeadMessage = | 'Events:' | 'Statistic:' | 'Rewards:' - | 'Deprecation:'; + | 'Deprecation:' + | 'API:'; diff --git a/packages/sdk/src/withdraw/types.ts b/packages/sdk/src/withdraw/types.ts index 7c4f727f..c3ea8eac 100644 --- a/packages/sdk/src/withdraw/types.ts +++ b/packages/sdk/src/withdraw/types.ts @@ -53,26 +53,35 @@ export type GetWithdrawalRequestsInfoReturnType = { }; export type WithdrawalWaitingTimeByAmountParams = { - amount: bigint; + amount?: bigint; }; -export type RequestInfoDto = { +export type RequestInfo = { finalizationIn: number; finalizationAt: string; type: WaitingTimeCalculationType; }; export type WithdrawalWaitingTimeByAmountResponse = { - requestInfo: RequestInfoDto; + requestInfo: RequestInfo; status: WaitingTimeStatus; nextCalculationAt: string; }; +export type WithdrawalWaitingTimeByAmountOptions = { + getWqApiURL?: () => string; +}; + export type WithdrawalWaitingTimeByRequestIdsParams = { ids: readonly bigint[]; }; -export type RequestByIdInfoDto = { +export type WithdrawalWaitingTimeByRequestIdsOptions = { + requestDelay?: number; + getWqApiURL?: () => string; +}; + +export type RequestByIdInfo = { finalizationIn: number; finalizationAt: string; requestId?: string; @@ -81,7 +90,7 @@ export type RequestByIdInfoDto = { }; export type WithdrawalWaitingTimeRequestInfo = { - requestInfo: RequestByIdInfoDto; + requestInfo: RequestByIdInfo; status: WaitingTimeStatus; nextCalculationAt: string; }; diff --git a/packages/sdk/src/withdraw/withdraw-waiting-time.ts b/packages/sdk/src/withdraw/withdraw-waiting-time.ts index b58da9be..6515c6ea 100644 --- a/packages/sdk/src/withdraw/withdraw-waiting-time.ts +++ b/packages/sdk/src/withdraw/withdraw-waiting-time.ts @@ -7,14 +7,12 @@ import type { WithdrawalWaitingTimeByAmountParams, WithdrawalWaitingTimeByRequestIdsParams, } from './types.js'; -import { CHAINS } from '../common/index.js'; +import { WQ_API_URLS } from '../common/index.js'; import { formatEther } from 'viem'; - -const urls = { - [CHAINS.Mainnet]: 'https://wq-api.lido.fi', - [CHAINS.Goerli]: 'https://wq-api.testnet.fi', - [CHAINS.Holesky]: 'https://wq-api-holesky.testnet.fi', -}; +import { + WithdrawalWaitingTimeByAmountOptions, + WithdrawalWaitingTimeByRequestIdsOptions, +} from './types.js'; const endpoints = { calculateByAmount: '/v2/request-time/calculate', @@ -22,20 +20,26 @@ const endpoints = { }; export class LidoSDKWithdrawWaitingTime extends BusModule { - // Utils - - @Logger('Utils:') + // API call integrations + @Logger('API:') @ErrorHandler() public async getWithdrawalWaitingTimeByAmount( props: WithdrawalWaitingTimeByAmountParams, + options?: WithdrawalWaitingTimeByAmountOptions, ): Promise { + const getWqApiURL = options?.getWqApiURL; + const query = new URLSearchParams(); - query.set('amount', formatEther(props.amount)); - const url = - urls[this.bus.core.chainId] + - endpoints.calculateByAmount + - '?' + - query.toString(); + if (props.amount) { + query.set('amount', formatEther(props.amount)); + } + + const baseUrl = + getWqApiURL && typeof getWqApiURL === 'function' + ? getWqApiURL() + : WQ_API_URLS[this.bus.core.chainId]; + + const url = `${baseUrl}${endpoints.calculateByAmount}?${query.toString()}`; const response = await fetch(url, { headers: { @@ -46,15 +50,27 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { return response.json(); } - @Logger('Utils:') + @Logger('API:') @ErrorHandler() public async getWithdrawalWaitingTimeByRequestIds( props: WithdrawalWaitingTimeByRequestIdsParams, + options?: WithdrawalWaitingTimeByRequestIdsOptions, ): Promise { + const requestDelay = options?.requestDelay ?? 1000; + const getWqApiURL = options?.getWqApiURL; + + if (!Array.isArray(props.ids) || props.ids.length === 0) { + throw new Error('expected not empty array ids'); + } + const idsPages = []; const pageSize = 20; const baseUrl = - urls[this.bus.core.chainId] + endpoints.calculateByRequestId; + getWqApiURL && typeof getWqApiURL === 'function' + ? getWqApiURL() + : WQ_API_URLS[this.bus.core.chainId]; + + const path = `${baseUrl}${endpoints.calculateByRequestId}`; for (let i = 0; i < props.ids.length; i += pageSize) { idsPages.push(props.ids.slice(i, i + pageSize)); @@ -66,7 +82,7 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { const query = new URLSearchParams(); query.set('ids', page.toString()); - const url = baseUrl + '?' + query.toString(); + const url = `${path}?${query.toString()}`; const response = await fetch(url, { headers: { @@ -79,7 +95,7 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { if (idsPages.length > 1) { // avoid backend spam - await new Promise((resolve) => setTimeout(resolve, 1000)); + await new Promise((resolve) => setTimeout(resolve, requestDelay)); } } From fdc60188f4f0bfad982d31efde4b77a2cb6a44bc Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Mon, 25 Mar 2024 12:55:36 +0100 Subject: [PATCH 08/12] feat: update function parameters --- packages/sdk/src/withdraw/types.ts | 15 ++++----- .../sdk/src/withdraw/withdraw-waiting-time.ts | 32 ++++++++----------- playground/demo/withdrawals/request.tsx | 4 +-- 3 files changed, 21 insertions(+), 30 deletions(-) diff --git a/packages/sdk/src/withdraw/types.ts b/packages/sdk/src/withdraw/types.ts index c3ea8eac..0ca5a4a3 100644 --- a/packages/sdk/src/withdraw/types.ts +++ b/packages/sdk/src/withdraw/types.ts @@ -52,8 +52,14 @@ export type GetWithdrawalRequestsInfoReturnType = { claimableETH: GetClaimableRequestsETHByAccountReturnType; }; +export type WqApiCustomUrlGetter = ( + defaultUrl: string, + chainId: number, +) => string; + export type WithdrawalWaitingTimeByAmountParams = { amount?: bigint; + getCustomApiUrl?: WqApiCustomUrlGetter; }; export type RequestInfo = { @@ -68,17 +74,10 @@ export type WithdrawalWaitingTimeByAmountResponse = { nextCalculationAt: string; }; -export type WithdrawalWaitingTimeByAmountOptions = { - getWqApiURL?: () => string; -}; - export type WithdrawalWaitingTimeByRequestIdsParams = { ids: readonly bigint[]; -}; - -export type WithdrawalWaitingTimeByRequestIdsOptions = { requestDelay?: number; - getWqApiURL?: () => string; + getCustomApiUrl?: WqApiCustomUrlGetter; }; export type RequestByIdInfo = { diff --git a/packages/sdk/src/withdraw/withdraw-waiting-time.ts b/packages/sdk/src/withdraw/withdraw-waiting-time.ts index 6515c6ea..9ea924e4 100644 --- a/packages/sdk/src/withdraw/withdraw-waiting-time.ts +++ b/packages/sdk/src/withdraw/withdraw-waiting-time.ts @@ -6,13 +6,10 @@ import type { WithdrawalWaitingTimeRequestInfo, WithdrawalWaitingTimeByAmountParams, WithdrawalWaitingTimeByRequestIdsParams, + WqApiCustomUrlGetter, } from './types.js'; import { WQ_API_URLS } from '../common/index.js'; import { formatEther } from 'viem'; -import { - WithdrawalWaitingTimeByAmountOptions, - WithdrawalWaitingTimeByRequestIdsOptions, -} from './types.js'; const endpoints = { calculateByAmount: '/v2/request-time/calculate', @@ -25,20 +22,15 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { @ErrorHandler() public async getWithdrawalWaitingTimeByAmount( props: WithdrawalWaitingTimeByAmountParams, - options?: WithdrawalWaitingTimeByAmountOptions, ): Promise { - const getWqApiURL = options?.getWqApiURL; + const getCustomApiUrl = props?.getCustomApiUrl; const query = new URLSearchParams(); if (props.amount) { query.set('amount', formatEther(props.amount)); } - const baseUrl = - getWqApiURL && typeof getWqApiURL === 'function' - ? getWqApiURL() - : WQ_API_URLS[this.bus.core.chainId]; - + const baseUrl = this.getBaseUrl(getCustomApiUrl); const url = `${baseUrl}${endpoints.calculateByAmount}?${query.toString()}`; const response = await fetch(url, { @@ -54,10 +46,9 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { @ErrorHandler() public async getWithdrawalWaitingTimeByRequestIds( props: WithdrawalWaitingTimeByRequestIdsParams, - options?: WithdrawalWaitingTimeByRequestIdsOptions, ): Promise { - const requestDelay = options?.requestDelay ?? 1000; - const getWqApiURL = options?.getWqApiURL; + const requestDelay = props?.requestDelay ?? 1000; + const getCustomApiUrl = props?.getCustomApiUrl; if (!Array.isArray(props.ids) || props.ids.length === 0) { throw new Error('expected not empty array ids'); @@ -65,11 +56,7 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { const idsPages = []; const pageSize = 20; - const baseUrl = - getWqApiURL && typeof getWqApiURL === 'function' - ? getWqApiURL() - : WQ_API_URLS[this.bus.core.chainId]; - + const baseUrl = this.getBaseUrl(getCustomApiUrl); const path = `${baseUrl}${endpoints.calculateByRequestId}`; for (let i = 0; i < props.ids.length; i += pageSize) { @@ -101,4 +88,11 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { return result; } + + getBaseUrl(getCustomApiUrl?: WqApiCustomUrlGetter) { + const defaultUrl = WQ_API_URLS[this.bus.core.chainId]; + return getCustomApiUrl && typeof getCustomApiUrl === 'function' + ? getCustomApiUrl(defaultUrl, this.bus.core.chainId) + : defaultUrl; + } } diff --git a/playground/demo/withdrawals/request.tsx b/playground/demo/withdrawals/request.tsx index 9445f97c..e8ee7e2d 100644 --- a/playground/demo/withdrawals/request.tsx +++ b/playground/demo/withdrawals/request.tsx @@ -195,9 +195,7 @@ export const WithdrawalsRequestDemo = () => { title={`Withdrawal Waiting Time For Account Requests`} walletAction action={async () => { - const ids = await withdraw.views.getWithdrawalRequestsIds({ - account, - }); + const ids = [1234n, 1235n]; return withdraw.waitingTime.getWithdrawalWaitingTimeByRequestIds({ ids, }); From 54ecf8f37cd1df0371853fc44cfc273b5bd775cc Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Mon, 25 Mar 2024 14:33:09 +0100 Subject: [PATCH 09/12] fix: bigint update --- playground/demo/withdrawals/request.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/playground/demo/withdrawals/request.tsx b/playground/demo/withdrawals/request.tsx index e8ee7e2d..9445f97c 100644 --- a/playground/demo/withdrawals/request.tsx +++ b/playground/demo/withdrawals/request.tsx @@ -195,7 +195,9 @@ export const WithdrawalsRequestDemo = () => { title={`Withdrawal Waiting Time For Account Requests`} walletAction action={async () => { - const ids = [1234n, 1235n]; + const ids = await withdraw.views.getWithdrawalRequestsIds({ + account, + }); return withdraw.waitingTime.getWithdrawalWaitingTimeByRequestIds({ ids, }); From 70038c8210c79763a553f1e80f5ed7b7b73f52f6 Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Tue, 26 Mar 2024 10:30:16 +0100 Subject: [PATCH 10/12] docs: added changelog --- packages/sdk/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md index 393e46d3..9ac09254 100644 --- a/packages/sdk/CHANGELOG.md +++ b/packages/sdk/CHANGELOG.md @@ -5,10 +5,13 @@ ### Added - `Sepolia` testnet +- New method `getWithdrawalWaitingTimeByAmount` for fetching withdrawal waiting time for amount of eth +- New method `getWithdrawalWaitingTimeByRequestIds` for fetching withdrawal waiting time for earlier created requests by their ids ## Playground - Support for `Sepolia` testnet +- Added blocks with new methods `getWithdrawalWaitingTimeByAmount` and `getWithdrawalWaitingTimeByRequestIds` # 3.1.0 From 242310aae4fa5c849f74d89989deff1f5d83574d Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Tue, 26 Mar 2024 10:56:23 +0100 Subject: [PATCH 11/12] feat: added unsupported chain error --- packages/sdk/src/common/constants.ts | 3 ++- packages/sdk/src/withdraw/types.ts | 5 +++-- .../sdk/src/withdraw/withdraw-waiting-time.ts | 16 +++++++++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/sdk/src/common/constants.ts b/packages/sdk/src/common/constants.ts index 69fdc788..b81e29a9 100644 --- a/packages/sdk/src/common/constants.ts +++ b/packages/sdk/src/common/constants.ts @@ -112,8 +112,9 @@ export const VIEM_CHAINS: { [key in CHAINS]: Chain } = { [CHAINS.Sepolia]: sepolia, }; -export const WQ_API_URLS: { [key in CHAINS]: string } = { +export const WQ_API_URLS: { [key in CHAINS]: string | null } = { [CHAINS.Mainnet]: 'https://wq-api.lido.fi', [CHAINS.Goerli]: 'https://wq-api.testnet.fi', [CHAINS.Holesky]: 'https://wq-api-holesky.testnet.fi', + [CHAINS.Sepolia]: null, }; diff --git a/packages/sdk/src/withdraw/types.ts b/packages/sdk/src/withdraw/types.ts index 0ca5a4a3..9b6dea29 100644 --- a/packages/sdk/src/withdraw/types.ts +++ b/packages/sdk/src/withdraw/types.ts @@ -1,6 +1,7 @@ import type { Address } from 'viem'; import type { Bus } from './bus.js'; import type { AccountValue } from '../index.js'; +import { CHAINS } from '../index.js'; export type LidoSDKWithdrawModuleProps = { bus: Bus; version?: string }; @@ -53,8 +54,8 @@ export type GetWithdrawalRequestsInfoReturnType = { }; export type WqApiCustomUrlGetter = ( - defaultUrl: string, - chainId: number, + defaultUrl: string | null, + chainId: CHAINS, ) => string; export type WithdrawalWaitingTimeByAmountParams = { diff --git a/packages/sdk/src/withdraw/withdraw-waiting-time.ts b/packages/sdk/src/withdraw/withdraw-waiting-time.ts index 9ea924e4..5d02fb7c 100644 --- a/packages/sdk/src/withdraw/withdraw-waiting-time.ts +++ b/packages/sdk/src/withdraw/withdraw-waiting-time.ts @@ -91,8 +91,18 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { getBaseUrl(getCustomApiUrl?: WqApiCustomUrlGetter) { const defaultUrl = WQ_API_URLS[this.bus.core.chainId]; - return getCustomApiUrl && typeof getCustomApiUrl === 'function' - ? getCustomApiUrl(defaultUrl, this.bus.core.chainId) - : defaultUrl; + + const baseUrl = + getCustomApiUrl && typeof getCustomApiUrl === 'function' + ? getCustomApiUrl(defaultUrl, this.bus.core.chainId) + : defaultUrl; + + if (!baseUrl) { + throw new Error( + `wq-api URL is not found for chain ${this.bus.core.chainId}, use getCustomApiUrl prop to setup custom URL`, + ); + } + + return baseUrl; } } From 1a6bed030c56be07c3847d33b38c916d9ffa651b Mon Sep 17 00:00:00 2001 From: Taras Alekhin Date: Tue, 26 Mar 2024 12:50:54 +0100 Subject: [PATCH 12/12] fix: custom errors --- packages/sdk/src/withdraw/withdraw-waiting-time.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/sdk/src/withdraw/withdraw-waiting-time.ts b/packages/sdk/src/withdraw/withdraw-waiting-time.ts index 5d02fb7c..4727674f 100644 --- a/packages/sdk/src/withdraw/withdraw-waiting-time.ts +++ b/packages/sdk/src/withdraw/withdraw-waiting-time.ts @@ -8,7 +8,7 @@ import type { WithdrawalWaitingTimeByRequestIdsParams, WqApiCustomUrlGetter, } from './types.js'; -import { WQ_API_URLS } from '../common/index.js'; +import { ERROR_CODE, WQ_API_URLS } from '../common/index.js'; import { formatEther } from 'viem'; const endpoints = { @@ -51,7 +51,10 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { const getCustomApiUrl = props?.getCustomApiUrl; if (!Array.isArray(props.ids) || props.ids.length === 0) { - throw new Error('expected not empty array ids'); + throw this.bus.core.error({ + code: ERROR_CODE.INVALID_ARGUMENT, + message: 'expected not empty array ids', + }); } const idsPages = []; @@ -98,9 +101,10 @@ export class LidoSDKWithdrawWaitingTime extends BusModule { : defaultUrl; if (!baseUrl) { - throw new Error( - `wq-api URL is not found for chain ${this.bus.core.chainId}, use getCustomApiUrl prop to setup custom URL`, - ); + throw this.bus.core.error({ + code: ERROR_CODE.INVALID_ARGUMENT, + message: `wq-api URL is not found for chain ${this.bus.core.chainId}, use getCustomApiUrl prop to setup custom URL`, + }); } return baseUrl;