From 12b6a6523ebefaaf6381a69847a7718b15272442 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Thu, 25 Jul 2024 16:20:14 +0300 Subject: [PATCH 01/15] [vault create sdk] add vault create --- src/graphql/backend/vault/index.ts | 3 + .../vault/uploadMetadataMutation.graphql | 9 +++ .../vault/transactions/createVault/common.ts | 66 ++++++++++++++++ .../createVault/createVaultEncode.ts | 21 ++++++ .../createVault/createVaultGas.ts | 23 ++++++ .../vault/transactions/createVault/index.ts | 27 +++++++ .../vault/transactions/createVault/types.d.ts | 29 +++++++ .../createVault/validateCreateVaultArgs.ts | 75 +++++++++++++++++++ .../vault/transactions/operate/checkAccess.ts | 2 +- .../vault/transactions/operate/common.ts | 6 +- .../vault/transactions/operate/index.ts | 7 +- .../transactions/operate/multicallEncode.ts | 10 ++- .../transactions/operate/multicallGas.ts | 7 +- .../vault/transactions/operate/types.d.ts | 17 ++++- src/methods/vault/transactions/util/index.ts | 1 + .../metadata/getMetadataHashMock/index.ts | 17 +++++ .../vault/transactions/util/metadata/index.ts | 2 + .../util/metadata/uploadMetadata/index.ts | 39 ++++++++++ .../util/params/getMetadataParams.ts | 8 +- src/utils/enums.ts | 6 ++ 20 files changed, 357 insertions(+), 18 deletions(-) create mode 100644 src/graphql/backend/vault/uploadMetadataMutation.graphql create mode 100644 src/methods/vault/transactions/createVault/common.ts create mode 100644 src/methods/vault/transactions/createVault/createVaultEncode.ts create mode 100644 src/methods/vault/transactions/createVault/createVaultGas.ts create mode 100644 src/methods/vault/transactions/createVault/index.ts create mode 100644 src/methods/vault/transactions/createVault/types.d.ts create mode 100644 src/methods/vault/transactions/createVault/validateCreateVaultArgs.ts create mode 100644 src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts create mode 100644 src/methods/vault/transactions/util/metadata/index.ts create mode 100644 src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts diff --git a/src/graphql/backend/vault/index.ts b/src/graphql/backend/vault/index.ts index 00ce3b17..e589a5c8 100644 --- a/src/graphql/backend/vault/index.ts +++ b/src/graphql/backend/vault/index.ts @@ -9,3 +9,6 @@ export type { UserRewardsQueryPayload, UserRewardsQueryVariables } from './userR export { fetchScorePercentilesQuery } from './scorePercentilesQuery.graphql' export type { ScorePercentilesQueryPayload, ScorePercentilesQueryVariables } from './scorePercentilesQuery.graphql' + +export { submitUploadMetadataMutation } from './uploadMetadataMutation.graphql' +export type { UploadMetadataMutationPayload, UploadMetadataMutationVariables } from './uploadMetadataMutation.graphql' diff --git a/src/graphql/backend/vault/uploadMetadataMutation.graphql b/src/graphql/backend/vault/uploadMetadataMutation.graphql new file mode 100644 index 00000000..a752997a --- /dev/null +++ b/src/graphql/backend/vault/uploadMetadataMutation.graphql @@ -0,0 +1,9 @@ +mutation UploadMetadata ( + $payload: PayloadType! +) { + uploadMetadata( + payload: $payload + ) { + ipfsHash + } +} diff --git a/src/methods/vault/transactions/createVault/common.ts b/src/methods/vault/transactions/createVault/common.ts new file mode 100644 index 00000000..cd427d9e --- /dev/null +++ b/src/methods/vault/transactions/createVault/common.ts @@ -0,0 +1,66 @@ +import { AbiCoder, MaxUint256 } from 'ethers' +import type { CreateVaultTransactionInput } from './types' +import { validateArgs, VaultType } from '../../../../utils' +import validateCreateVaultArgs from './validateCreateVaultArgs' + + +export const commonLogic = async (values: CreateVaultTransactionInput) => { + const { + type = VaultType.Default, vaultToken, capacity, keysManagerFee, isOwnMevEscrow = false, metadataIpfsHash, + contracts, userAddress, + } = values + + validateArgs.address({ userAddress }) + validateCreateVaultArgs.vaultType(type) + validateCreateVaultArgs.mevEscrow(isOwnMevEscrow) + + if (vaultToken) { + validateCreateVaultArgs.vaultToken(vaultToken) + } + + if (capacity) { + validateArgs.bigint({ capacity }) + validateCreateVaultArgs.capacity(capacity) + } + + if (keysManagerFee) { + validateCreateVaultArgs.keysManagerFee(keysManagerFee) + } + + const vaultFactories = vaultToken ? { + [VaultType.Default]: contracts.factories.erc20Vault, + [VaultType.Private]: contracts.factories.erc20PrivateVault, + [VaultType.Blocklist]: contracts.factories.erc20BlocklistVault, + } : { + [VaultType.Default]: contracts.factories.vault, + [VaultType.Private]: contracts.factories.privateVault, + [VaultType.Blocklist]: contracts.factories.blocklistVault, + } + + const vaultFactory = vaultFactories[type] + const defaultAbiCoder = AbiCoder.defaultAbiCoder() + + const formattedParams = { + feePercent: (keysManagerFee || 0) * 100, + capacity: capacity || MaxUint256, + symbol: vaultToken?.symbol, + name: vaultToken?.name, + } + + const encodedParams = vaultToken + ? defaultAbiCoder.encode( + [ 'tuple(uint256 capacity, uint16 feePercent, string name, string symbol, string metadataIpfsHash)' ], + [ [ formattedParams.capacity, formattedParams.feePercent, formattedParams.name, formattedParams.symbol, metadataIpfsHash ] ] + ) + : defaultAbiCoder.encode( + [ 'tuple(uint256 capacity, uint16 feePercent, string metadataIpfsHash)' ], + [ [ formattedParams.capacity, formattedParams.feePercent, metadataIpfsHash ] ] + ) + + const params: [ string, boolean ] = [ encodedParams, isOwnMevEscrow ] + + return { + vaultFactory, + params, + } +} diff --git a/src/methods/vault/transactions/createVault/createVaultEncode.ts b/src/methods/vault/transactions/createVault/createVaultEncode.ts new file mode 100644 index 00000000..39be76b7 --- /dev/null +++ b/src/methods/vault/transactions/createVault/createVaultEncode.ts @@ -0,0 +1,21 @@ +import { commonLogic } from './common' +import type { CreateVaultInput } from './types' +import { getMetadataHashMock } from '../util' + + +const depositEncode = async (values: CreateVaultInput) => { + const { image, displayName, description, ...rest } = values + + const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) + + const rx = await vaultFactory.createVault.populateTransaction(...params) + + return { + to: rx.to, + data: rx.data, + } +} + + +export default depositEncode diff --git a/src/methods/vault/transactions/createVault/createVaultGas.ts b/src/methods/vault/transactions/createVault/createVaultGas.ts new file mode 100644 index 00000000..fe76aa7d --- /dev/null +++ b/src/methods/vault/transactions/createVault/createVaultGas.ts @@ -0,0 +1,23 @@ +import { commonLogic } from './common' +import { getGas } from '../../../../utils' +import type { CreateVaultInput } from './types' +import { getMetadataHashMock } from '../util' + + +const depositGas = async (values: CreateVaultInput) => { + const { image, displayName, description, ...rest } = values + const { provider, userAddress } = rest + + const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) + + const signer = await provider.getSigner(userAddress) + const signedContract = vaultFactory.connect(signer) + + const estimatedGas = await signedContract.createVault.estimateGas(...params) + + return getGas({ estimatedGas, provider }) +} + + +export default depositGas diff --git a/src/methods/vault/transactions/createVault/index.ts b/src/methods/vault/transactions/createVault/index.ts new file mode 100644 index 00000000..0f56011c --- /dev/null +++ b/src/methods/vault/transactions/createVault/index.ts @@ -0,0 +1,27 @@ +import { commonLogic } from './common' +import createVaultGas from './createVaultGas' +import createVaultEncode from './createVaultEncode' +import { uploadMetadata } from '../util' +import type { CreateVault } from './types' + + +const createVault: CreateVault = async (values) => { + const { image, displayName, description, ...rest } = values + const { provider, options, userAddress } = rest + + const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) + const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) + + const signer = await provider.getSigner(userAddress) + const signedContract = vaultFactory.connect(signer) + + const response = await signedContract.createVault(...params) + + return response.hash +} + +createVault.encode = createVaultEncode +createVault.estimateGas = createVaultGas + + +export default createVault diff --git a/src/methods/vault/transactions/createVault/types.d.ts b/src/methods/vault/transactions/createVault/types.d.ts new file mode 100644 index 00000000..489abd9e --- /dev/null +++ b/src/methods/vault/transactions/createVault/types.d.ts @@ -0,0 +1,29 @@ +import createVaultGas from './createVaultGas' +import createVaultEncode from './createVaultEncode' +import type { BaseInput } from '../../../utils' +import type { VaultType } from '../../../../utils' +import type { UploadMetadataInput } from '../util/metadata/uploadMetadata' + + +export type CreateVaultCommonInput = Omit & { + type?: VaultType + vaultToken?: { + name: string + symbol: string + } + capacity?: bigint + keysManagerFee?: number + isOwnMevEscrow?: boolean +} + +export type CreateVaultInput = CreateVaultCommonInput & UploadMetadataInput + +export type CreateVaultTransactionInput = CreateVaultCommonInput & { + metadataIpfsHash: string | null +} + +export interface CreateVault { + (values: CreateVaultInput): Promise + estimateGas: typeof createVaultGas + encode: typeof createVaultEncode +} diff --git a/src/methods/vault/transactions/createVault/validateCreateVaultArgs.ts b/src/methods/vault/transactions/createVault/validateCreateVaultArgs.ts new file mode 100644 index 00000000..46a1f8c6 --- /dev/null +++ b/src/methods/vault/transactions/createVault/validateCreateVaultArgs.ts @@ -0,0 +1,75 @@ +import { MaxUint256 } from 'ethers' +import { VaultType, constants } from '../../../../utils' + + +const capacity = (value: bigint) => { + if (value < constants.blockchain.amount32) { + throw new Error(`The "capacity" argument must be at least ${constants.blockchain.amount32}`) + } + if (value > MaxUint256) { + throw new Error(`The "capacity" argument must be at most ${MaxUint256}`) + } +} + +const mevEscrow = (value: unknown) => { + if (typeof value !== 'boolean') { + throw new Error(`The "isOwnMevEscrow" argument must be of boolean type`) + } +} + +const vaultType = (value: VaultType) => { + const vaultTypes = Object.values(VaultType) + const isValidType = vaultTypes.includes(value) + + if (!isValidType) { + throw new Error(`The "type" argument must be one of the following: ${vaultTypes.join(', ')}`) + } +} + +const vaultToken = (vaultToken: { name: string, symbol: string }) => { + if (typeof vaultToken !== 'object') { + throw new Error(`The "vaultToken" argument must be an object`) + } + + const missingParams = Object.keys(vaultToken) + .filter((key) => typeof vaultToken[key as keyof typeof vaultToken] !== 'string') + + if (missingParams.length) { + const args = missingParams.map((key) => `"vaultToken.${key}"`).join(', ') + + throw new Error(`The ${args} ${missingParams.length === 1 ? 'argument' : 'arguments'} must be a string`) + } + + const emptyParams = Object.keys(vaultToken) + .filter((key) => !vaultToken[key as keyof typeof vaultToken]) + + if (emptyParams.length) { + const args = emptyParams.map((key) => `"vaultToken.${key}"`).join(', ') + + throw new Error(`The ${args} ${missingParams.length === 1 ? 'argument' : 'arguments'} must be not empty string`) + } +} + +const keysManagerFee = (value: number) => { + if (value < 0) { + throw new Error(`The "capacity" argument must be at least 0`) + } + if (value > 100) { + throw new Error(`The "capacity" argument must be at most 100`) + } + + const decimals = value.toString().split('.')[1]?.length + + if (decimals > 2) { + throw new Error(`The "capacity" argument must have at most two decimal places`) + } +} + + +export default { + capacity, + mevEscrow, + vaultType, + vaultToken, + keysManagerFee, +} diff --git a/src/methods/vault/transactions/operate/checkAccess.ts b/src/methods/vault/transactions/operate/checkAccess.ts index debce8ff..e0cdcbac 100644 --- a/src/methods/vault/transactions/operate/checkAccess.ts +++ b/src/methods/vault/transactions/operate/checkAccess.ts @@ -1,4 +1,4 @@ -import type { MulticallInput as Input } from './types' +import type { MulticallTransactionInput as Input } from './types' import { checkAdminAccess, diff --git a/src/methods/vault/transactions/operate/common.ts b/src/methods/vault/transactions/operate/common.ts index ceb34766..bced37dd 100644 --- a/src/methods/vault/transactions/operate/common.ts +++ b/src/methods/vault/transactions/operate/common.ts @@ -1,4 +1,4 @@ -import type { MulticallInput } from './types' +import type { MulticallTransactionInput } from './types' import { validateArgs } from '../../../../utils' import { vaultMulticall } from '../../../../contracts' @@ -17,7 +17,7 @@ import { } from '../util' -export const commonLogic = async (values: MulticallInput) => { +export const commonLogic = async (values: MulticallTransactionInput) => { const { validatorsRoot, blocklistManager, metadataIpfsHash, blocklist, whitelist, depositDataManager, whitelistManager, feeRecipient, @@ -116,7 +116,7 @@ export const commonLogic = async (values: MulticallInput) => { params.push(...validatorsRootParams) } - if (metadataIpfsHash) { + if (typeof metadataIpfsHash !== 'undefined') { const metadataParams = getMetadataParams({ ...baseInput, metadataIpfsHash }) params.push(...metadataParams) diff --git a/src/methods/vault/transactions/operate/index.ts b/src/methods/vault/transactions/operate/index.ts index 1fecbeb6..ff3ca6a3 100644 --- a/src/methods/vault/transactions/operate/index.ts +++ b/src/methods/vault/transactions/operate/index.ts @@ -4,10 +4,15 @@ import type { Multicall } from './types' import multicallGas from './multicallGas' import multicallEncode from './multicallEncode' import { vaultMulticall } from '../../../../contracts' +import { uploadMetadata } from '../util' const operate: Multicall = async (values) => { - const multicallCommonArgs = await commonLogic(values) + const { image, displayName, description, ...rest } = values + const { options } = rest + + const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) + const multicallCommonArgs = await commonLogic({ metadataIpfsHash, ...rest }) const result = await vaultMulticall<{ hash: string }>(multicallCommonArgs) diff --git a/src/methods/vault/transactions/operate/multicallEncode.ts b/src/methods/vault/transactions/operate/multicallEncode.ts index a7317e32..d8221fe0 100644 --- a/src/methods/vault/transactions/operate/multicallEncode.ts +++ b/src/methods/vault/transactions/operate/multicallEncode.ts @@ -1,10 +1,14 @@ -import { getVaultMulticallEncode } from '../../../utils' -import type { MulticallInput } from './types' import { commonLogic } from './common' +import type { MulticallInput } from './types' +import { getMetadataHashMock } from '../util' +import { getVaultMulticallEncode } from '../../../utils' const multicallEncode = async (values: MulticallInput): Promise => { - const multicallArgs = await commonLogic(values) + const { image, displayName, description, ...rest } = values + + const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const multicallArgs = await commonLogic({ metadataIpfsHash, ...rest }) return getVaultMulticallEncode(multicallArgs) } diff --git a/src/methods/vault/transactions/operate/multicallGas.ts b/src/methods/vault/transactions/operate/multicallGas.ts index d5ced89f..e5999f22 100644 --- a/src/methods/vault/transactions/operate/multicallGas.ts +++ b/src/methods/vault/transactions/operate/multicallGas.ts @@ -1,12 +1,15 @@ import { commonLogic } from './common' import { getVaultMulticallGas } from '../../../utils' import type { MulticallInput } from './types' +import { getMetadataHashMock } from '../util' const multicallGas = async (props: MulticallInput) => { - const { provider } = props + const { image, displayName, description, ...rest } = props + const { provider } = rest - const multicallArgs = await commonLogic(props) + const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const multicallArgs = await commonLogic({ metadataIpfsHash, ...rest }) return getVaultMulticallGas({ ...multicallArgs, provider }) } diff --git a/src/methods/vault/transactions/operate/types.d.ts b/src/methods/vault/transactions/operate/types.d.ts index febd4948..f5ff00be 100644 --- a/src/methods/vault/transactions/operate/types.d.ts +++ b/src/methods/vault/transactions/operate/types.d.ts @@ -1,6 +1,7 @@ import multicallGas from './multicallGas' import multicallEncode from './multicallEncode' +import type { UploadMetadataInput } from '../util/metadata/uploadMetadata' import type { SetMetadataParams } from '../util/params/getMetadataParams' import type { UpdateBlocklistParams } from '../util/params/getBlocklistParams' import type { UpdateWhitelistParams } from '../util/params/getWhitelistParams' @@ -21,9 +22,8 @@ type BaseInput = { provider: StakeWise.Provider } -type MulticallParams = Partial< - SetMetadataParams - & SetWhitelisterParams +type MulticallCommonParams = + SetWhitelisterParams & SetFeeRecipientParams & UpdateBlocklistParams & UpdateWhitelistParams @@ -33,8 +33,19 @@ type MulticallParams = Partial< & SetDepositDataManagerParams & SetRestakeOperatorsManagerParams & SetRestakeWithdrawalsManagerParams + +type MulticallParams = Partial< + UploadMetadataInput + & MulticallCommonParams > +type MulticallTransactionParams = Partial< + SetMetadataParams + & MulticallCommonParams +> + +export type MulticallTransactionInput = BaseInput & MulticallTransactionParams + export type MulticallInput = BaseInput & MulticallParams export interface Multicall { diff --git a/src/methods/vault/transactions/util/index.ts b/src/methods/vault/transactions/util/index.ts index 97daeeb3..0c21970a 100644 --- a/src/methods/vault/transactions/util/index.ts +++ b/src/methods/vault/transactions/util/index.ts @@ -1,2 +1,3 @@ export * from './check' export * from './params' +export * from './metadata' diff --git a/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts b/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts new file mode 100644 index 00000000..374c43de --- /dev/null +++ b/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts @@ -0,0 +1,17 @@ +type Input = { + image?: string + displayName?: string + description?: string +} + + +const getMetadataHashMock = ({ image, displayName, description }: Input) => { + if (image || displayName || description) { + return '00000000000000000000000000000000000000000000000000000000000' + } + + return null +} + + +export default getMetadataHashMock diff --git a/src/methods/vault/transactions/util/metadata/index.ts b/src/methods/vault/transactions/util/metadata/index.ts new file mode 100644 index 00000000..5be77835 --- /dev/null +++ b/src/methods/vault/transactions/util/metadata/index.ts @@ -0,0 +1,2 @@ +export { default as uploadMetadata } from './uploadMetadata' +export { default as getMetadataHashMock } from './getMetadataHashMock' diff --git a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts new file mode 100644 index 00000000..fcbc5e4d --- /dev/null +++ b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts @@ -0,0 +1,39 @@ +import graphql from '../../../../../../graphql' +import { apiUrls, validateArgs } from '../../../../../../utils' + + +export type UploadMetadataInput = { + image?: string + displayName?: string + description?: string +} + +type Input = UploadMetadataInput & { + options: StakeWise.Options +} + +const uploadMetadata = async (input: Input) => { + const { image = '', displayName = '', description = '', options } = input + + validateArgs.string({ image, displayName, description }) + + if (image || displayName || description) { + const data = await graphql.backend.vault.submitUploadMetadataMutation({ + url: apiUrls.getBackendUrl(options), + variables: { + payload: { + image, + displayName, + description, + }, + }, + }) + + return data?.uploadMetadata?.ipfsHash + } + + return null +} + + +export default uploadMetadata diff --git a/src/methods/vault/transactions/util/params/getMetadataParams.ts b/src/methods/vault/transactions/util/params/getMetadataParams.ts index 64914de8..2a3d2476 100644 --- a/src/methods/vault/transactions/util/params/getMetadataParams.ts +++ b/src/methods/vault/transactions/util/params/getMetadataParams.ts @@ -1,16 +1,14 @@ -import { validateArgs } from '../../../../../utils' import { vaultMulticall } from '../../../../../contracts' -export type SetMetadataParams = { - metadataIpfsHash: string +type SetMetadataParams = { + metadataIpfsHash: string | null } const getMetadataParams = (values: SetMetadataParams) => { const { metadataIpfsHash } = values - validateArgs.string({ metadataIpfsHash }) - + // ATTN we don't validate `metadataIpfsHash` because it is not provided by user const params: Parameters[0]['request']['params'] = [ { method: 'setMetadata', args: [ metadataIpfsHash ], diff --git a/src/utils/enums.ts b/src/utils/enums.ts index beaee609..1e920aef 100644 --- a/src/utils/enums.ts +++ b/src/utils/enums.ts @@ -6,6 +6,12 @@ export enum Network { Chiado = 10200, } +export enum VaultType { + Default = 'Default', + Private = 'Private', + Blocklist = 'Blocklist', +} + export enum AllocatorActionType { Redeemed = 'Redeemed', Migrated = 'Migrated', From cd6ec1c1f169244b0ea072c72e269b34efa0dafc Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Mon, 29 Jul 2024 09:51:48 +0300 Subject: [PATCH 02/15] [vault create sdk] update vault create --- src/methods/index.ts | 11 ++++++++-- src/methods/vault/index.ts | 6 +++++ .../{createVault => create}/common.ts | 10 ++++++--- .../createVaultEncode.ts | 4 ++-- .../{createVault => create}/createVaultGas.ts | 4 ++-- .../create/createVaultStaticCall.ts | 22 +++++++++++++++++++ .../{createVault => create}/index.ts | 10 +++++---- .../{createVault => create}/types.d.ts | 2 ++ .../validateCreateVaultArgs.ts | 0 src/utils/constants/blockchain.ts | 1 + 10 files changed, 57 insertions(+), 13 deletions(-) rename src/methods/vault/transactions/{createVault => create}/common.ts (81%) rename src/methods/vault/transactions/{createVault => create}/createVaultEncode.ts (83%) rename src/methods/vault/transactions/{createVault => create}/createVaultGas.ts (88%) create mode 100644 src/methods/vault/transactions/create/createVaultStaticCall.ts rename src/methods/vault/transactions/{createVault => create}/index.ts (74%) rename src/methods/vault/transactions/{createVault => create}/types.d.ts (89%) rename src/methods/vault/transactions/{createVault => create}/validateCreateVaultArgs.ts (100%) diff --git a/src/methods/index.ts b/src/methods/index.ts index 59efac92..f8a44c53 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -21,6 +21,7 @@ interface UnknownMethod { (values: unknown): unknown encode?: (values: unknown) => unknown estimateGas?: (values: unknown) => unknown + staticCall?: (values: unknown) => unknown } type CheckArgs> = [keyof Obj] extends [never] ? [] : [Obj] @@ -41,9 +42,15 @@ type WithEstimateGas = WithEncode & { ) } +type WithStaticCall = WithEstimateGas & { + staticCall: (...values: CheckArgs>[0], 'options' | 'contracts' | 'provider'>>) => ( + ReturnType> + ) +} + type ModifiedMethod = 'encode' extends keyof M ? 'estimateGas' extends keyof M - ? WithEstimateGas + ? 'staticCall' extends keyof M ? WithStaticCall : WithEstimateGas : WithEncode : WithoutEncode @@ -60,7 +67,7 @@ type ModifyMethods> = { type CreateMethodsOutput = ModifyMethods const generateSubMethods = (fn: UnknownMethod, wrapper: UnknownMethod, params: CommonParams) => { - const submethods = [ 'encode', 'estimateGas' ] as const + const submethods = [ 'encode', 'estimateGas', 'staticCall' ] as const submethods.forEach((submethod) => { if (typeof fn[submethod] === 'function') { diff --git a/src/methods/vault/index.ts b/src/methods/vault/index.ts index 630eae7e..bedc4d42 100644 --- a/src/methods/vault/index.ts +++ b/src/methods/vault/index.ts @@ -15,6 +15,7 @@ import getScorePercentiles from './requests/getScorePercentiles' import getExitQueuePositions from './requests/getExitQueuePositions' // Transactions +import { default as create } from './transactions/create' import { default as deposit } from './transactions/deposit' import { default as operate } from './transactions/operate' import { default as withdraw } from './transactions/withdraw' @@ -131,6 +132,11 @@ export default { * @see https://github.com/stakewise/v3-sdk/?tab=readme-ov-file#sdkvaultoperate */ operate, + /** + * @description Create vault + * @see https://github.com/stakewise/v3-sdk/?tab=readme-ov-file#sdkvaultcreate + */ + create, /** * @description Adding root validators to vault * @throws Supports only the second version of vault diff --git a/src/methods/vault/transactions/createVault/common.ts b/src/methods/vault/transactions/create/common.ts similarity index 81% rename from src/methods/vault/transactions/createVault/common.ts rename to src/methods/vault/transactions/create/common.ts index cd427d9e..2f2f3d04 100644 --- a/src/methods/vault/transactions/createVault/common.ts +++ b/src/methods/vault/transactions/create/common.ts @@ -1,13 +1,14 @@ import { AbiCoder, MaxUint256 } from 'ethers' import type { CreateVaultTransactionInput } from './types' -import { validateArgs, VaultType } from '../../../../utils' +import { PayableOverrides } from '../../../../contracts/types/common' +import { constants, Network, validateArgs, VaultType } from '../../../../utils' import validateCreateVaultArgs from './validateCreateVaultArgs' export const commonLogic = async (values: CreateVaultTransactionInput) => { const { type = VaultType.Default, vaultToken, capacity, keysManagerFee, isOwnMevEscrow = false, metadataIpfsHash, - contracts, userAddress, + contracts, userAddress, options, } = values validateArgs.address({ userAddress }) @@ -57,7 +58,10 @@ export const commonLogic = async (values: CreateVaultTransactionInput) => { [ [ formattedParams.capacity, formattedParams.feePercent, metadataIpfsHash ] ] ) - const params: [ string, boolean ] = [ encodedParams, isOwnMevEscrow ] + const isStakeNativeToken = [ Network.Mainnet, Network.Holesky ].includes(options.network) + const params: [ string, boolean, PayableOverrides ] = isStakeNativeToken + ? [ encodedParams, isOwnMevEscrow, { value: constants.blockchain.gwei } ] + : [ encodedParams, isOwnMevEscrow, {} ] return { vaultFactory, diff --git a/src/methods/vault/transactions/createVault/createVaultEncode.ts b/src/methods/vault/transactions/create/createVaultEncode.ts similarity index 83% rename from src/methods/vault/transactions/createVault/createVaultEncode.ts rename to src/methods/vault/transactions/create/createVaultEncode.ts index 39be76b7..6fcff1e6 100644 --- a/src/methods/vault/transactions/createVault/createVaultEncode.ts +++ b/src/methods/vault/transactions/create/createVaultEncode.ts @@ -3,7 +3,7 @@ import type { CreateVaultInput } from './types' import { getMetadataHashMock } from '../util' -const depositEncode = async (values: CreateVaultInput) => { +const createVaultEncode = async (values: CreateVaultInput) => { const { image, displayName, description, ...rest } = values const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) @@ -18,4 +18,4 @@ const depositEncode = async (values: CreateVaultInput) => { } -export default depositEncode +export default createVaultEncode diff --git a/src/methods/vault/transactions/createVault/createVaultGas.ts b/src/methods/vault/transactions/create/createVaultGas.ts similarity index 88% rename from src/methods/vault/transactions/createVault/createVaultGas.ts rename to src/methods/vault/transactions/create/createVaultGas.ts index fe76aa7d..af76383c 100644 --- a/src/methods/vault/transactions/createVault/createVaultGas.ts +++ b/src/methods/vault/transactions/create/createVaultGas.ts @@ -4,7 +4,7 @@ import type { CreateVaultInput } from './types' import { getMetadataHashMock } from '../util' -const depositGas = async (values: CreateVaultInput) => { +const createVaultGas = async (values: CreateVaultInput) => { const { image, displayName, description, ...rest } = values const { provider, userAddress } = rest @@ -20,4 +20,4 @@ const depositGas = async (values: CreateVaultInput) => { } -export default depositGas +export default createVaultGas diff --git a/src/methods/vault/transactions/create/createVaultStaticCall.ts b/src/methods/vault/transactions/create/createVaultStaticCall.ts new file mode 100644 index 00000000..d537f694 --- /dev/null +++ b/src/methods/vault/transactions/create/createVaultStaticCall.ts @@ -0,0 +1,22 @@ +import { commonLogic } from './common' +import type { CreateVaultInput } from './types' +import { getMetadataHashMock } from '../util' + + +const createVaultStaticCall = async (values: CreateVaultInput) => { + const { image, displayName, description, ...rest } = values + const { provider, userAddress } = rest + + const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) + + const signer = await provider.getSigner(userAddress) + const signedContract = vaultFactory.connect(signer) + + const vaultAddress = await signedContract.createVault.staticCall(...params) + + return vaultAddress +} + + +export default createVaultStaticCall diff --git a/src/methods/vault/transactions/createVault/index.ts b/src/methods/vault/transactions/create/index.ts similarity index 74% rename from src/methods/vault/transactions/createVault/index.ts rename to src/methods/vault/transactions/create/index.ts index 0f56011c..6ad9ba65 100644 --- a/src/methods/vault/transactions/createVault/index.ts +++ b/src/methods/vault/transactions/create/index.ts @@ -1,11 +1,12 @@ import { commonLogic } from './common' import createVaultGas from './createVaultGas' import createVaultEncode from './createVaultEncode' +import createVaultStaticCall from './createVaultStaticCall' import { uploadMetadata } from '../util' import type { CreateVault } from './types' -const createVault: CreateVault = async (values) => { +const create: CreateVault = async (values) => { const { image, displayName, description, ...rest } = values const { provider, options, userAddress } = rest @@ -20,8 +21,9 @@ const createVault: CreateVault = async (values) => { return response.hash } -createVault.encode = createVaultEncode -createVault.estimateGas = createVaultGas +create.encode = createVaultEncode +create.estimateGas = createVaultGas +create.staticCall = createVaultStaticCall -export default createVault +export default create diff --git a/src/methods/vault/transactions/createVault/types.d.ts b/src/methods/vault/transactions/create/types.d.ts similarity index 89% rename from src/methods/vault/transactions/createVault/types.d.ts rename to src/methods/vault/transactions/create/types.d.ts index 489abd9e..a2edf025 100644 --- a/src/methods/vault/transactions/createVault/types.d.ts +++ b/src/methods/vault/transactions/create/types.d.ts @@ -1,5 +1,6 @@ import createVaultGas from './createVaultGas' import createVaultEncode from './createVaultEncode' +import createVaultStaticCall from './createVaultStaticCall' import type { BaseInput } from '../../../utils' import type { VaultType } from '../../../../utils' import type { UploadMetadataInput } from '../util/metadata/uploadMetadata' @@ -26,4 +27,5 @@ export interface CreateVault { (values: CreateVaultInput): Promise estimateGas: typeof createVaultGas encode: typeof createVaultEncode + staticCall: typeof createVaultStaticCall } diff --git a/src/methods/vault/transactions/createVault/validateCreateVaultArgs.ts b/src/methods/vault/transactions/create/validateCreateVaultArgs.ts similarity index 100% rename from src/methods/vault/transactions/createVault/validateCreateVaultArgs.ts rename to src/methods/vault/transactions/create/validateCreateVaultArgs.ts diff --git a/src/utils/constants/blockchain.ts b/src/utils/constants/blockchain.ts index 2c9486b5..e6fd45ae 100644 --- a/src/utils/constants/blockchain.ts +++ b/src/utils/constants/blockchain.ts @@ -3,6 +3,7 @@ export default { secondsInBlock: 13, blocksInYear: 2427458, secondsInYear: 31536000, + gwei: 1000000000n, amount0: 0n, amount1: 1000000000000000000n, amount10: 10000000000000000000n, From cd0d7bbee3a3c154bd6afcfb6ce21f3e69645f6f Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Mon, 29 Jul 2024 14:57:26 +0300 Subject: [PATCH 03/15] [vault create sdk] update vault create --- src/index.ts | 2 +- .../create/validateCreateVaultArgs.ts | 6 ++--- src/utils/getVaultFactory.ts | 25 +++++++++++++++++++ src/utils/index.ts | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/utils/getVaultFactory.ts diff --git a/src/index.ts b/src/index.ts index a408c66f..72b8d900 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,6 @@ import { constants } from './utils' export * from './utils/enums' export { createContract } from './contracts' export { default as StakeWiseSDK } from './StakeWiseSDK' -export { BigDecimal, configs, getGas, createProvider } from './utils' +export { BigDecimal, configs, getGas, createProvider, getVaultFactory } from './utils' export const chains = constants.chains diff --git a/src/methods/vault/transactions/create/validateCreateVaultArgs.ts b/src/methods/vault/transactions/create/validateCreateVaultArgs.ts index 46a1f8c6..5de07e72 100644 --- a/src/methods/vault/transactions/create/validateCreateVaultArgs.ts +++ b/src/methods/vault/transactions/create/validateCreateVaultArgs.ts @@ -52,16 +52,16 @@ const vaultToken = (vaultToken: { name: string, symbol: string }) => { const keysManagerFee = (value: number) => { if (value < 0) { - throw new Error(`The "capacity" argument must be at least 0`) + throw new Error(`The "keysManagerFee" argument must be at least 0`) } if (value > 100) { - throw new Error(`The "capacity" argument must be at most 100`) + throw new Error(`The "keysManagerFee" argument must be at most 100`) } const decimals = value.toString().split('.')[1]?.length if (decimals > 2) { - throw new Error(`The "capacity" argument must have at most two decimal places`) + throw new Error(`The "keysManagerFee" argument must have at most two decimal places`) } } diff --git a/src/utils/getVaultFactory.ts b/src/utils/getVaultFactory.ts new file mode 100644 index 00000000..f5607332 --- /dev/null +++ b/src/utils/getVaultFactory.ts @@ -0,0 +1,25 @@ +import { VaultType } from './enums' + + +type Input = { + vaultType: VaultType + contracts: StakeWise.Contracts + isErc20?: boolean +} + +const getVaultFactory = ({ vaultType, contracts, isErc20 }: Input) => { + const vaultFactories = isErc20 ? { + [VaultType.Default]: contracts.factories.erc20Vault, + [VaultType.Private]: contracts.factories.erc20PrivateVault, + [VaultType.Blocklist]: contracts.factories.erc20BlocklistVault, + } : { + [VaultType.Default]: contracts.factories.vault, + [VaultType.Private]: contracts.factories.privateVault, + [VaultType.Blocklist]: contracts.factories.blocklistVault, + } + + return vaultFactories[vaultType] +} + + +export default getVaultFactory diff --git a/src/utils/index.ts b/src/utils/index.ts index 41a9f10d..28644fab 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -8,4 +8,5 @@ export { default as BigDecimal } from './BigDecimal' export { default as validateArgs } from './validateArgs' export { default as createProvider } from './createProvider' export { default as getNetworkTypes } from './getNetworkTypes' +export { default as getVaultFactory } from './getVaultFactory' export { default as getValidLtvPercent } from './getValidLtvPercent' From d5539619218be5256b19d32492cc3edecfb27b87 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Mon, 29 Jul 2024 17:10:09 +0300 Subject: [PATCH 04/15] [vault create sdk] update vault create --- .../mutationTemplate.ts | 24 +++++++++++-- .../util/metadata/uploadMetadata/index.ts | 36 +++++++++++++------ src/utils/validateArgs.ts | 22 ++++++++++++ 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/scripts/generateGraphqlExports/mutationTemplate.ts b/scripts/generateGraphqlExports/mutationTemplate.ts index 4ef33bc9..5905107d 100644 --- a/scripts/generateGraphqlExports/mutationTemplate.ts +++ b/scripts/generateGraphqlExports/mutationTemplate.ts @@ -7,14 +7,34 @@ type SubmitInput = { variables: {QueryName}Variables } +type Output = { + data: {QueryName}Payload + errors?: { + path: string[] + message: string + extensions: { + code: string + } + }[] +} + const submit{QueryName} = ({ variables, url }: SubmitInput) => fetch(url, { method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, body: JSON.stringify({ query, variables, }) }) - .then((res) => res.json() as Promise<{ data: {QueryName}Payload }>) - .then(({ data }) => data) + .then((res) => res.json() as Promise) + .then(({ data, errors }) => { + if (!errors) { + return data + } + + return Promise.reject(errors) + }) ` diff --git a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts index fcbc5e4d..b2abfd2c 100644 --- a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts +++ b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts @@ -15,21 +15,37 @@ type Input = UploadMetadataInput & { const uploadMetadata = async (input: Input) => { const { image = '', displayName = '', description = '', options } = input + if (image) { + validateArgs.image(image) + } + + validateArgs.maxLength({ + displayName: { value: displayName, length: 30 }, + description: { value: description, length: 1000 }, + }) + validateArgs.string({ image, displayName, description }) if (image || displayName || description) { - const data = await graphql.backend.vault.submitUploadMetadataMutation({ - url: apiUrls.getBackendUrl(options), - variables: { - payload: { - image, - displayName, - description, + try { + const data = await graphql.backend.vault.submitUploadMetadataMutation({ + url: apiUrls.getBackendUrl(options), + variables: { + payload: { + image, + displayName, + description, + }, }, - }, - }) + }) + + return data?.uploadMetadata?.ipfsHash + } + catch (error) { + const errorCode = Array.isArray(error) ? error[0]?.extensions?.code : null - return data?.uploadMetadata?.ipfsHash + return Promise.reject(errorCode || error) + } } return null diff --git a/src/utils/validateArgs.ts b/src/utils/validateArgs.ts index 71a264a8..e3d946b7 100644 --- a/src/utils/validateArgs.ts +++ b/src/utils/validateArgs.ts @@ -1,6 +1,17 @@ import { isAddress } from 'ethers' +const image = (value: string) => { + const decode = value?.substring(value.indexOf(',') + 1) + const sizeMB = decode ? atob(decode).length / 1000 / 1000 : 0 + + if (sizeMB > 1) { + const currentSize = sizeMB.toFixed(2) + + throw new Error(`The size of the image must be under 1 MB, current size is ${currentSize} MB`) + } +} + const bigint = (values: Record) => { Object.keys(values).forEach((key) => { if (typeof values[key] !== 'bigint') { @@ -44,11 +55,22 @@ const array = (values: Record, withEmptyCheck: boolean = true) => }) } +const maxLength = (values: Record) => { + Object.keys(values).forEach((key) => { + const { value, length } = values[key] + if (value.length > length) { + throw new Error(`The value for "${key}" argument must be less than ${length} characters`) + } + }) +} + export default { + image, array, bigint, string, number, address, + maxLength, } From d8a6cec38b3142a166b4910139b4ea7ee3da5062 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Mon, 29 Jul 2024 17:36:58 +0300 Subject: [PATCH 05/15] [vault create sdk] update static call --- src/methods/vault/transactions/create/createVaultStaticCall.ts | 3 ++- .../transactions/util/metadata/getMetadataHashMock/index.ts | 2 +- .../vault/transactions/util/metadata/uploadMetadata/index.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/methods/vault/transactions/create/createVaultStaticCall.ts b/src/methods/vault/transactions/create/createVaultStaticCall.ts index d537f694..49d36687 100644 --- a/src/methods/vault/transactions/create/createVaultStaticCall.ts +++ b/src/methods/vault/transactions/create/createVaultStaticCall.ts @@ -1,3 +1,4 @@ +import { ethers } from 'ethers' import { commonLogic } from './common' import type { CreateVaultInput } from './types' import { getMetadataHashMock } from '../util' @@ -10,7 +11,7 @@ const createVaultStaticCall = async (values: CreateVaultInput) => { const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) - const signer = await provider.getSigner(userAddress) + const signer = new ethers.VoidSigner(userAddress, provider) const signedContract = vaultFactory.connect(signer) const vaultAddress = await signedContract.createVault.staticCall(...params) diff --git a/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts b/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts index 374c43de..9fe9eabb 100644 --- a/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts +++ b/src/methods/vault/transactions/util/metadata/getMetadataHashMock/index.ts @@ -10,7 +10,7 @@ const getMetadataHashMock = ({ image, displayName, description }: Input) => { return '00000000000000000000000000000000000000000000000000000000000' } - return null + return '' } diff --git a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts index b2abfd2c..415f21e0 100644 --- a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts +++ b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts @@ -48,7 +48,7 @@ const uploadMetadata = async (input: Input) => { } } - return null + return '' } From c6ed761f05948e3d2eb2b15e692187f587795538 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 10:35:36 +0300 Subject: [PATCH 06/15] [vault create sdk] update readme --- README.md | 116 ++++++++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 2 files changed, 97 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 08993543..abf93669 100644 --- a/README.md +++ b/README.md @@ -130,9 +130,10 @@ promise.abort() ##### Table of transactions: | **Vault** | **RewardSplitter** | **osToken** | |-------------------------------------------------------------------|---------------------------------------------------------------------------------|-------------------------------------| -| [sdk.vault.deposit](#sdkvaultdeposit) | [sdk.rewardSplitter.create](#sdkrewardsplittercreate) | [sdk.osToken.mint](#sdkostokenmint) | -| [sdk.vault.withdraw](#sdkvaultwithdraw) | [sdk.rewardSplitter.claimRewards](#sdkrewardsplitterclaimrewards) | [sdk.osToken.burn](#sdkostokenburn) | -| [sdk.vault.operate](#sdkvaultoperate) | [sdk.rewardSplitter.updateFeeRecipients](#sdkrewardsplitterupdatefeerecipients) | | +| [sdk.vault.create](#sdkvaultcreate) | [sdk.rewardSplitter.create](#sdkrewardsplittercreate) | [sdk.osToken.mint](#sdkostokenmint) | +| [sdk.vault.deposit](#sdkvaultdeposit) | [sdk.rewardSplitter.claimRewards](#sdkrewardsplitterclaimrewards) | [sdk.osToken.burn](#sdkostokenburn) | +| [sdk.vault.withdraw](#sdkvaultwithdraw) | [sdk.rewardSplitter.updateFeeRecipients](#sdkrewardsplitterupdatefeerecipients) | | +| [sdk.vault.operate](#sdkvaultoperate) | | | | [sdk.vault.setDepositDataManager](#sdkvaultsetdepositdatamanager) | | | | [sdk.vault.setDepositDataRoot](#sdkvaultsetdepositdataroot) | | | | [sdk.claimExitQueue](#sdkvaultclaimexitqueue) | | | @@ -1133,6 +1134,78 @@ await sdk.utils.getTransactions({ hash: '0x...' }) Transactions work through the provider you sent when creating an instance of our SDK class. Or, if you are a custodian, you can get the transaction data and sign it yourself. Each transaction also gives you the opportunity to get an approximate gas for sending it. For custodians, it is more reliable to calculate the gas yourself. Each transaction has encode and estimateGas methods for your convenience +### `sdk.vault.create` + +#### Description: + +Create a vault. When the transaction is executed, one gwei of the deposit token must be stored in the vault to avoid [inflation attack](https://blog.openzeppelin.com/a-novel-defense-against-erc4626-inflation-attacks). +Pay attention to chains where the deposit token is not a native token (such as Gnosis or Chiado). +Before creating the vault, we should approve this amount to the `vaultFactory`. + +#### Arguments: + +| Name | Type | Required | Description | +|----------------|------------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | +| type | `VaultType` | **No** | Allowed vault types: Default, Private, or Blocklist. Available vault types can be found in the `enum VaultType` which you can be imported from the library | +| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | +| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | +| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | +| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | +| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | + +#### Example: + +```ts +const params = { + userAddress: '0x...', + type: VaultType.Default, + vaultToken: { + name: 'Vault Token', + symbol: 'vlt', + }, + capacity: MaxUint256, + keysManagerFee: 0, + isOwnMevEscrow: false, + image: 'data:image/png;base64,...', + displayName: 'Example vault', + description: 'Example description', +} + +// Approve example (only for chains where the deposit token is not a native token) +import { getVaultFactory } from 'sdk' + +if (sdk.config.tokens.depositToken !== sdk.config.tokens.nativeToken) { + const signer = await sdk.provider.getSigner() + const tokenContract = sdk.contracts.helpers.createErc20(tokenAddress).connect(signer) + const vaultFactory = getVaultFactory({ + vaultType: params.type, + isErc20: Boolean(params.vaultToken), + contracts: sdk.contracts, + }) + const vaultFactoryAddress = await vaultFactory.getAddress() + const gwei = 1000000000n + + // Send approve transactions for the vault factory + const { hash: approvalHash } = await signedContract.approve(vaultFactoryAddress, gwei) +} + +// Transaction example +// Send transaction to create a vault +const hash = await sdk.vault.create(params) +// When you sign transactions on the backend (for custodians) +const { data, to, value } = await sdk.vault.deposit.encode(params) +// Get an approximate gas per transaction +const gas = await sdk.vault.deposit.estimateGas(params) +// Get vault address before the transaction is sent +// Note: To make this call on chains where the deposit token is not a native token (e.g., Gnosis, Chiado), +// please ensure you use an address that has already approved the token. +// For example, this address can be used for this call: `0xb5afcEbCA5C1A55E149b4DDF02B9681541Dd29D6` +const vaultAddress = await sdk.vault.create.staticCall(params) +``` +--- ### `sdk.vault.deposit` #### Description: @@ -1434,21 +1507,23 @@ Updates the vault by authorized personnel such as the vault admin, whitelistMana #### Arguments: -| Name | Type | Required | Access | Description | -|------------------|----------------------------------------------|----------|-------------------|-----------------------------------------------------------------------------------------------------------------------------| -| whitelistManager | `Array<{ address: string, isNew: boolean }>` | **No** | whitelistManager | List of addresses to update the whitelist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | -| blocklist | `Array<{ address: string, isNew: boolean }>` | **No** | Blocklist manager | List of addresses to update the blocklist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | -| depositDataManager | `string` | **No** | Deposit-data manager | Address of the vault keys manager. Support only **first version** on valults. For second verion use `vault.setDepositDataManager` | -| validatorsManager | `string` | **No** | Admin | Address of the vault deposit data manager. Support only **second version** on valults. | -| restakeWithdrawalsManager | `string` | **No** | Admin | The restake withdrawals manager must be assigned to the wallet connected to the operator service. It is responsible for withdrawing exiting validators from the EigenLayer. | -| restakeOperatorsManager | `string` | **No** | Admin | The restake operators manager can add EigenPods and update EigenLayer operators. | -| whitelistManager | `string` | **No** | Admin | Address of the vault whitelistManager | -| feeRecipient | `string` | **No** | Admin | Address of the vault fee recipient | -| validatorsRoot | `string` | **No** | Keys manager | The vault validators merkle tree root. Support only **first version** on valults. For second verion use `vault.setDepositDataRoot` | -| blocklistManager | `string` | **No** | Admin | The blocklisted vault blocklist manager | -| metadataIpfsHash | `string` | **No** | Admin | The vault metadata IPFS hash | -| userAddress | `string` | **Yes** | - | The address of the user making the update (admin, whitelist manager, blocklist manager or keys manager) | -| vaultAddress | `string` | **Yes** | - | The address of the vault | +| Name | Type | Required | Access | Description | +|---------------------------|----------------------------------------------|----------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| whitelistManager | `Array<{ address: string, isNew: boolean }>` | **No** | whitelistManager | List of addresses to update the whitelist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | +| blocklist | `Array<{ address: string, isNew: boolean }>` | **No** | Blocklist manager | List of addresses to update the blocklist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | +| depositDataManager | `string` | **No** | Deposit-data manager | Address of the vault keys manager. Support only **first version** on valults. For second verion use `vault.setDepositDataManager` | +| validatorsManager | `string` | **No** | Admin | Address of the vault deposit data manager. Support only **second version** on valults. | +| restakeWithdrawalsManager | `string` | **No** | Admin | The restake withdrawals manager must be assigned to the wallet connected to the operator service. It is responsible for withdrawing exiting validators from the EigenLayer. | +| restakeOperatorsManager | `string` | **No** | Admin | The restake operators manager can add EigenPods and update EigenLayer operators. | +| whitelistManager | `string` | **No** | Admin | Address of the vault whitelistManager | +| feeRecipient | `string` | **No** | Admin | Address of the vault fee recipient | +| validatorsRoot | `string` | **No** | Keys manager | The vault validators merkle tree root. Support only **first version** on valults. For second verion use `vault.setDepositDataRoot` | +| blocklistManager | `string` | **No** | Admin | The blocklisted vault blocklist manager | +| image | `string` | **No** | Admin | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | Admin | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | Admin | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | +| userAddress | `string` | **Yes** | - | The address of the user making the update (admin, whitelist manager, blocklist manager or keys manager) | +| vaultAddress | `string` | **Yes** | - | The address of the vault | #### Example: @@ -1457,8 +1532,10 @@ Updates the vault by authorized personnel such as the vault admin, whitelistMana const params = { userAddress: '0x...', vaultAddress: '0x...', + image: '...', + displayName: '...', + description: '...', feeRecipient: '0x...', - metadataIpfsHash: '...', validatorsRoot: '0x...', blocklistManager: '0x...', whitelistManager: '0x...', @@ -1466,7 +1543,6 @@ const params = { depositDataManager: '0x...', restakeOperatorsManager: '0x...', restakeWithdrawalsManager: '0x...', - } // Data to update the vault by vault keys manager. diff --git a/package.json b/package.json index a19101cb..642a1df5 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.3.1", + "version": "1.3.2", "sideEffects": false, "main": "dist/index.js", "types": "dist/index.d.ts", From 8dd3575621a31eca9946987291bb42afa976e715 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 11:10:01 +0300 Subject: [PATCH 07/15] [vault create sdk] update next release --- changelog/next-release.md | 110 ++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 16 deletions(-) diff --git a/changelog/next-release.md b/changelog/next-release.md index 927d9f86..4c078a0d 100644 --- a/changelog/next-release.md +++ b/changelog/next-release.md @@ -6,6 +6,9 @@ If the directory does not contain any .graphql files, it is deleted along with a - Refactor **multicall** contracts. Implement new **commonMulticall**, **vaultMulticall**, **eigenPodOwnerMulticall**, **rewardSplitterMulticall**. - Implement new logic for **encode** & **estimateGas** to all transaction methods - Add new check access utils methods: `checkAdminAccess | checkBlocklistManagerAccess | checkDepositDataManagerAccess | checkRestakeOperatorsManagerAccess | checkWhitelisterAccess`, to more thoroughly verify access for vault transactions +- Add the sdk.vault.create method +- Add a getVaultFactory helper to retrieve the vault factory contract based on the provided vault type and ERC20 token availability +- Update the sdk.vault.operate method to accept `image`, `displayName`, and `description` instead of `metadataIpfsHash` # Updates @@ -318,21 +321,23 @@ Updates the vault by authorized personnel such as the vault admin, whitelistMana #### Arguments: -| Name | Type | Required | Access | Description | -|------------------|----------------------------------------------|----------|-------------------|-----------------------------------------------------------------------------------------------------------------------------| -| whitelistManager | `Array<{ address: string, isNew: boolean }>` | **No** | whitelistManager | List of addresses to update the whitelist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | -| blocklist | `Array<{ address: string, isNew: boolean }>` | **No** | Blocklist manager | List of addresses to update the blocklist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | -| depositDataManager | `string` | **No** | Deposit-data manager | Address of the vault keys manager. Support only **first version** on valults. For second verion use `vault.setDepositDataManager` | -| validatorsManager | `string` | **No** | Admin | Address of the vault deposit data manager. Support only **second version** on valults. | -| restakeWithdrawalsManager | `string` | **No** | Admin | The restake withdrawals manager must be assigned to the wallet connected to the operator service. It is responsible for withdrawing exiting validators from the EigenLayer. | -| restakeOperatorsManager | `string` | **No** | Admin | The restake operators manager can add EigenPods and update EigenLayer operators. | -| whitelistManager | `string` | **No** | Admin | Address of the vault whitelistManager | -| feeRecipient | `string` | **No** | Admin | Address of the vault fee recipient | -| validatorsRoot | `string` | **No** | Keys manager | The vault validators merkle tree root. Support only **first version** on valults. For second verion use `vault.setDepositDataRoot` | -| blocklistManager | `string` | **No** | Admin | The blocklisted vault blocklist manager | -| metadataIpfsHash | `string` | **No** | Admin | The vault metadata IPFS hash | -| userAddress | `string` | **Yes** | - | The address of the user making the update (admin, whitelist manager, blocklist manager or keys manager) | -| vaultAddress | `string` | **Yes** | - | The address of the vault | +| Name | Type | Required | Access | Description | +|---------------------------|----------------------------------------------|----------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| whitelistManager | `Array<{ address: string, isNew: boolean }>` | **No** | whitelistManager | List of addresses to update the whitelist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | +| blocklist | `Array<{ address: string, isNew: boolean }>` | **No** | Blocklist manager | List of addresses to update the blocklist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | +| depositDataManager | `string` | **No** | Deposit-data manager | Address of the vault keys manager. Support only **first version** on valults. For second verion use `vault.setDepositDataManager` | +| validatorsManager | `string` | **No** | Admin | Address of the vault deposit data manager. Support only **second version** on valults. | +| restakeWithdrawalsManager | `string` | **No** | Admin | The restake withdrawals manager must be assigned to the wallet connected to the operator service. It is responsible for withdrawing exiting validators from the EigenLayer. | +| restakeOperatorsManager | `string` | **No** | Admin | The restake operators manager can add EigenPods and update EigenLayer operators. | +| whitelistManager | `string` | **No** | Admin | Address of the vault whitelistManager | +| feeRecipient | `string` | **No** | Admin | Address of the vault fee recipient | +| validatorsRoot | `string` | **No** | Keys manager | The vault validators merkle tree root. Support only **first version** on valults. For second verion use `vault.setDepositDataRoot` | +| blocklistManager | `string` | **No** | Admin | The blocklisted vault blocklist manager | +| image | `string` | **No** | Admin | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | Admin | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | Admin | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | +| userAddress | `string` | **Yes** | - | The address of the user making the update (admin, whitelist manager, blocklist manager or keys manager) | +| vaultAddress | `string` | **Yes** | - | The address of the vault | #### Example: @@ -341,8 +346,10 @@ Updates the vault by authorized personnel such as the vault admin, whitelistMana const params = { userAddress: '0x...', vaultAddress: '0x...', + image: '...', + displayName: '...', + description: '...', feeRecipient: '0x...', - metadataIpfsHash: '...', validatorsRoot: '0x...', blocklistManager: '0x...', whitelistManager: '0x...', @@ -572,3 +579,74 @@ const { data, to } = await sdk.rewardSplitter.updateFeeRecipients.encode(params) const gas = await sdk.rewardSplitter.updateFeeRecipients.estimateGas(params) ``` --- +### `sdk.vault.create` + +#### Description: + +Create a vault. When the transaction is executed, one gwei of the deposit token must be stored in the vault to avoid [inflation attack](https://blog.openzeppelin.com/a-novel-defense-against-erc4626-inflation-attacks). +Pay attention to chains where the deposit token is not a native token (such as Gnosis or Chiado). +Before creating the vault, we should approve this amount to the `vaultFactory`. + +#### Arguments: + +| Name | Type | Required | Description | +|----------------|------------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | +| type | `VaultType` | **No** | Allowed vault types: Default, Private, or Blocklist. Available vault types can be found in the `enum VaultType` which you can be imported from the library | +| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | +| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | +| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | +| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | +| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | + +#### Example: + +```ts +const params = { + userAddress: '0x...', + type: VaultType.Default, + vaultToken: { + name: 'Vault Token', + symbol: 'vlt', + }, + capacity: MaxUint256, + keysManagerFee: 0, + isOwnMevEscrow: false, + image: 'data:image/png;base64,...', + displayName: 'Example vault', + description: 'Example description', +} + +// Approve example (only for chains where the deposit token is not a native token) +import { getVaultFactory } from 'sdk' + +if (sdk.config.tokens.depositToken !== sdk.config.tokens.nativeToken) { + const signer = await sdk.provider.getSigner() + const tokenContract = sdk.contracts.helpers.createErc20(tokenAddress).connect(signer) + const vaultFactory = getVaultFactory({ + vaultType: params.type, + isErc20: Boolean(params.vaultToken), + contracts: sdk.contracts, + }) + const vaultFactoryAddress = await vaultFactory.getAddress() + const gwei = 1000000000n + + // Send approve transactions for the vault factory + const { hash: approvalHash } = await signedContract.approve(vaultFactoryAddress, gwei) +} + +// Transaction example +// Send transaction to create a vault +const hash = await sdk.vault.create(params) +// When you sign transactions on the backend (for custodians) +const { data, to, value } = await sdk.vault.deposit.encode(params) +// Get an approximate gas per transaction +const gas = await sdk.vault.deposit.estimateGas(params) +// Get vault address before the transaction is sent +// Note: To make this call on chains where the deposit token is not a native token (e.g., Gnosis, Chiado), +// please ensure you use an address that has already approved the token. +// For example, this address can be used for this call: `0xb5afcEbCA5C1A55E149b4DDF02B9681541Dd29D6` +const vaultAddress = await sdk.vault.create.staticCall(params) +``` From 47100c7b81e2d8c5b7a1e52adf01961b429ba975 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 12:23:05 +0300 Subject: [PATCH 08/15] [vault create sdk] update sdk --- .../util/metadata/uploadMetadata/index.ts | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts index 415f21e0..89ba4456 100644 --- a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts +++ b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts @@ -26,29 +26,25 @@ const uploadMetadata = async (input: Input) => { validateArgs.string({ image, displayName, description }) - if (image || displayName || description) { - try { - const data = await graphql.backend.vault.submitUploadMetadataMutation({ - url: apiUrls.getBackendUrl(options), - variables: { - payload: { - image, - displayName, - description, - }, + try { + const data = await graphql.backend.vault.submitUploadMetadataMutation({ + url: apiUrls.getBackendUrl(options), + variables: { + payload: { + image, + displayName, + description, }, - }) + }, + }) - return data?.uploadMetadata?.ipfsHash - } - catch (error) { - const errorCode = Array.isArray(error) ? error[0]?.extensions?.code : null - - return Promise.reject(errorCode || error) - } + return data?.uploadMetadata?.ipfsHash } + catch (error) { + const errorCode = Array.isArray(error) ? error[0]?.extensions?.code : null - return '' + return Promise.reject(errorCode || error) + } } From 803bb8d06636190302ba9b27e5d93dbd50f0a94e Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 12:43:27 +0300 Subject: [PATCH 09/15] [vault create sdk] update readme --- README.md | 24 +- changelog/next-release.md | 595 +------------------------------------- src/StakeWiseSDK.ts | 11 +- src/index.ts | 2 +- 4 files changed, 25 insertions(+), 607 deletions(-) diff --git a/README.md b/README.md index abf93669..e8eb661d 100644 --- a/README.md +++ b/README.md @@ -1140,7 +1140,10 @@ Transactions work through the provider you sent when creating an instance of our Create a vault. When the transaction is executed, one gwei of the deposit token must be stored in the vault to avoid [inflation attack](https://blog.openzeppelin.com/a-novel-defense-against-erc4626-inflation-attacks). Pay attention to chains where the deposit token is not a native token (such as Gnosis or Chiado). -Before creating the vault, we should approve this amount to the `vaultFactory`. +On these chains before creating the vault, ensure that you call the `approve` function on the deposit token contract, +allowing the vault factory address to spend one gwei. +You can retrieve the vault factory contract using the helper function: `sdk.getVaultFactory({ vaultType: params.type, isErc20: params.isErc20 })`. + #### Arguments: @@ -1174,24 +1177,6 @@ const params = { description: 'Example description', } -// Approve example (only for chains where the deposit token is not a native token) -import { getVaultFactory } from 'sdk' - -if (sdk.config.tokens.depositToken !== sdk.config.tokens.nativeToken) { - const signer = await sdk.provider.getSigner() - const tokenContract = sdk.contracts.helpers.createErc20(tokenAddress).connect(signer) - const vaultFactory = getVaultFactory({ - vaultType: params.type, - isErc20: Boolean(params.vaultToken), - contracts: sdk.contracts, - }) - const vaultFactoryAddress = await vaultFactory.getAddress() - const gwei = 1000000000n - - // Send approve transactions for the vault factory - const { hash: approvalHash } = await signedContract.approve(vaultFactoryAddress, gwei) -} - // Transaction example // Send transaction to create a vault const hash = await sdk.vault.create(params) @@ -1202,7 +1187,6 @@ const gas = await sdk.vault.deposit.estimateGas(params) // Get vault address before the transaction is sent // Note: To make this call on chains where the deposit token is not a native token (e.g., Gnosis, Chiado), // please ensure you use an address that has already approved the token. -// For example, this address can be used for this call: `0xb5afcEbCA5C1A55E149b4DDF02B9681541Dd29D6` const vaultAddress = await sdk.vault.create.staticCall(params) ``` --- diff --git a/changelog/next-release.md b/changelog/next-release.md index 4c078a0d..b7cf26cc 100644 --- a/changelog/next-release.md +++ b/changelog/next-release.md @@ -1,591 +1,35 @@ -- Update **eslint** -> 8.56.0 -- Update **node** version -> 20.12.2 -- Update Backend GraphQ **url** -> "https://holesky-api.stakewise.io/graphql" -- Add removeOldFiles helper. The removeOldFiles function deletes all files with the extension .graphql.ts in subdirectories of the specified directory, if there is no corresponding file with the extension .graphql. -If the directory does not contain any .graphql files, it is deleted along with all its contents. -- Refactor **multicall** contracts. Implement new **commonMulticall**, **vaultMulticall**, **eigenPodOwnerMulticall**, **rewardSplitterMulticall**. -- Implement new logic for **encode** & **estimateGas** to all transaction methods -- Add new check access utils methods: `checkAdminAccess | checkBlocklistManagerAccess | checkDepositDataManagerAccess | checkRestakeOperatorsManagerAccess | checkWhitelisterAccess`, to more thoroughly verify access for vault transactions - Add the sdk.vault.create method - Add a getVaultFactory helper to retrieve the vault factory contract based on the provided vault type and ERC20 token availability - Update the sdk.vault.operate method to accept `image`, `displayName`, and `description` instead of `metadataIpfsHash` # Updates - -### sdk.vault.getExitQueuePositions - -#### Returns: -```ts -type Output = { - ...oldOutput, - duration: number | null -} -``` -| Name | Description | -|------|-----------------------| -| `duration` | Total queue duration time (in seconds).
- It represents the approximate time after which the assets can be collected (in seconds).
- If the value is null, the time is still being calculated.
- If the value is 0, the assets are available and can be collected. (New*) | ---- -### sdk.vault.getVault - -#### Returns: -```ts -type Output = { - ...oldOutput, - version: number - isRestake: boolean - whitelistManager: string - depositDataManager: string - restakeOperatorsManager: string - restakeWithdrawalsManager: string -} -``` - -| Name | Description | Status | -|--------------------|------------------|----------------| -| `whitelister` | - | **Deprecated!** | -| `vaultKeysManager` | - | **Deprecated!** | -| `version` | Vault version (1 or 2) | **New** | -| `isRestake` | Indicates whether the Vault is a restaking vault | **New** | -| `whitelistManager` | Whitelist | **New** | -| `depositDataManager` | Keys | **New** | -| `restakeOperatorsManager` | If the Vault is a restaking vault, restake operators manager can add/remove restake operators | **New** | -| `restakeWithdrawalsManager` | If the Vault is a restaking vault, restake withdrawals manager can manage EigenLayer withdrawals | **New** | ---- -### sdk.vault.getMaxWithdraw - -#### New arguments: -| Name | Type | Required | Info | -|------|------|-------------|-------| -| vaultAddress | `bigint` | **Yes** | Address of vault | - ---- -### sdk.vault.updateWhitelist **Deprecated!** -#### Description: -Use **sdk.vault.operate** instead - ---- -### sdk.vault.updateBlocklist **Deprecated!** -#### Description: -Use **sdk.vault.operate** instead - ---- ---- -## osToken -### sdk.osToken.getBurnAmount - -#### New arguments: -| Name | Type | Required | Info | -|------|------|-------------|-------| -| vaultAddress | `string` | **Yes** | Address of vault | - ---- -### sdk.osToken.getMaxMint - -#### New arguments: -| Name | Type | Required | Info | -|------|------|-------------|-------| -| vaultAddress | `string` | **Yes** | Address of vault | - ---- -### sdk.osToken.getBaseData **Deprecated!** -#### Description: -Use **osToken.getConfig** and **osToken.getRate** - ---- - -# New -## Vault -### sdk.vault.getRewardSplitters - -Fetch the list of created reward splitters. A reward splitter is a contract designed to distribute vault rewards among multiple fee recipients in predefined proportions. -To use a reward splitter, its address should be added to the vault as a fee recipient. - -#### Arguments: -| Name | Type | Type | Description | -|------|----------|---------|--------------------------------------------------------------------------------------------------------------------------------------------| -| vaultAddress | `string` | **Yes** | The address of the vault | -| owner | `string` | **Yes** | The owner of the reward splitter | -| rewardSplitterAddress | `string` | **No** | The address of the reward splitter (optional) | - -#### Returns: -```ts -type FeeRecipient = { - shares: bigint - percent: number - address: string -} - -type RewardSplitter = { - owner: string - address: string - totalShares: bigint - feeRecipients: FeeRecipient[] -} - -type Output = { - rewardSplitters: RewardSplitter[] -} -``` -| Name | Description | -|-------------------|-------------| -| `rewardSplitters` | An array of objects representing the result of the query based on your parameters | | ---- -### sdk.vault.getEigenPods - -Returns eigen pods for restake vault. - -#### Arguments: -| Name | Type | Required | Description | -|------|------|----------|-------------| -| vaultAddress | `string` | **Yes** | The address of the vault | -| limit | `number` | **No** | Limits the number of eigen pods returned. Defaults to 100 | -| skip | `number` | **No** | Skips the specified number of eigen pods. Defaults to 0 | - -#### Returns: -```ts -type Output = { - link: string - owner: string - operator: string - restaked: string - createdAt: number - podAddress: string -} -``` -| Name | Description | -|-------------|---------------------------------| -| `createdAt` | Date of Creation | -| `link` | Link to beaconchain | -| `operator` | The eigenPod's operator | -| `podAddress` | The eigenPod's address | -| `restaked` | EgenPod's restaked (in ETH) | -| `owner` | The address of the eigen pod owner | ---- - -### sdk.vault.setDepositDataRoot - -#### Description: - -Adding root validators to vaults **version 2** or higher - -#### Arguments: - -| Name | Type | Required | Description | -|----------------|----------|----------|-------------| -| validatorsRoot | `string` | **Yes** | The vault validators merkle tree | -| userAddress | `string` | **Yes** | - | -| vaultAddress | `string` | **Yes** | - | - -#### Example: - -```ts -const params = { - validatorsRoot: 'hash', - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Send transaction -const hash = await sdk.vault.setDepositDataRoot(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.vault.setDepositDataRoot.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.vault.setDepositDataRoot.estimateGas(params) -``` ---- -### sdk.vault.setDepositDataManager - -#### Description: - -Adding deposit data manager to vaults **version 2** or higher - -#### Arguments: - -| Name | Type | Required | Description | -|----------------|----------|----------|-------------| -| managerAddress | `string` | **Yes** | New deposit-data manager | -| userAddress | `string` | **Yes** | - | -| vaultAddress | `string` | **Yes** | - | - -#### Example: - -```ts -const params = { - managerAddress: '0x...', - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Send transaction -const hash = await sdk.vault.setDepositDataManager(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.vault.setDepositDataManager.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.vault.setDepositDataManager.estimateGas(params) -``` ---- -### sdk.vault.createEigenPod - -#### Description: - -Adding eigen pod to the vault. Only for restake vaults and only restake operators manager can perform this action. - -#### Arguments: - -| Name | Type | Required | Description | -|----------------|----------|----------|-----------| -| userAddress | `string` | **Yes** | The address of the user making the request | -| vaultAddress | `string` | **Yes** | The address of the vault | - -#### Example: - -```ts -const params = { - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Send transaction -const hash = await sdk.vault.createEigenPod(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.vault.createEigenPod.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.vault.createEigenPod.estimateGas(params) -``` ---- -### sdk.vault.setEigenPodOperator - -#### Description: - -Adding operator to the current eigen pod. This action is specific to restake vaults and can only be executed by the restake operators manager. - -#### Arguments: - -| Name | Type | Required | Description | -|----------------|----------|----------|----------------------------------| -| userAddress | `string` | **Yes** | The address of the user making the request | -| vaultAddress | `string` | **Yes** | The address of the vault | -| ownerAddress | `string` | **Yes** | The address of the eigen pod owner | -| operatorAddress | `string` | **Yes** | New operator for current eigen pods | - -#### Example: - -```ts -const params = { - operatorAddress: '0x...', -} - -// Send transaction -const hash = await sdk.vault.setEigenPodOperator(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.vault.setEigenPodOperator.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.vault.setEigenPodOperator.estimateGas(params) -``` ---- -### sdk.vault.updateEigenPodOperator - -#### Description: - -Update operator to the current eigen pod. This action is specific to restake vaults and can only be executed by the restake operators manager. - -#### Arguments: - -| Name | Type | Required | Description | -|----------------|----------|----------|----------------------------------| -| userAddress | `string` | **Yes** | The address of the user making the request | -| vaultAddress | `string` | **Yes** | The address of the vault | -| ownerAddress | `string` | **Yes** | The address of the eigen pod owner | -| operatorAddress | `string` | **Yes** | New operator for current eigen pods | - -#### Example: - -```ts -const params = { - operatorAddress: '0x...', -} - -// Send transaction -const hash = await sdk.vault.updateEigenPodOperator(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.vault.updateEigenPodOperator.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.vault.updateEigenPodOperator.estimateGas(params) -``` ---- ### sdk.vault.operate -#### Description: +#### Removed arguments: -Updates the vault by authorized personnel such as the vault admin, whitelistManager, blocklist manager, validators manager, or deposit-data manager. +| Name | Type | Required | Access | Description | +|------------------|----------|----------|--------|------------------------------| +| metadataIpfsHash | `string` | **No** | Admin | The vault metadata IPFS hash | -#### Arguments: +#### New arguments: | Name | Type | Required | Access | Description | |---------------------------|----------------------------------------------|----------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| whitelistManager | `Array<{ address: string, isNew: boolean }>` | **No** | whitelistManager | List of addresses to update the whitelist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | -| blocklist | `Array<{ address: string, isNew: boolean }>` | **No** | Blocklist manager | List of addresses to update the blocklist. Use `isNew: true` to add a new address, `isNew: false` to remove an existing one. Max count at time - 700 addresses. | -| depositDataManager | `string` | **No** | Deposit-data manager | Address of the vault keys manager. Support only **first version** on valults. For second verion use `vault.setDepositDataManager` | -| validatorsManager | `string` | **No** | Admin | Address of the vault deposit data manager. Support only **second version** on valults. | -| restakeWithdrawalsManager | `string` | **No** | Admin | The restake withdrawals manager must be assigned to the wallet connected to the operator service. It is responsible for withdrawing exiting validators from the EigenLayer. | -| restakeOperatorsManager | `string` | **No** | Admin | The restake operators manager can add EigenPods and update EigenLayer operators. | -| whitelistManager | `string` | **No** | Admin | Address of the vault whitelistManager | -| feeRecipient | `string` | **No** | Admin | Address of the vault fee recipient | -| validatorsRoot | `string` | **No** | Keys manager | The vault validators merkle tree root. Support only **first version** on valults. For second verion use `vault.setDepositDataRoot` | -| blocklistManager | `string` | **No** | Admin | The blocklisted vault blocklist manager | | image | `string` | **No** | Admin | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | | displayName | `string` | **No** | Admin | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | | description | `string` | **No** | Admin | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | -| userAddress | `string` | **Yes** | - | The address of the user making the update (admin, whitelist manager, blocklist manager or keys manager) | -| vaultAddress | `string` | **Yes** | - | The address of the vault | -#### Example: -```ts -// Data to update the vault by admin. -const params = { - userAddress: '0x...', - vaultAddress: '0x...', - image: '...', - displayName: '...', - description: '...', - feeRecipient: '0x...', - validatorsRoot: '0x...', - blocklistManager: '0x...', - whitelistManager: '0x...', - validatorsManager: '0x...', - depositDataManager: '0x...', - restakeOperatorsManager: '0x...', - restakeWithdrawalsManager: '0x...', - -} - -// Data to update the vault by vault keys manager. -const params = { - validatorsRoot: '...', - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Data to update the private vault by whitelist manager. -// The whitelist contains addresses allowed to stake or mint within -// the vault. -const params = { - whitelist: [ - { - address: '0x...', - isNew: true, - }, - { - address: '0x...', - isNew: false, - }, - ], - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Data to update blocklisted vault by blocklist manager. -// The blocklist contains addresses disallowed to stake or mint within -// the vault. -const params = { - blocklist: [ - { - address: '0x...', - isNew: true, - }, - { - address: '0x...', - isNew: false, - }, - ], - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Send transaction -const hash = await sdk.vault.operate(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.vault.operate.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.vault.operate.estimateGas(params) -``` - ---- -### sdk.osToken.getRate - -Returns ETH - osToken rate - -#### Returns: -```ts -type Output = string -``` ---- -### sdk.osToken.getConfig - -#### Description: -Basic information on the token - -#### Arguments: -| Name | Type | Required | Description | -|--------------|----------|----------|---------------| -| vaultAddress | `string` | **Yes** | Vault address | -#### Returns: -```ts -type Output = { - ltvPercent: bigint - thresholdPercent: bigint -} -``` -| Name | Description | -|------|-------------| -| `ltvPercent` | The percent used to calculate how much user can mint OsToken shares | -| `thresholdPercent` | The liquidation threshold percent used to calculate health factor for OsToken position | ---- -## RewardSplitter -### sdk.rewardSplitter.getClaimAmount - -#### Description: -Calculates the amount of assets that the user can claim from the reward splitter. - -#### Arguments: -| Name | Type | Required | Description | -|-----------------------|----------|----------|--------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user making the request | -| vaultAddress | `string` | **Yes** | The address of the vault | -| rewardSplitterAddress | `string` | **Yes** | The address of the reward splitter | - -#### Returns: -```ts -type Output = bigint -``` ---- -### sdk.rewardSplitter.create - -#### Description: -Creates a reward splitter contract to distribute vault rewards among multiple fee recipients in predefined proportions. -Subsequently, the address of the created reward splitter must be added to the vault as a fee recipient in order to -utilize it. Please note that only vault admin is permitted to perform this action. - -#### Arguments: -| Name | Type | Required | Description | -|--------------|----------|----------|--------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the owner of the reward splitter and must be the vault admin | -| vaultAddress | `string` | **Yes** | The address of the vault | - -#### Example: - -```ts -const params = { - vaultAddress: '0x...', - userAddress: '0x...', -} - -// Send transaction -const hash = await sdk.rewardSplitter.create(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.rewardSplitter.create.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.rewardSplitter.create.estimateGas(params) -``` ---- -### sdk.rewardSplitter.claimRewards - -#### Description: - -Claims rewards from the reward splitter contract - -#### Arguments: -| Name | Type | Required | Description | -|-----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the owner of the reward splitter and must be the vault admin | -| vaultAddress | `string` | **Yes** | The address of the vault | -| rewardSplitterAddress | `string` | **Yes** | The address of the reward splitter | -| assets | `bigint` | **Yes** | The amount of assets to claim | - -#### Example: - -```ts -const params = { - vaultAddress: '0x...', - userAddress: '0x...', - rewardSplitterAddress: '0x...', - assets: parseEther('100'), -} - -// Send transaction -const hash = await sdk.rewardSplitter.claimRewards(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.rewardSplitter.claimRewards.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.rewardSplitter.claimRewards.estimateGas(params) -``` ---- -### sdk.rewardSplitter.updateFeeRecipients - -#### Description: - -Updates the reward splitter fee recipients and predefined fee splitting proportions. -Please note that only the vault admin, who is also the owner of the reward splitter, is permitted to perform this action. - -#### Arguments: - -| Name | Type | Required | Description | -|-----------------------|----------------------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. It should be the vault admin, who is also the owner of the reward splitter. | -| vaultAddress | `string` | **Yes** | The address of the vault | -| rewardSplitterAddress | `string` | **Yes** | The address of the reward splitter | -| feeRecipients | `Array<{ address: string, shares: bigint }>` | **Yes** | The list of the vault fee recipients with their addresses and shares amount. For simplicity, we suggest setting the amount as a percentage converted to a BigInt value. For example, for 100% shares: `parseEther('100')` | -| oldFeeRecipients | `Array<{ address: string, shares: bigint }>` | **No** | The current list of the vault fee recipients that will be updated within this action. It is needed to calculate how many shares will be added or removed from each fee recipient. If not provided, it will be requested from the [sdk.vault.getRewardSplitters](#sdkvaultgetrewardsplitters) action | - -#### Example: - -```ts -const params = { - vaultAddress: '0x...', - userAddress: '0x...', - rewardSplitterAddress: '0x...', - feeRecipients: [ - { - address: '0x...1', // The fee for this address will be increased from 20% to 50%. - shares: parseEther('50'), - }, - { - address: '0x...4', // This address will be added as a fee recipient with 50% fee distribution. - shares: parseEther('50'), - }, - ], - oldFeeRecipients: [ - { - address: '0x...1', // The fee for this address will be increased from 20% to 50%. - shares: parseEther('20'), - }, - { - address: '0x...2', // This address will be removed from the fee recipients since it is not in the `feeRecipients` list. - shares: parseEther('40'), - }, - { - address: '0x...3', // This address will also be removed from the fee recipients. - shares: parseEther('40'), - }, - ], -} - -// Send transaction -const hash = await sdk.rewardSplitter.updateFeeRecipients(params) -// When you sign transactions on the backend (for custodians) -const { data, to } = await sdk.rewardSplitter.updateFeeRecipients.encode(params) -// Get an approximate gas per transaction -const gas = await sdk.rewardSplitter.updateFeeRecipients.estimateGas(params) -``` ---- +# New ### `sdk.vault.create` #### Description: Create a vault. When the transaction is executed, one gwei of the deposit token must be stored in the vault to avoid [inflation attack](https://blog.openzeppelin.com/a-novel-defense-against-erc4626-inflation-attacks). Pay attention to chains where the deposit token is not a native token (such as Gnosis or Chiado). -Before creating the vault, we should approve this amount to the `vaultFactory`. +On these chains before creating the vault, ensure that you call the `approve` function on the deposit token contract, +allowing the vault factory address to spend one gwei. +You can retrieve the vault factory contract using the helper function: `sdk.getVaultFactory({ vaultType: params.type, isErc20: params.isErc20 })`. #### Arguments: @@ -619,24 +63,6 @@ const params = { description: 'Example description', } -// Approve example (only for chains where the deposit token is not a native token) -import { getVaultFactory } from 'sdk' - -if (sdk.config.tokens.depositToken !== sdk.config.tokens.nativeToken) { - const signer = await sdk.provider.getSigner() - const tokenContract = sdk.contracts.helpers.createErc20(tokenAddress).connect(signer) - const vaultFactory = getVaultFactory({ - vaultType: params.type, - isErc20: Boolean(params.vaultToken), - contracts: sdk.contracts, - }) - const vaultFactoryAddress = await vaultFactory.getAddress() - const gwei = 1000000000n - - // Send approve transactions for the vault factory - const { hash: approvalHash } = await signedContract.approve(vaultFactoryAddress, gwei) -} - // Transaction example // Send transaction to create a vault const hash = await sdk.vault.create(params) @@ -647,6 +73,5 @@ const gas = await sdk.vault.deposit.estimateGas(params) // Get vault address before the transaction is sent // Note: To make this call on chains where the deposit token is not a native token (e.g., Gnosis, Chiado), // please ensure you use an address that has already approved the token. -// For example, this address can be used for this call: `0xb5afcEbCA5C1A55E149b4DDF02B9681541Dd29D6` const vaultAddress = await sdk.vault.create.staticCall(params) -``` +``` \ No newline at end of file diff --git a/src/StakeWiseSDK.ts b/src/StakeWiseSDK.ts index 335c3127..9a27c083 100644 --- a/src/StakeWiseSDK.ts +++ b/src/StakeWiseSDK.ts @@ -1,8 +1,9 @@ import methods from './methods' -import { configs, getGas, createProvider } from './utils' +import { configs, getGas, createProvider, getVaultFactory, VaultType } from './utils' import { createContracts, vaultMulticall, rewardSplitterMulticall } from './contracts' +type GetVaultFactoryInput = { vaultType: VaultType, isErc20?: boolean } type VaultMulticallInput = Pick[0], 'request' | 'userAddress' | 'vaultAddress'> type RewardSplitterMulticallInput = Pick[0], 'request' | 'userAddress' | 'vaultAddress'> & { rewardSplitterAddress: string @@ -38,6 +39,14 @@ class StakeWiseSDK { this.rewardSplitter = methods.createRewardSplitterMethods(argsForMethods) } + getVaultFactory({ vaultType, isErc20 }: GetVaultFactoryInput) { + return getVaultFactory({ + vaultType, + isErc20, + contracts: this.contracts, + }) + } + vaultMulticall({ userAddress, vaultAddress, request }: VaultMulticallInput) { return vaultMulticall({ vaultContract: this.contracts.helpers.createVault(vaultAddress), diff --git a/src/index.ts b/src/index.ts index 72b8d900..a408c66f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,6 @@ import { constants } from './utils' export * from './utils/enums' export { createContract } from './contracts' export { default as StakeWiseSDK } from './StakeWiseSDK' -export { BigDecimal, configs, getGas, createProvider, getVaultFactory } from './utils' +export { BigDecimal, configs, getGas, createProvider } from './utils' export const chains = constants.chains From 9cd4d6f7c67e0936d2a8593979d03c578a280923 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 12:55:26 +0300 Subject: [PATCH 10/15] [vault create sdk] update readme --- README.md | 22 +++++++++---------- changelog/next-release.md | 22 +++++++++---------- .../transactions/create/createVaultEncode.ts | 5 +++-- .../transactions/operate/multicallEncode.ts | 5 +++-- src/utils/enums.ts | 2 +- src/utils/getVaultFactory.ts | 4 ++-- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index e8eb661d..16b1e442 100644 --- a/README.md +++ b/README.md @@ -1147,17 +1147,17 @@ You can retrieve the vault factory contract using the helper function: `sdk.getV #### Arguments: -| Name | Type | Required | Description | -|----------------|------------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | -| type | `VaultType` | **No** | Allowed vault types: Default, Private, or Blocklist. Available vault types can be found in the `enum VaultType` which you can be imported from the library | -| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | -| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | -| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | -| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | -| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | -| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | -| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | +| Name | Type | Required | Description | +|----------------|------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | +| type | `VaultType` | **No** | Allowed vault types: Default, Private. Available vault types can be found in the `enum VaultType` which you can be imported from the library | +| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | +| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | +| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | +| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | +| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | #### Example: diff --git a/changelog/next-release.md b/changelog/next-release.md index b7cf26cc..f2028d7c 100644 --- a/changelog/next-release.md +++ b/changelog/next-release.md @@ -33,17 +33,17 @@ You can retrieve the vault factory contract using the helper function: `sdk.getV #### Arguments: -| Name | Type | Required | Description | -|----------------|------------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | -| type | `VaultType` | **No** | Allowed vault types: Default, Private, or Blocklist. Available vault types can be found in the `enum VaultType` which you can be imported from the library | -| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | -| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | -| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | -| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | -| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | -| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | -| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | +| Name | Type | Required | Description | +|----------------|------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | +| type | `VaultType` | **No** | Allowed vault types: Default, Private. Available vault types can be found in the `enum VaultType` which you can be imported from the library | +| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | +| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | +| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | +| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | +| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | #### Example: diff --git a/src/methods/vault/transactions/create/createVaultEncode.ts b/src/methods/vault/transactions/create/createVaultEncode.ts index 6fcff1e6..c29e08d5 100644 --- a/src/methods/vault/transactions/create/createVaultEncode.ts +++ b/src/methods/vault/transactions/create/createVaultEncode.ts @@ -1,12 +1,13 @@ import { commonLogic } from './common' import type { CreateVaultInput } from './types' -import { getMetadataHashMock } from '../util' +import { uploadMetadata } from '../util' const createVaultEncode = async (values: CreateVaultInput) => { const { image, displayName, description, ...rest } = values + const { options } = rest - const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) const rx = await vaultFactory.createVault.populateTransaction(...params) diff --git a/src/methods/vault/transactions/operate/multicallEncode.ts b/src/methods/vault/transactions/operate/multicallEncode.ts index d8221fe0..205c85f4 100644 --- a/src/methods/vault/transactions/operate/multicallEncode.ts +++ b/src/methods/vault/transactions/operate/multicallEncode.ts @@ -1,13 +1,14 @@ import { commonLogic } from './common' import type { MulticallInput } from './types' -import { getMetadataHashMock } from '../util' +import { uploadMetadata } from '../util' import { getVaultMulticallEncode } from '../../../utils' const multicallEncode = async (values: MulticallInput): Promise => { const { image, displayName, description, ...rest } = values + const { options } = rest - const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) + const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) const multicallArgs = await commonLogic({ metadataIpfsHash, ...rest }) return getVaultMulticallEncode(multicallArgs) diff --git a/src/utils/enums.ts b/src/utils/enums.ts index 1e920aef..ed73878c 100644 --- a/src/utils/enums.ts +++ b/src/utils/enums.ts @@ -9,7 +9,7 @@ export enum Network { export enum VaultType { Default = 'Default', Private = 'Private', - Blocklist = 'Blocklist', + // Blocklist = 'Blocklist', } export enum AllocatorActionType { diff --git a/src/utils/getVaultFactory.ts b/src/utils/getVaultFactory.ts index f5607332..d1417086 100644 --- a/src/utils/getVaultFactory.ts +++ b/src/utils/getVaultFactory.ts @@ -11,11 +11,11 @@ const getVaultFactory = ({ vaultType, contracts, isErc20 }: Input) => { const vaultFactories = isErc20 ? { [VaultType.Default]: contracts.factories.erc20Vault, [VaultType.Private]: contracts.factories.erc20PrivateVault, - [VaultType.Blocklist]: contracts.factories.erc20BlocklistVault, + // [VaultType.Blocklist]: contracts.factories.erc20BlocklistVault, } : { [VaultType.Default]: contracts.factories.vault, [VaultType.Private]: contracts.factories.privateVault, - [VaultType.Blocklist]: contracts.factories.blocklistVault, + // [VaultType.Blocklist]: contracts.factories.blocklistVault, } return vaultFactories[vaultType] From c6f49d8b799c3fba2a4ed383f0c23ad5ead39147 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 13:15:14 +0300 Subject: [PATCH 11/15] [vault create sdk] update blocklist --- README.md | 22 +++++++++++----------- changelog/next-release.md | 22 +++++++++++----------- src/utils/enums.ts | 2 +- src/utils/getVaultFactory.ts | 4 ++-- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 16b1e442..9aa3f7e2 100644 --- a/README.md +++ b/README.md @@ -1147,17 +1147,17 @@ You can retrieve the vault factory contract using the helper function: `sdk.getV #### Arguments: -| Name | Type | Required | Description | -|----------------|------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | -| type | `VaultType` | **No** | Allowed vault types: Default, Private. Available vault types can be found in the `enum VaultType` which you can be imported from the library | -| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | -| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | -| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | -| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | -| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | -| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | -| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | +| Name | Type | Required | Description | +|----------------|------------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | +| type | `VaultType` | **No** | Allowed vault types: Default, Private and Blocklist. Available vault types can be found in the `enum VaultType` which you can be imported from the library | +| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | +| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | +| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | +| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | +| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | #### Example: diff --git a/changelog/next-release.md b/changelog/next-release.md index f2028d7c..f0556ee2 100644 --- a/changelog/next-release.md +++ b/changelog/next-release.md @@ -33,17 +33,17 @@ You can retrieve the vault factory contract using the helper function: `sdk.getV #### Arguments: -| Name | Type | Required | Description | -|----------------|------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| -| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | -| type | `VaultType` | **No** | Allowed vault types: Default, Private. Available vault types can be found in the `enum VaultType` which you can be imported from the library | -| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | -| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | -| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | -| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | -| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | -| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | -| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | +| Name | Type | Required | Description | +|----------------|------------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| userAddress | `string` | **Yes** | The address of the user initiating the action. This address will become the vault admin | +| type | `VaultType` | **No** | Allowed vault types: Default, Private and Blocklist. Available vault types can be found in the `enum VaultType` which you can be imported from the library | +| vaultToken | `{ name: string, symbol: string }` | **No** | If provided, the vault will be created with its own ERC20 token | +| capacity | `bigint` | **No** | If provided, should be defined in gwei. By default, capacity is `MaxUint256`; the minimum allowed capacity is `parseEther('32')` | +| keysManagerFee | `number` | **No** | If provided, should be between `0` and `100`, inclusive with a maximum of two decimal digits allowed (e.g., `15.35`). By default, the fee is `0` | +| isOwnMevEscrow | `boolean` | **No** | Defines whether to send block rewards to the Smoothing Pool (`false`) or keep them only to your Vault (`true`). By default, this value is `false` | +| image | `string` | **No** | The vault image in base64 string format (will be uploaded to IPFS; maximum size is 1 MB) | +| displayName | `string` | **No** | The vault display name (will be uploaded to IPFS; maximum size is 30 characters) | +| description | `string` | **No** | The vault description (will be uploaded to IPFS; maximum size is 1000 characters) | #### Example: diff --git a/src/utils/enums.ts b/src/utils/enums.ts index ed73878c..1e920aef 100644 --- a/src/utils/enums.ts +++ b/src/utils/enums.ts @@ -9,7 +9,7 @@ export enum Network { export enum VaultType { Default = 'Default', Private = 'Private', - // Blocklist = 'Blocklist', + Blocklist = 'Blocklist', } export enum AllocatorActionType { diff --git a/src/utils/getVaultFactory.ts b/src/utils/getVaultFactory.ts index d1417086..f5607332 100644 --- a/src/utils/getVaultFactory.ts +++ b/src/utils/getVaultFactory.ts @@ -11,11 +11,11 @@ const getVaultFactory = ({ vaultType, contracts, isErc20 }: Input) => { const vaultFactories = isErc20 ? { [VaultType.Default]: contracts.factories.erc20Vault, [VaultType.Private]: contracts.factories.erc20PrivateVault, - // [VaultType.Blocklist]: contracts.factories.erc20BlocklistVault, + [VaultType.Blocklist]: contracts.factories.erc20BlocklistVault, } : { [VaultType.Default]: contracts.factories.vault, [VaultType.Private]: contracts.factories.privateVault, - // [VaultType.Blocklist]: contracts.factories.blocklistVault, + [VaultType.Blocklist]: contracts.factories.blocklistVault, } return vaultFactories[vaultType] From dca03ac59d22871ee58d38b2b856332e84ecf511 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 15:42:09 +0300 Subject: [PATCH 12/15] [vault create sdk] update encode --- README.md | 4 ---- changelog/next-release.md | 4 ---- src/StakeWiseSDK.ts | 2 +- .../multicall/util/handleTransactionData.ts | 7 +----- src/methods/index.ts | 11 ++------- .../osToken/transactions/burn/burnEncode.ts | 7 +----- .../claimRewards/claimRewardsEncode.ts | 7 +----- .../createRewardSplitterEncode.ts | 7 +----- .../updateFeeRecipientsEncode.ts | 7 +----- src/methods/utils/getVaultMulticallEncode.ts | 7 +----- .../transactions/create/createVaultEncode.ts | 7 +----- .../create/createVaultStaticCall.ts | 23 ------------------- .../vault/transactions/create/index.ts | 2 -- .../vault/transactions/create/types.d.ts | 2 -- .../createEigenPod/createEigenPodEncode.ts | 7 +----- .../setDepositDataManagerEncode.ts | 7 +----- .../setDepositDataRootEncode.ts | 7 +----- .../setEigenPodOperatorEncode.ts | 7 +----- .../updateEigenPodOperatorEncode.ts | 7 +----- src/utils/getVaultFactory.ts | 4 ++-- 20 files changed, 17 insertions(+), 119 deletions(-) delete mode 100644 src/methods/vault/transactions/create/createVaultStaticCall.ts diff --git a/README.md b/README.md index 9aa3f7e2..2b5d9bae 100644 --- a/README.md +++ b/README.md @@ -1184,10 +1184,6 @@ const hash = await sdk.vault.create(params) const { data, to, value } = await sdk.vault.deposit.encode(params) // Get an approximate gas per transaction const gas = await sdk.vault.deposit.estimateGas(params) -// Get vault address before the transaction is sent -// Note: To make this call on chains where the deposit token is not a native token (e.g., Gnosis, Chiado), -// please ensure you use an address that has already approved the token. -const vaultAddress = await sdk.vault.create.staticCall(params) ``` --- ### `sdk.vault.deposit` diff --git a/changelog/next-release.md b/changelog/next-release.md index f0556ee2..ce0b8e7e 100644 --- a/changelog/next-release.md +++ b/changelog/next-release.md @@ -70,8 +70,4 @@ const hash = await sdk.vault.create(params) const { data, to, value } = await sdk.vault.deposit.encode(params) // Get an approximate gas per transaction const gas = await sdk.vault.deposit.estimateGas(params) -// Get vault address before the transaction is sent -// Note: To make this call on chains where the deposit token is not a native token (e.g., Gnosis, Chiado), -// please ensure you use an address that has already approved the token. -const vaultAddress = await sdk.vault.create.staticCall(params) ``` \ No newline at end of file diff --git a/src/StakeWiseSDK.ts b/src/StakeWiseSDK.ts index 9a27c083..94f90da2 100644 --- a/src/StakeWiseSDK.ts +++ b/src/StakeWiseSDK.ts @@ -3,7 +3,7 @@ import { configs, getGas, createProvider, getVaultFactory, VaultType } from './u import { createContracts, vaultMulticall, rewardSplitterMulticall } from './contracts' -type GetVaultFactoryInput = { vaultType: VaultType, isErc20?: boolean } +type GetVaultFactoryInput = { vaultType?: VaultType, isErc20?: boolean } type VaultMulticallInput = Pick[0], 'request' | 'userAddress' | 'vaultAddress'> type RewardSplitterMulticallInput = Pick[0], 'request' | 'userAddress' | 'vaultAddress'> & { rewardSplitterAddress: string diff --git a/src/contracts/multicall/util/handleTransactionData.ts b/src/contracts/multicall/util/handleTransactionData.ts index 193b6279..0ee4b66b 100644 --- a/src/contracts/multicall/util/handleTransactionData.ts +++ b/src/contracts/multicall/util/handleTransactionData.ts @@ -10,12 +10,7 @@ type Input = { const handleTransactionData = async ({ contract, multicallParams }: Input) => { const calls = getMulticallCalls({ multicallParams, contract }) - const rx = await contract.multicall.populateTransaction(calls) - - return { - to: rx.to, - data: rx.data, - } + return contract.multicall.populateTransaction(calls) } diff --git a/src/methods/index.ts b/src/methods/index.ts index f8a44c53..59efac92 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -21,7 +21,6 @@ interface UnknownMethod { (values: unknown): unknown encode?: (values: unknown) => unknown estimateGas?: (values: unknown) => unknown - staticCall?: (values: unknown) => unknown } type CheckArgs> = [keyof Obj] extends [never] ? [] : [Obj] @@ -42,15 +41,9 @@ type WithEstimateGas = WithEncode & { ) } -type WithStaticCall = WithEstimateGas & { - staticCall: (...values: CheckArgs>[0], 'options' | 'contracts' | 'provider'>>) => ( - ReturnType> - ) -} - type ModifiedMethod = 'encode' extends keyof M ? 'estimateGas' extends keyof M - ? 'staticCall' extends keyof M ? WithStaticCall : WithEstimateGas + ? WithEstimateGas : WithEncode : WithoutEncode @@ -67,7 +60,7 @@ type ModifyMethods> = { type CreateMethodsOutput = ModifyMethods const generateSubMethods = (fn: UnknownMethod, wrapper: UnknownMethod, params: CommonParams) => { - const submethods = [ 'encode', 'estimateGas', 'staticCall' ] as const + const submethods = [ 'encode', 'estimateGas' ] as const submethods.forEach((submethod) => { if (typeof fn[submethod] === 'function') { diff --git a/src/methods/osToken/transactions/burn/burnEncode.ts b/src/methods/osToken/transactions/burn/burnEncode.ts index cf6b1ba1..9801344b 100644 --- a/src/methods/osToken/transactions/burn/burnEncode.ts +++ b/src/methods/osToken/transactions/burn/burnEncode.ts @@ -7,12 +7,7 @@ const burnEncode = async (values: BurnInput): Promise const vaultContract = commonLogic(values) - const rx = await vaultContract.burnOsToken.populateTransaction(shares) - - return { - data: rx.data, - to: rx.to, - } + return vaultContract.burnOsToken.populateTransaction(shares) } diff --git a/src/methods/rewardSplitter/transactions/claimRewards/claimRewardsEncode.ts b/src/methods/rewardSplitter/transactions/claimRewards/claimRewardsEncode.ts index 9eff3a04..477a1079 100644 --- a/src/methods/rewardSplitter/transactions/claimRewards/claimRewardsEncode.ts +++ b/src/methods/rewardSplitter/transactions/claimRewards/claimRewardsEncode.ts @@ -6,18 +6,13 @@ import { rewardSplitterMulticall } from '../../../../contracts' const claimRewardsEncode = async (values: ClaimRewardsInput) => { const multicallArgs = await commonLogic(values) - const rx = await rewardSplitterMulticall<{ data: string, to: string }>({ + return rewardSplitterMulticall<{ data: string, to: string }>({ ...multicallArgs, request: { ...multicallArgs.request, transactionData: true, }, }) - - return { - data: rx.data, - to: rx.to, - } } diff --git a/src/methods/rewardSplitter/transactions/createRewardSplitter/createRewardSplitterEncode.ts b/src/methods/rewardSplitter/transactions/createRewardSplitter/createRewardSplitterEncode.ts index 6476c5ad..07c7044a 100644 --- a/src/methods/rewardSplitter/transactions/createRewardSplitter/createRewardSplitterEncode.ts +++ b/src/methods/rewardSplitter/transactions/createRewardSplitter/createRewardSplitterEncode.ts @@ -5,12 +5,7 @@ import type { CreateRewardSplitterInput } from './types' const createRewardSplitterEncode = async (values: CreateRewardSplitterInput) => { const rewardSplitterFactory = await commonLogic(values) - const rx = await rewardSplitterFactory.createRewardSplitter.populateTransaction(values.vaultAddress) - - return { - data: rx.data, - to: rx.to, - } + return rewardSplitterFactory.createRewardSplitter.populateTransaction(values.vaultAddress) } diff --git a/src/methods/rewardSplitter/transactions/updateFeeRecipients/updateFeeRecipientsEncode.ts b/src/methods/rewardSplitter/transactions/updateFeeRecipients/updateFeeRecipientsEncode.ts index f68e5b2f..fd4dfca4 100644 --- a/src/methods/rewardSplitter/transactions/updateFeeRecipients/updateFeeRecipientsEncode.ts +++ b/src/methods/rewardSplitter/transactions/updateFeeRecipients/updateFeeRecipientsEncode.ts @@ -6,18 +6,13 @@ import { rewardSplitterMulticall } from '../../../../contracts' const updateFeeRecipientsEncode = async (values: UpdateFeeRecipientsInput) => { const multicallArgs = await commonLogic(values) - const rx = await rewardSplitterMulticall<{ data: string, to: string }>({ + return rewardSplitterMulticall<{ data: string, to: string }>({ ...multicallArgs, request: { ...multicallArgs.request, transactionData: true, }, }) - - return { - data: rx.data, - to: rx.to, - } } diff --git a/src/methods/utils/getVaultMulticallEncode.ts b/src/methods/utils/getVaultMulticallEncode.ts index f2bbb32d..94cd2251 100644 --- a/src/methods/utils/getVaultMulticallEncode.ts +++ b/src/methods/utils/getVaultMulticallEncode.ts @@ -4,18 +4,13 @@ import { vaultMulticall } from '../../contracts' type Input = Parameters[0] const getVaultMulticallEncode = async (values: Input): Promise => { - const rx = await vaultMulticall<{ data: string, to: string }>({ + return vaultMulticall<{ data: string, to: string }>({ ...values, request: { ...values.request, transactionData: true, }, }) - - return { - data: rx.data, - to: rx.to, - } } diff --git a/src/methods/vault/transactions/create/createVaultEncode.ts b/src/methods/vault/transactions/create/createVaultEncode.ts index c29e08d5..fd8d7192 100644 --- a/src/methods/vault/transactions/create/createVaultEncode.ts +++ b/src/methods/vault/transactions/create/createVaultEncode.ts @@ -10,12 +10,7 @@ const createVaultEncode = async (values: CreateVaultInput) => { const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) - const rx = await vaultFactory.createVault.populateTransaction(...params) - - return { - to: rx.to, - data: rx.data, - } + return vaultFactory.createVault.populateTransaction(...params) } diff --git a/src/methods/vault/transactions/create/createVaultStaticCall.ts b/src/methods/vault/transactions/create/createVaultStaticCall.ts deleted file mode 100644 index 49d36687..00000000 --- a/src/methods/vault/transactions/create/createVaultStaticCall.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ethers } from 'ethers' -import { commonLogic } from './common' -import type { CreateVaultInput } from './types' -import { getMetadataHashMock } from '../util' - - -const createVaultStaticCall = async (values: CreateVaultInput) => { - const { image, displayName, description, ...rest } = values - const { provider, userAddress } = rest - - const metadataIpfsHash = getMetadataHashMock({ image, displayName, description }) - const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) - - const signer = new ethers.VoidSigner(userAddress, provider) - const signedContract = vaultFactory.connect(signer) - - const vaultAddress = await signedContract.createVault.staticCall(...params) - - return vaultAddress -} - - -export default createVaultStaticCall diff --git a/src/methods/vault/transactions/create/index.ts b/src/methods/vault/transactions/create/index.ts index 6ad9ba65..210cebcc 100644 --- a/src/methods/vault/transactions/create/index.ts +++ b/src/methods/vault/transactions/create/index.ts @@ -1,7 +1,6 @@ import { commonLogic } from './common' import createVaultGas from './createVaultGas' import createVaultEncode from './createVaultEncode' -import createVaultStaticCall from './createVaultStaticCall' import { uploadMetadata } from '../util' import type { CreateVault } from './types' @@ -23,7 +22,6 @@ const create: CreateVault = async (values) => { create.encode = createVaultEncode create.estimateGas = createVaultGas -create.staticCall = createVaultStaticCall export default create diff --git a/src/methods/vault/transactions/create/types.d.ts b/src/methods/vault/transactions/create/types.d.ts index a2edf025..489abd9e 100644 --- a/src/methods/vault/transactions/create/types.d.ts +++ b/src/methods/vault/transactions/create/types.d.ts @@ -1,6 +1,5 @@ import createVaultGas from './createVaultGas' import createVaultEncode from './createVaultEncode' -import createVaultStaticCall from './createVaultStaticCall' import type { BaseInput } from '../../../utils' import type { VaultType } from '../../../../utils' import type { UploadMetadataInput } from '../util/metadata/uploadMetadata' @@ -27,5 +26,4 @@ export interface CreateVault { (values: CreateVaultInput): Promise estimateGas: typeof createVaultGas encode: typeof createVaultEncode - staticCall: typeof createVaultStaticCall } diff --git a/src/methods/vault/transactions/createEigenPod/createEigenPodEncode.ts b/src/methods/vault/transactions/createEigenPod/createEigenPodEncode.ts index 5b66bbf2..39a441f8 100644 --- a/src/methods/vault/transactions/createEigenPod/createEigenPodEncode.ts +++ b/src/methods/vault/transactions/createEigenPod/createEigenPodEncode.ts @@ -5,12 +5,7 @@ import { CreateEigenPodInput } from './types' const depositEncode = async (values: CreateEigenPodInput) => { const contract = await commonLogic(values) - const rx = await contract.createEigenPod.populateTransaction() - - return { - to: rx.to, - data: rx.data, - } + return contract.createEigenPod.populateTransaction() } diff --git a/src/methods/vault/transactions/setDepositDataManager/setDepositDataManagerEncode.ts b/src/methods/vault/transactions/setDepositDataManager/setDepositDataManagerEncode.ts index 4e7e2e21..73292292 100644 --- a/src/methods/vault/transactions/setDepositDataManager/setDepositDataManagerEncode.ts +++ b/src/methods/vault/transactions/setDepositDataManager/setDepositDataManagerEncode.ts @@ -5,12 +5,7 @@ import type { SetDepositDataManagerInput } from './types' const setDepositDataManagerEncode = async (values: SetDepositDataManagerInput) => { const contract = commonLogic(values) - const rx = await contract.setDepositDataManager.populateTransaction(values.vaultAddress, values.managerAddress) - - return { - to: rx.to, - data: rx.data, - } + return contract.setDepositDataManager.populateTransaction(values.vaultAddress, values.managerAddress) } diff --git a/src/methods/vault/transactions/setDepositDataRoot/setDepositDataRootEncode.ts b/src/methods/vault/transactions/setDepositDataRoot/setDepositDataRootEncode.ts index c5ce956a..1afccf18 100644 --- a/src/methods/vault/transactions/setDepositDataRoot/setDepositDataRootEncode.ts +++ b/src/methods/vault/transactions/setDepositDataRoot/setDepositDataRootEncode.ts @@ -5,12 +5,7 @@ import type { SetDepositDataRootInput } from './types' const setDepositDataRootEncode = async (values: SetDepositDataRootInput) => { const contract = commonLogic(values) - const rx = await contract.setDepositDataRoot.populateTransaction(values.vaultAddress, values.validatorsRoot) - - return { - to: rx.to, - data: rx.data, - } + return contract.setDepositDataRoot.populateTransaction(values.vaultAddress, values.validatorsRoot) } diff --git a/src/methods/vault/transactions/setEigenPodOperator/setEigenPodOperatorEncode.ts b/src/methods/vault/transactions/setEigenPodOperator/setEigenPodOperatorEncode.ts index 2079f479..483cfe00 100644 --- a/src/methods/vault/transactions/setEigenPodOperator/setEigenPodOperatorEncode.ts +++ b/src/methods/vault/transactions/setEigenPodOperator/setEigenPodOperatorEncode.ts @@ -5,12 +5,7 @@ import { SetEigenPodOperatorInput } from './types' const setEigenPodOperatorEncode = async (values: SetEigenPodOperatorInput) => { const { eigenPodOwnerContract } = await commonLogic(values) - const rx = await eigenPodOwnerContract.eigenPod.populateTransaction() - - return { - to: rx.to, - data: rx.data, - } + return eigenPodOwnerContract.eigenPod.populateTransaction() } diff --git a/src/methods/vault/transactions/updateEigenPodOperator/updateEigenPodOperatorEncode.ts b/src/methods/vault/transactions/updateEigenPodOperator/updateEigenPodOperatorEncode.ts index 4ad4cc9c..5399d820 100644 --- a/src/methods/vault/transactions/updateEigenPodOperator/updateEigenPodOperatorEncode.ts +++ b/src/methods/vault/transactions/updateEigenPodOperator/updateEigenPodOperatorEncode.ts @@ -6,18 +6,13 @@ import { eigenPodOwnerMulticall } from '../../../../contracts' const updateEigenPodOperatorEncode = async (values: UpdateEigenPodOperatorInput) => { const multicallArgs = await commonLogic(values) - const rx = await eigenPodOwnerMulticall<{ data: string, to: string }>({ + return eigenPodOwnerMulticall<{ data: string, to: string }>({ ...multicallArgs, request: { ...multicallArgs.request, transactionData: true, }, }) - - return { - data: rx.data, - to: rx.to, - } } diff --git a/src/utils/getVaultFactory.ts b/src/utils/getVaultFactory.ts index f5607332..1c3b7b54 100644 --- a/src/utils/getVaultFactory.ts +++ b/src/utils/getVaultFactory.ts @@ -2,8 +2,8 @@ import { VaultType } from './enums' type Input = { - vaultType: VaultType contracts: StakeWise.Contracts + vaultType?: VaultType isErc20?: boolean } @@ -18,7 +18,7 @@ const getVaultFactory = ({ vaultType, contracts, isErc20 }: Input) => { [VaultType.Blocklist]: contracts.factories.blocklistVault, } - return vaultFactories[vaultType] + return vaultFactories[vaultType || VaultType.Default] } From 83b05e4f287b64b98f3f4429889c4a728b1dbc68 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 15:45:49 +0300 Subject: [PATCH 13/15] [vault create sdk] update encode --- .../vault/transactions/deposit/nativeToken/depositEncode.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/methods/vault/transactions/deposit/nativeToken/depositEncode.ts b/src/methods/vault/transactions/deposit/nativeToken/depositEncode.ts index 3a221ccc..5c4ea72a 100644 --- a/src/methods/vault/transactions/deposit/nativeToken/depositEncode.ts +++ b/src/methods/vault/transactions/deposit/nativeToken/depositEncode.ts @@ -18,8 +18,7 @@ const depositEncode = async (values: DepositInput): Promise = const rx = await vaultContract.updateStateAndDeposit.populateTransaction(userAddress, referrer, harvestParams, overrides) return { - to: rx.to, - data: rx.data, + ...rx, value: overrides.value, } } @@ -27,8 +26,7 @@ const depositEncode = async (values: DepositInput): Promise = const rx = await vaultContract.deposit.populateTransaction(userAddress, referrer, overrides) return { - to: rx.to, - data: rx.data, + ...rx, value: overrides.value, } } From 20dc03b559912a04b288ebcc69f78de8ad9c3d92 Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 15:56:17 +0300 Subject: [PATCH 14/15] [vault create sdk] update upload --- .../vault/transactions/util/metadata/uploadMetadata/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts index 89ba4456..dda69b2d 100644 --- a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts +++ b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts @@ -15,6 +15,10 @@ type Input = UploadMetadataInput & { const uploadMetadata = async (input: Input) => { const { image = '', displayName = '', description = '', options } = input + if (!image && !displayName && !description) { + return '' + } + if (image) { validateArgs.image(image) } From 5a8b40d2f4985029823fb9c00941e4f55fb0dfde Mon Sep 17 00:00:00 2001 From: MikeDiam Date: Tue, 30 Jul 2024 15:58:43 +0300 Subject: [PATCH 15/15] [vault create sdk] update upload --- src/methods/vault/transactions/create/createVaultEncode.ts | 7 ++++++- src/methods/vault/transactions/create/index.ts | 7 ++++++- .../transactions/util/metadata/uploadMetadata/index.ts | 4 ---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/methods/vault/transactions/create/createVaultEncode.ts b/src/methods/vault/transactions/create/createVaultEncode.ts index fd8d7192..456eb4ae 100644 --- a/src/methods/vault/transactions/create/createVaultEncode.ts +++ b/src/methods/vault/transactions/create/createVaultEncode.ts @@ -7,7 +7,12 @@ const createVaultEncode = async (values: CreateVaultInput) => { const { image, displayName, description, ...rest } = values const { options } = rest - const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) + let metadataIpfsHash = '' + + if (image || displayName || description) { + metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) + } + const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) return vaultFactory.createVault.populateTransaction(...params) diff --git a/src/methods/vault/transactions/create/index.ts b/src/methods/vault/transactions/create/index.ts index 210cebcc..3e8b2170 100644 --- a/src/methods/vault/transactions/create/index.ts +++ b/src/methods/vault/transactions/create/index.ts @@ -9,7 +9,12 @@ const create: CreateVault = async (values) => { const { image, displayName, description, ...rest } = values const { provider, options, userAddress } = rest - const metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) + let metadataIpfsHash = '' + + if (image || displayName || description) { + metadataIpfsHash = await uploadMetadata({ image, displayName, description, options }) + } + const { vaultFactory, params } = await commonLogic({ metadataIpfsHash, ...rest }) const signer = await provider.getSigner(userAddress) diff --git a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts index dda69b2d..89ba4456 100644 --- a/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts +++ b/src/methods/vault/transactions/util/metadata/uploadMetadata/index.ts @@ -15,10 +15,6 @@ type Input = UploadMetadataInput & { const uploadMetadata = async (input: Input) => { const { image = '', displayName = '', description = '', options } = input - if (!image && !displayName && !description) { - return '' - } - if (image) { validateArgs.image(image) }