diff --git a/scripts/example.ts b/scripts/example.ts index 9ec663dbc..551a1c9d1 100644 --- a/scripts/example.ts +++ b/scripts/example.ts @@ -3,6 +3,7 @@ import { writeFile } from "node:fs/promises"; import { pino } from "pino"; import { AccountsCounterPlugin } from "../src/plugins/accounts-counter/index.js"; +import { AdaptersPlugin } from "../src/plugins/adapters/AdaptersPlugin.js"; import { BotsPlugin } from "../src/plugins/bots/index.js"; import { DegenDistributorsPlugin } from "../src/plugins/degen-distributors/index.js"; import { Pools7DAgoPlugin } from "../src/plugins/pools-history/index.js"; @@ -30,7 +31,7 @@ async function example(): Promise { const sdk = await GearboxSDK.attach({ rpcURLs: [RPC], timeout: 480_000, - // blockNumber: 22118452, // 21977000, // 22118452 + blockNumber: 23928400, // redstoneHistoricTimestamp: true, // addressProvider: ADDRESS_PROVIDER, // marketConfigurators: [], @@ -38,6 +39,7 @@ async function example(): Promise { // ignoreUpdateablePrices: true, strictContractTypes: true, plugins: { + adapters: new AdaptersPlugin(true), zappers: new ZappersPlugin([], true), bots: new BotsPlugin(true), degen: new DegenDistributorsPlugin(true), @@ -47,9 +49,11 @@ async function example(): Promise { }, redstone: { ignoreMissingFeeds: true, + historicTimestamp: true, }, pyth: { ignoreMissingFeeds: true, + historicTimestamp: true, }, }); @@ -80,11 +84,11 @@ async function example(): Promise { const prefix = RPC.includes("127.0.0.1") ? "anvil_" : ""; const net = sdk.networkType; await writeFile( - `tmp/state_${kind}_human_${net}_${prefix}${sdk.currentBlock}.json`, + `tmp/state_next_${kind}_human_${net}_${prefix}${sdk.currentBlock}.json`, json_stringify(sdk.stateHuman()), ); await writeFile( - `tmp/state_${kind}_${net}_${prefix}${sdk.currentBlock}.json`, + `tmp/state_next_${kind}_${net}_${prefix}${sdk.currentBlock}.json`, json_stringify(sdk.state), ); diff --git a/src/dev/create2.ts b/src/dev/create2.ts index 9d1d1ca17..7dad6661f 100644 --- a/src/dev/create2.ts +++ b/src/dev/create2.ts @@ -24,7 +24,7 @@ import { import { getCode, sendTransaction } from "viem/actions"; import type { GearboxSDK, ILogger } from "../sdk/index.js"; -import { SDKConstruct } from "../sdk/index.js"; +import { Construct } from "../sdk/index.js"; export const PUBLIC_CREATE2_FACTORY: Address = "0x4e59b44847b379578588920ca78fbf26c0b4956c"; @@ -69,7 +69,7 @@ export class Create2Deployer< transport extends Transport = Transport, chain extends Chain = Chain, account extends Account = Account, -> extends SDKConstruct { +> extends Construct { #walletClient: WalletClient; #logger?: ILogger; diff --git a/src/dev/mint/AbstractMinter.ts b/src/dev/mint/AbstractMinter.ts index db50753dc..e2179ed18 100644 --- a/src/dev/mint/AbstractMinter.ts +++ b/src/dev/mint/AbstractMinter.ts @@ -1,10 +1,6 @@ import { type Address, parseEther } from "viem"; import { ierc20Abi } from "../../abi/iERC20.js"; -import { - type GearboxSDK, - type ILogger, - SDKConstruct, -} from "../../sdk/index.js"; +import { type GearboxSDK, SDKConstruct } from "../../sdk/index.js"; import { iOwnableAbi } from "../abi.js"; import type { AnvilClient } from "../createAnvilClient.js"; import type { IMinter } from "./types.js"; @@ -14,14 +10,12 @@ export default abstract class AbstractMinter implements IMinter { protected readonly anvil: AnvilClient; - protected readonly logger?: ILogger; - public readonly name: string; + public name: string; - constructor(sdk: GearboxSDK, anvil: AnvilClient, name = "Minter") { + constructor(sdk: GearboxSDK, anvil: AnvilClient) { super(sdk); this.anvil = anvil; - this.name = name; - this.logger = sdk.logger?.child?.({ name }) ?? sdk.logger; + this.name = this.constructor.name; } public async tryMint( diff --git a/src/dev/mint/DealMinter.ts b/src/dev/mint/DealMinter.ts index 00de525a1..a71c2eb99 100644 --- a/src/dev/mint/DealMinter.ts +++ b/src/dev/mint/DealMinter.ts @@ -1,14 +1,8 @@ import type { Address, TestClient } from "viem"; -import type { GearboxSDK } from "../../sdk/index.js"; -import type { AnvilClient } from "../createAnvilClient.js"; import AbstractMinter from "./AbstractMinter.js"; import type { IMinter } from "./types.js"; export class DealMinter extends AbstractMinter implements IMinter { - constructor(sdk: GearboxSDK, anvil: AnvilClient) { - super(sdk, anvil, "DealMinter"); - } - public override async mint( token: Address, dest: Address, diff --git a/src/dev/mint/DirectMinter.ts b/src/dev/mint/DirectMinter.ts index 0141875d1..051aecbcf 100644 --- a/src/dev/mint/DirectMinter.ts +++ b/src/dev/mint/DirectMinter.ts @@ -1,14 +1,8 @@ import { type Address, parseAbi } from "viem"; -import type { GearboxSDK } from "../../sdk/index.js"; -import type { AnvilClient } from "../createAnvilClient.js"; import AbstractMinter from "./AbstractMinter.js"; import type { IMinter } from "./types.js"; export class DirectMinter extends AbstractMinter implements IMinter { - constructor(sdk: GearboxSDK, anvil: AnvilClient) { - super(sdk, anvil, "DirectMinter"); - } - public override async mint( token: Address, dest: Address, diff --git a/src/dev/mint/FallbackMinter.ts b/src/dev/mint/FallbackMinter.ts index 708af73cd..989422ba2 100644 --- a/src/dev/mint/FallbackMinter.ts +++ b/src/dev/mint/FallbackMinter.ts @@ -8,7 +8,7 @@ export class FallbackMinter extends AbstractMinter implements IMinter { #minters: IMinter[]; constructor(sdk: GearboxSDK, anvil: AnvilClient, minters: IMinter[]) { - super(sdk, anvil, "FallbackMinter"); + super(sdk, anvil); this.#minters = minters; } diff --git a/src/dev/mint/TransferMinter.ts b/src/dev/mint/TransferMinter.ts index 01b1025a1..2eef5af41 100644 --- a/src/dev/mint/TransferMinter.ts +++ b/src/dev/mint/TransferMinter.ts @@ -1,15 +1,9 @@ import { type Address, parseAbi } from "viem"; import { ierc20Abi } from "../../abi/iERC20.js"; -import type { GearboxSDK } from "../../sdk/index.js"; -import type { AnvilClient } from "../createAnvilClient.js"; import AbstractMinter from "./AbstractMinter.js"; import type { IMinter } from "./types.js"; export class TransferMinter extends AbstractMinter implements IMinter { - constructor(sdk: GearboxSDK, anvil: AnvilClient) { - super(sdk, anvil, "TransferMinter"); - } - public override async mint( token: Address, dest: Address, diff --git a/src/permissionless/bindings/address-provider.ts b/src/permissionless/bindings/address-provider.ts index 7c85c34dc..7e3036e3e 100644 --- a/src/permissionless/bindings/address-provider.ts +++ b/src/permissionless/bindings/address-provider.ts @@ -1,12 +1,15 @@ -import { type Address, type PublicClient, stringToHex } from "viem"; -import { iAddressProviderV310Abi } from "../../abi/310/generated.js"; -import { BaseContract } from "./base-contract.js"; +import { + type Address, + type Chain, + type PublicClient, + stringToHex, + type Transport, +} from "viem"; +import { AddressProviderV310Contract } from "../../sdk/index.js"; -const abi = iAddressProviderV310Abi; - -export class AddressProviderContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "AddressProvider"); +export class AddressProviderContract extends AddressProviderV310Contract { + constructor(addr: Address, client: PublicClient) { + super({ client }, addr); } async getAddressOrRevert(key: string, version = 0n): Promise
{ diff --git a/src/permissionless/bindings/base-contract.ts b/src/permissionless/bindings/base-contract.ts deleted file mode 100644 index 33cec530c..000000000 --- a/src/permissionless/bindings/base-contract.ts +++ /dev/null @@ -1,220 +0,0 @@ -import { - type Abi, - type Address, - type Client, - type ContractEventArgs, - type ContractEventName, - type ContractFunctionName, - type DecodeFunctionDataReturnType, - type EncodeFunctionDataParameters, - type GetContractEventsReturnType, - type GetContractReturnType, - getContract, - type Hex, - type PublicClient, -} from "viem"; -import type { RawTx } from "../../sdk/types/index.js"; -import { createRawTx } from "../../sdk/utils/index.js"; -import type { CrossChainCall, ParsedCall } from "../core/proposal.js"; -// import { createRawTx, EncodeFunctionDataParams } from "../core/raw-tx"; -import { decodeFunctionWithNamedArgs } from "../utils/abi-decoder.js"; - -export class BaseContract { - public readonly abi: abi; - public readonly address: Address; - public readonly name: string; - protected static register: Record> = {}; - - protected contract: GetContractReturnType; - public readonly client: PublicClient; - - constructor(abi: abi, address: Address, client: PublicClient, name: string) { - this.abi = abi; - this.client = client; - this.address = address.toLowerCase() as Address; - this.name = name; - this.contract = getContract({ - address: address, - abi: abi, - client: client, - }); - BaseContract.register[this.address] = this; - } - - public static parseCall(call: CrossChainCall): ParsedCall { - const parsedCall = BaseContract.parse(call.target, call.callData); - return { - ...parsedCall, - chainId: call.chainId, - }; - } - - public static parse(address: Address, calldata: Hex): ParsedCall { - const contract = BaseContract.register[address.toLowerCase() as Address]; - if (contract) { - return contract.parseFunctionData(calldata); - } else { - return { - chainId: 0, - target: address, - label: "Unknown contract", - functionName: `Unknown function: ${calldata}`, - args: {}, - }; - } - } - - parseFunctionData(calldata: Hex): ParsedCall { - // Use the shared utility to decode with named arguments - const decodedWithNames = decodeFunctionWithNamedArgs(this.abi, calldata); - - if (!decodedWithNames) { - return { - chainId: 0, - target: this.address, - label: this.name, - functionName: `Unknown function: ${calldata}`, - args: {}, - }; - } - - // Check if there's a specific parser for this function - const specParsed = this.parseFunctionParams( - decodedWithNames.originalDecoded, - ); - if (specParsed) { - return specParsed; - } - - return this.wrapParseCall( - decodedWithNames.originalDecoded, - decodedWithNames.args, - ); - } - - protected wrapParseCall( - params: DecodeFunctionDataReturnType, - parsedParams: Record, - ): ParsedCall { - return { - chainId: 0, - target: this.address, - label: this.name, - functionName: params.functionName, - args: parsedParams, - }; - } - - parseFunctionParams( - _params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { - return undefined; - } - - public createRawTx< - functionName extends ContractFunctionName | undefined = undefined, - >( - parameters: Omit, "abi"> & { - description?: string; - }, - ): RawTx { - const { description: argsDescription } = parameters; - - const tx = createRawTx( - this.address, - { - abi: this.abi, - ...parameters, - } as unknown as EncodeFunctionDataParameters, - argsDescription, - ); - - tx.description = - parameters.description || - argsDescription || - this.stringifyParsedCall(this.parseFunctionData(tx.callData)); - - return tx; - } - - protected stringifyParsedCall(parsedCall: ParsedCall): string { - const argsStr = Object.entries(parsedCall.args) - .map(([key, value]) => `${key}: ${value}`) - .join(", "); - return `${parsedCall.label}.${parsedCall.functionName}(${argsStr})`; - } - - public async getEvents>( - eventName: EventName, - fromBlock: bigint, - toBlock: bigint, - args?: - | ContractEventArgs< - abi, - EventName extends ContractEventName - ? EventName - : ContractEventName - > - | undefined, - chunkSize?: number, - ): Promise< - GetContractEventsReturnType - > { - if (chunkSize) { - const chunkSizeBigint = BigInt(chunkSize); - - const getEventPromises = []; - for (let i = fromBlock; i < toBlock; i += chunkSizeBigint) { - getEventPromises.push( - this.client.getContractEvents({ - address: this.address, - fromBlock: i, - toBlock: i + chunkSizeBigint, - abi: this.abi, - eventName, - args, - }), - ); - } - const events = (await Promise.all(getEventPromises)).flat(); - return events; - } - - try { - const events = await this.client.getContractEvents({ - address: this.address, - fromBlock, - toBlock, - abi: this.abi, - eventName, - args, - }); - return events; - } catch (e) { - const blockRangeErrors = [ - "query exceeds max block", - "range is too large", - "eth_getLogs is limited to", - "Unable to perform request", - "Block range limit exceeded", - ]; - - if ( - e instanceof Error && - blockRangeErrors.some(errorText => e.message.includes(errorText)) - ) { - const middle = (fromBlock + toBlock) / 2n; - const [firstHalfEvents, secondHalfEvents] = await Promise.all([ - this.getEvents(eventName, fromBlock, middle, args), - this.getEvents(eventName, middle + 1n, toBlock, args), - ]); - return [...firstHalfEvents, ...secondHalfEvents]; - } - throw e; - } - } - - public getContract(): GetContractReturnType { - return this.contract; - } -} diff --git a/src/permissionless/bindings/bytecode-repository.ts b/src/permissionless/bindings/bytecode-repository.ts index 7ec2ca2ef..9882e69ac 100644 --- a/src/permissionless/bindings/bytecode-repository.ts +++ b/src/permissionless/bindings/bytecode-repository.ts @@ -1,5 +1,6 @@ import { type Address, + type Chain, type DecodeFunctionDataReturnType, type Hex, hashStruct, @@ -9,20 +10,20 @@ import { parseEventLogs, recoverTypedDataAddress, stringToHex, + type Transport, type WalletClient, } from "viem"; import { iBytecodeRepositoryAbi } from "../../abi/310/iBytecodeRepository.js"; -import type { RawTx } from "../../sdk/types/index.js"; +import type { RawTx } from "../../sdk/index.js"; +import { BaseContract, type ParsedCallArgs } from "../../sdk/index.js"; import type { Auditor } from "../core/auditor.js"; import type { AuditEvent, Bytecode, DeploymentExtended, } from "../core/bytecode.js"; -import type { ParsedCall } from "../core/proposal.js"; import { normalizeSignature } from "../utils/index.js"; import { BYTECODE_REPOSITORY } from "../utils/literals.js"; -import { BaseContract } from "./base-contract.js"; const abi = iBytecodeRepositoryAbi; @@ -35,8 +36,8 @@ interface ComputeAddressArgs { } export class BytecodeRepositoryContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "BytecodeRepository"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "BytecodeRepository" }); } async getBytecodeByHash(hash: `0x${string}`) { @@ -296,74 +297,72 @@ export class BytecodeRepositoryContract extends BaseContract { return events; } - parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { switch (params.functionName) { + // TODO: simple array -> map can be removed, since this is what super.parseFunctionParams does case "allowSystemContract": { const [bytecodeHash] = params.args; - return this.wrapParseCall(params, { + return { bytecodeHash, - }); + }; } case "addAuditor": { const [auditor, name] = params.args; - return this.wrapParseCall(params, { - auditor, - name, - }); + return { auditor, name }; } case "removeAuditor": { const [auditor] = params.args; - return this.wrapParseCall(params, { + return { auditor, - }); + }; } case "addPublicDomain": { const [domain] = params.args; - return this.wrapParseCall(params, { + return { domain: hexToString(domain, { size: 32 }), - }); + }; } case "removePublicContractType": { const [contractType] = params.args; - return this.wrapParseCall(params, { + return { contractType: hexToString(contractType, { size: 32 }), - }); + }; } case "forbidInitCode": { const [bytecodeHash] = params.args; - return this.wrapParseCall(params, { + return { bytecodeHash, - }); + }; } case "setTokenSpecificPostfix": { const [token, postfix] = params.args; - return this.wrapParseCall(params, { + return { token, postfix: hexToString(postfix, { size: 32 }), - }); + }; } case "uploadBytecode": { const [uploadData] = params.args; - return this.wrapParseCall(params, { + return { contractType: hexToString(uploadData.contractType, { size: 32 }), version: uploadData.version.toString(), initCode: uploadData.initCode, author: uploadData.author, source: uploadData.source, authorSignature: uploadData.authorSignature, - }); + }; } case "submitAuditReport": { const [bytecodeHash, { auditor, reportUrl, signature }] = params.args; - return this.wrapParseCall(params, { + return { bytecodeHash, auditor, reportUrl, signature, - }); + }; } // TODO: add all functions here! // case "deployContract": { @@ -384,7 +383,7 @@ export class BytecodeRepositoryContract extends BaseContract { // }); // } default: - return undefined; + return super.parseFunctionParams(params); } } diff --git a/src/permissionless/bindings/compressors/token-compressor.ts b/src/permissionless/bindings/compressors/token-compressor.ts index c09b2e667..dc1956a0d 100644 --- a/src/permissionless/bindings/compressors/token-compressor.ts +++ b/src/permissionless/bindings/compressors/token-compressor.ts @@ -1,18 +1,20 @@ import { type Abi, type Address, + type Chain, erc20Abi, type PublicClient, parseAbi, + type Transport, } from "viem"; import { tokenCompressorAbi } from "../../../abi/compressors/tokenCompressor.js"; -import { BaseContract } from "../base-contract.js"; +import { BaseContract } from "../../../sdk/index.js"; const abi = tokenCompressorAbi; export class TokenCompressorContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "TokenCompressor"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "TokenCompressor" }); } async getTokenInfo(token: Address): Promise<{ diff --git a/src/permissionless/bindings/compressors/withdrawal-compressor.ts b/src/permissionless/bindings/compressors/withdrawal-compressor.ts index b312bc2a2..ffd03bac2 100644 --- a/src/permissionless/bindings/compressors/withdrawal-compressor.ts +++ b/src/permissionless/bindings/compressors/withdrawal-compressor.ts @@ -1,23 +1,24 @@ import { type Address, + type Chain, type DecodeFunctionDataReturnType, hexToString, type PublicClient, + type Transport, } from "viem"; import { withdrawalCompressorAbi } from "../../../abi/compressors/withdrawalCompressor.js"; -import type { ParsedCall } from "../../core/index.js"; -import { BaseContract } from "../base-contract.js"; +import { BaseContract, type ParsedCallArgs } from "../../../sdk/index.js"; const abi = withdrawalCompressorAbi; export class WithdrawalCompressorContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "RoutingManager"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "WithdrawalCompressor" }); } - public parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { const { functionName, args } = params; switch (functionName) { @@ -25,23 +26,17 @@ export class WithdrawalCompressorContract extends BaseContract { const [withdrawableType, compressorType] = args; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - withdrawableType: hexToString(withdrawableType as `0x${string}`, { - size: 32, - }), - compressorType: hexToString(compressorType as `0x${string}`, { - size: 32, - }), - }, + withdrawableType: hexToString(withdrawableType as `0x${string}`, { + size: 32, + }), + compressorType: hexToString(compressorType as `0x${string}`, { + size: 32, + }), }; } default: - return undefined; + return super.parseFunctionParams(params); } } } diff --git a/src/permissionless/bindings/cross-chain-multisig.ts b/src/permissionless/bindings/cross-chain-multisig.ts index 47157ff21..d7a891e60 100644 --- a/src/permissionless/bindings/cross-chain-multisig.ts +++ b/src/permissionless/bindings/cross-chain-multisig.ts @@ -1,28 +1,33 @@ import { type Address, + type Chain, type DecodeFunctionDataReturnType, type Hex, type PublicClient, parseAbi, parseEventLogs, recoverTypedDataAddress, + type Transport, type WalletClient, zeroAddress, } from "viem"; import { crossChainMultisigAbi } from "../../abi/310/crossChainMultisig.js"; -import type { RawTx } from "../../sdk/types/index.js"; -import { json_stringify } from "../../sdk/utils/index.js"; +import type { RawTx } from "../../sdk/index.js"; +import { + BaseContract, + json_stringify, + type ParsedCall, + type ParsedCallArgs, +} from "../../sdk/index.js"; import type { Batch, CrossChainCall, - ParsedCall, RecoveryMessage, Signature, } from "../core/proposal.js"; import { Addresses } from "../deployment/addresses.js"; import { normalizeSignature } from "../utils/index.js"; import { CROSS_CHAIN_MULTISIG } from "../utils/literals.js"; -import { BaseContract } from "./base-contract.js"; import { InstanceManagerContract } from "./instance-manager.js"; import { MarketConfiguratorFactoryContract } from "./market-configurator-factory.js"; @@ -44,8 +49,8 @@ export interface Proposal { } export class CrossChainMultisigContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "CrossChainMultisig"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "CrossChainMultisig" }); } async getExecutedBatches( @@ -116,7 +121,9 @@ export class CrossChainMultisigContract extends BaseContract { transactionHash: transactionHash, blockNumber: blockNumber, hash: proposalHash, - parsedCalls: calls.map(c => BaseContract.parseCall(c)), + parsedCalls: calls.map(c => + this.register.parseFunctionData(c.target, c.callData), + ), signatures, }; } @@ -228,7 +235,7 @@ export class CrossChainMultisigContract extends BaseContract { return [...(await this.contract.read.getSigners())]; } - decodeFunctionData(target: Address, calldata: Hex): ParsedCall | undefined { + #decodeFunctionData(target: Address, calldata: Hex): ParsedCall | undefined { switch (target.toLowerCase()) { case this.address.toLowerCase(): { return this.parseFunctionData(calldata); @@ -257,44 +264,44 @@ export class CrossChainMultisigContract extends BaseContract { } } - parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { switch (params.functionName) { case "addSigner": { const [signer] = params.args; - return this.wrapParseCall(params, { + return { signer, - }); + }; } case "removeSigner": { const [signer] = params.args; - return this.wrapParseCall(params, { + return { signer, - }); + }; } case "setConfirmationThreshold": { const [threshold] = params.args; - return this.wrapParseCall(params, { + return { threshold: threshold.toString(), - }); + }; } case "submitBatch": { const [name, calls, prevHash] = params.args; - return this.wrapParseCall(params, { + return { name, calls: json_stringify( calls.map(({ chainId, target, callData }) => ({ - ...this.decodeFunctionData(target, callData), + ...this.#decodeFunctionData(target, callData), chainId: Number(chainId), target, })), ), prevHash, - }); + }; } default: - return undefined; + return super.parseFunctionParams(params); } } diff --git a/src/permissionless/bindings/factory/abstract-factory.ts b/src/permissionless/bindings/factory/abstract-factory.ts index 62fb6b397..8d4bd4fdf 100644 --- a/src/permissionless/bindings/factory/abstract-factory.ts +++ b/src/permissionless/bindings/factory/abstract-factory.ts @@ -1,11 +1,12 @@ -import type { - Abi, - ContractFunctionName, - EncodeFunctionDataParameters, - Hex, +import { + type Abi, + type ContractFunctionName, + decodeFunctionData, + type EncodeFunctionDataParameters, + type Hex, } from "viem"; +import { functionArgsToMap } from "../../../sdk/index.js"; import { createCallData } from "../../core/raw-tx.js"; -import { decodeFunctionWithNamedArgs } from "../../utils/abi-decoder.js"; export class AbstractFactory { public readonly abi: abi; @@ -34,11 +35,13 @@ export class AbstractFactory { decodeConfig( calldata: Hex, ): { functionName: string; args: Record } | null { - const decoded = decodeFunctionWithNamedArgs(this.abi, calldata); - if (!decoded) return null; + const decoded = decodeFunctionData({ + abi: this.abi, + data: calldata, + }); return { functionName: decoded.functionName, - args: decoded.args, + args: functionArgsToMap(this.abi, decoded.functionName, decoded.args), }; } } diff --git a/src/permissionless/bindings/governance/batches-chain.ts b/src/permissionless/bindings/governance/batches-chain.ts index b6c14e4cf..13ca38489 100644 --- a/src/permissionless/bindings/governance/batches-chain.ts +++ b/src/permissionless/bindings/governance/batches-chain.ts @@ -1,13 +1,12 @@ -import type { Address, Hash, PublicClient } from "viem"; +import type { Address, Chain, Hash, PublicClient, Transport } from "viem"; import { batchesChainAbi } from "../../../abi/governance/batchesChain.js"; -import type { RawTx } from "../../../sdk/types/index.js"; -import { BaseContract } from "../base-contract.js"; +import { BaseContract, type RawTx } from "../../../sdk/index.js"; const abi = batchesChainAbi; export class BatchesChainContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "BatchesChain"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "BatchesChain" }); } createBatchOrderingTx(prevHash: Hash): RawTx { diff --git a/src/permissionless/bindings/governance/governor.ts b/src/permissionless/bindings/governance/governor.ts index 8e3ec4da2..8347041c1 100644 --- a/src/permissionless/bindings/governance/governor.ts +++ b/src/permissionless/bindings/governance/governor.ts @@ -1,5 +1,6 @@ import { type Address, + type Chain, type DecodeFunctionDataReturnType, encodeAbiParameters, formatEther, @@ -7,15 +8,14 @@ import { type Hex, keccak256, type PublicClient, + type Transport, toBytes, } from "viem"; import { formatAbiItem } from "viem/utils"; import { governorAbi } from "../../../abi/governance/governor.js"; -import type { RawTx } from "../../../sdk/types/index.js"; -import { json_stringify } from "../../../sdk/utils/index.js"; -import type { ParsedCall } from "../../core/index.js"; +import type { ParsedCall, ParsedCallArgs, RawTx } from "../../../sdk/index.js"; +import { BaseContract, json_stringify } from "../../../sdk/index.js"; import { formatTimestamp } from "../../utils/index.js"; -import { BaseContract } from "../base-contract.js"; import { MarketConfiguratorContract } from "../market-configurator.js"; import { TreasurySplitterContract } from "../treasury-splitter.js"; import { BatchesChainContract } from "./batches-chain.js"; @@ -26,8 +26,8 @@ const abi = governorAbi; export class GovernorContract extends BaseContract { public readonly batchesChainContract: BatchesChainContract; - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "Governor"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "Governor" }); this.batchesChainContract = new BatchesChainContract( "0x59b2fd348e4Ade84ffEfDaf5fcdDa7276c8C5041", @@ -163,7 +163,7 @@ export class GovernorContract extends BaseContract { }); } - decodeFunctionData(target: Address, calldata: Hex): ParsedCall | undefined { + #decodeFunctionData(target: Address, calldata: Hex): ParsedCall | undefined { switch (target.toLowerCase()) { case this.address.toLowerCase(): { return this.parseFunctionData(calldata); @@ -201,9 +201,9 @@ export class GovernorContract extends BaseContract { } } - public parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { const { functionName, args } = params; switch (functionName) { @@ -211,13 +211,7 @@ export class GovernorContract extends BaseContract { const [eta] = args; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - eta: formatTimestamp(Number(eta)), - }, + eta: formatTimestamp(Number(eta)), }; } case "queueTransaction": { @@ -227,53 +221,41 @@ export class GovernorContract extends BaseContract { data.slice(2)) as Hex; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - target, - value: formatEther(value), - signature, - data: json_stringify( - this.decodeFunctionData(target, calldata)?.args ?? calldata, - ), - eta: formatTimestamp(Number(eta)), - }, + target, + value: formatEther(value), + signature, + data: json_stringify( + this.#decodeFunctionData(target, calldata)?.args ?? calldata, + ), + eta: formatTimestamp(Number(eta)), }; } case "executeBatch": { const [txs] = args; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - txs: json_stringify( - txs.map(tx => { - const { target, value, signature, data, eta } = tx; - const calldata = (keccak256(toBytes(signature)).slice(0, 10) + - data.slice(2)) as Hex; - - return { - target, - value: formatEther(value), - signature, - data: json_stringify( - this.decodeFunctionData(target, calldata)?.args ?? calldata, - ), - eta: formatTimestamp(Number(eta)), - }; - }), - ), - }, + txs: json_stringify( + txs.map(tx => { + const { target, value, signature, data, eta } = tx; + const calldata = (keccak256(toBytes(signature)).slice(0, 10) + + data.slice(2)) as Hex; + + return { + target, + value: formatEther(value), + signature, + data: json_stringify( + this.#decodeFunctionData(target, calldata)?.args ?? calldata, + ), + eta: formatTimestamp(Number(eta)), + }; + }), + ), }; } default: - return undefined; + return super.parseFunctionParams(params); } } } diff --git a/src/permissionless/bindings/governance/timelock.ts b/src/permissionless/bindings/governance/timelock.ts index 6d55615fc..051a0afba 100644 --- a/src/permissionless/bindings/governance/timelock.ts +++ b/src/permissionless/bindings/governance/timelock.ts @@ -1,11 +1,11 @@ -import type { Address, Hex, PublicClient } from "viem"; +import type { Address, Chain, Hex, PublicClient, Transport } from "viem"; import { iTimeLockAbi } from "../../../abi/governance/iTimeLock.js"; -import { BaseContract } from "../base-contract.js"; +import { BaseContract } from "../../../sdk/index.js"; import type { QueuedAndExecutedTransaction } from "./types.js"; export class TimeLockContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(iTimeLockAbi, address, client, "TimeLock"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi: iTimeLockAbi, addr, name: "TimeLock" }); } async admin(): Promise
{ diff --git a/src/permissionless/bindings/governance/types.ts b/src/permissionless/bindings/governance/types.ts index 80419d5dd..0ad4912c4 100644 --- a/src/permissionless/bindings/governance/types.ts +++ b/src/permissionless/bindings/governance/types.ts @@ -1,5 +1,5 @@ import type { Address, Hex } from "viem"; -import type { ContractMethod } from "../../../sdk/types/index.js"; +import type { ContractMethod } from "../../../sdk/index.js"; // @note Safe txs and bathes types export interface SafeTx { diff --git a/src/permissionless/bindings/index.ts b/src/permissionless/bindings/index.ts index f1c747a27..94f0e059b 100644 --- a/src/permissionless/bindings/index.ts +++ b/src/permissionless/bindings/index.ts @@ -1,5 +1,4 @@ export * from "./address-provider.js"; -export * from "./base-contract.js"; export * from "./bytecode-repository.js"; export * from "./compressors/index.js"; export * from "./cross-chain-multisig.js"; diff --git a/src/permissionless/bindings/instance-manager.ts b/src/permissionless/bindings/instance-manager.ts index 12a67b13f..e3db84bb5 100644 --- a/src/permissionless/bindings/instance-manager.ts +++ b/src/permissionless/bindings/instance-manager.ts @@ -1,10 +1,12 @@ import { type Address, + type Chain, type DecodeFunctionDataReturnType, type Hex, hexToString, type PublicClient, stringToHex, + type Transport, } from "viem"; import { instanceManagerAbi } from "../../abi/310/instanceManager.js"; import { camelotV3WorkerAbi } from "../../abi/router/camelotV3Worker.js"; @@ -14,11 +16,14 @@ import { mellow4626WorkerAbi } from "../../abi/router/mellow4626Worker.js"; import { pendleRouterWorkerAbi } from "../../abi/router/pendleRouterWorker.js"; import { uniswapV3WorkerAbi } from "../../abi/router/uniswapV3Worker.js"; import { uniswapV4WorkerAbi } from "../../abi/router/uniswapV4Worker.js"; -import type { RawTx } from "../../sdk/types/index.js"; -import { json_stringify } from "../../sdk/utils/index.js"; -import type { ParsedCall } from "../core/proposal.js"; +import type { RawTx } from "../../sdk/index.js"; +import { + BaseContract, + json_stringify, + type ParsedCall, + type ParsedCallArgs, +} from "../../sdk/index.js"; import { Addresses } from "../deployment/addresses.js"; -import { BaseContract } from "./base-contract.js"; import { WithdrawalCompressorContract } from "./compressors/index.js"; import { PriceFeedStoreContract } from "./price-feed-store.js"; import { RoutingManagerContract } from "./router/index.js"; @@ -27,12 +32,12 @@ import { TreasurySplitterContract } from "./treasury-splitter.js"; const abi = instanceManagerAbi; export class InstanceManagerContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "InstanceManager"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "InstanceManager" }); } // TODO: - decodeFunctionData(target: Address, calldata: Hex): ParsedCall | undefined { + #decodeFunctionData(target: Address, calldata: Hex): ParsedCall | undefined { switch (target.toLowerCase()) { case this.address.toLowerCase(): { return this.parseFunctionData(calldata); @@ -46,10 +51,8 @@ export class InstanceManagerContract extends BaseContract { // ROUTER let parsedData: ParsedCall; const router = new BaseContract( - gearboxRouterAbi, - target, - this.client, - "GearboxRouter", + { client: this.client }, + { abi: gearboxRouterAbi, addr: target, name: "GearboxRouter" }, ); parsedData = router.parseFunctionData(calldata); @@ -69,10 +72,8 @@ export class InstanceManagerContract extends BaseContract { // WORKERS const camelotV3Worker = new BaseContract( - camelotV3WorkerAbi, - target, - this.client, - "CamelotV3Worker", + { client: this.client }, + { abi: camelotV3WorkerAbi, addr: target, name: "CamelotV3Worker" }, ); parsedData = camelotV3Worker.parseFunctionData(calldata); @@ -81,10 +82,8 @@ export class InstanceManagerContract extends BaseContract { } const erc4626Worker = new BaseContract( - erc4626WorkerAbi, - target, - this.client, - "ERC4626Worker", + { client: this.client }, + { abi: erc4626WorkerAbi, addr: target, name: "ERC4626Worker" }, ); parsedData = erc4626Worker.parseFunctionData(calldata); @@ -93,10 +92,12 @@ export class InstanceManagerContract extends BaseContract { } const mellow4626Worker = new BaseContract( - mellow4626WorkerAbi, - target, - this.client, - "Mellow4626Worker", + { client: this.client }, + { + abi: mellow4626WorkerAbi, + addr: target, + name: "Mellow4626Worker", + }, ); parsedData = mellow4626Worker.parseFunctionData(calldata); @@ -105,10 +106,12 @@ export class InstanceManagerContract extends BaseContract { } const pendleRouterWorker = new BaseContract( - pendleRouterWorkerAbi, - target, - this.client, - "PendleRouterWorker", + { client: this.client }, + { + abi: pendleRouterWorkerAbi, + addr: target, + name: "PendleRouterWorker", + }, ); parsedData = pendleRouterWorker.parseFunctionData(calldata); @@ -117,10 +120,8 @@ export class InstanceManagerContract extends BaseContract { } const uniswapV3Worker = new BaseContract( - uniswapV3WorkerAbi, - target, - this.client, - "UniswapV3Worker", + { client: this.client }, + { abi: uniswapV3WorkerAbi, addr: target, name: "UniswapV3Worker" }, ); parsedData = uniswapV3Worker.parseFunctionData(calldata); @@ -129,10 +130,8 @@ export class InstanceManagerContract extends BaseContract { } const uniswapV4Worker = new BaseContract( - uniswapV4WorkerAbi, - target, - this.client, - "UniswapV4Worker", + { client: this.client }, + { abi: uniswapV4WorkerAbi, addr: target, name: "UniswapV4Worker" }, ); parsedData = uniswapV4Worker.parseFunctionData(calldata); @@ -158,15 +157,15 @@ export class InstanceManagerContract extends BaseContract { } // TODO: - parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { switch (params.functionName) { case "configureGlobal": { const [target, data] = params.args; - const nestedCall = BaseContract.parse(target, data); + const nestedCall = this.register.parseFunctionData(target, data); return { - ...nestedCall, + ...nestedCall.args, label: `${nestedCall.label} via instanceManager`, target: this.address, }; @@ -174,24 +173,18 @@ export class InstanceManagerContract extends BaseContract { case "configureLocal": { const [target, data] = params.args; - const decoded = this.decodeFunctionData(target, data); - - return { - chainId: 0, - target: this.address, - label: this.name, - functionName: params.functionName, - args: decoded - ? { - target, - functionName: decoded.functionName, - data: json_stringify(decoded.args), - } - : { - target, - data, - }, - }; + const decoded = this.#decodeFunctionData(target, data); + + return decoded + ? { + target, + functionName: decoded.functionName, + data: json_stringify(decoded.args), + } + : { + target, + data, + }; } case "configureTreasury": { const [target, data] = params.args; @@ -211,51 +204,45 @@ export class InstanceManagerContract extends BaseContract { decoded = undefined; } - return { - chainId: 0, - target: this.address, - label: this.name, - functionName: params.functionName, - args: decoded - ? { - target, - functionName: decoded.functionName, - data: json_stringify(decoded.args), - } - : { - target, - data, - }, - }; + return decoded + ? { + target, + functionName: decoded.functionName, + data: json_stringify(decoded.args), + } + : { + target, + data, + }; } case "activate": { const [instanceOwner, treasury, weth, gear] = params.args; - return this.wrapParseCall(params, { + return { instanceOwner, treasury, weth, gear, - }); + }; } case "deploySystemContract": { const [contractType, version, saveVersion] = params.args; - return this.wrapParseCall(params, { + return { contractType: hexToString(contractType, { size: 32 }), version: version.toString(), saveVersion: saveVersion ? "true" : "false", - }); + }; } case "setGlobalAddress": { const [key, address, saveVersion] = params.args; - return this.wrapParseCall(params, { + return { key, address, saveVersion: saveVersion ? "true" : "false", - }); + }; } default: - return undefined; + return super.parseFunctionParams(params); } } diff --git a/src/permissionless/bindings/market-configurator-factory.ts b/src/permissionless/bindings/market-configurator-factory.ts index abe57304e..725a8f9ff 100644 --- a/src/permissionless/bindings/market-configurator-factory.ts +++ b/src/permissionless/bindings/market-configurator-factory.ts @@ -1,15 +1,15 @@ -import type { Address, PublicClient } from "viem"; +import type { Address, Chain, PublicClient, Transport } from "viem"; import { iMarketConfiguratorFactoryAbi } from "../../abi/310/iMarketConfiguratorFactory.js"; -import type { RawTx } from "../../sdk/types/index.js"; -import { BaseContract } from "./base-contract.js"; +import type { RawTx } from "../../sdk/index.js"; +import { BaseContract } from "../../sdk/index.js"; const abi = iMarketConfiguratorFactoryAbi; export class MarketConfiguratorFactoryContract extends BaseContract< typeof abi > { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "MarketConfiguratorFactory"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "MarketConfiguratorFactory" }); } createMarketConfiguratorTx(args: { diff --git a/src/permissionless/bindings/market-configurator.ts b/src/permissionless/bindings/market-configurator.ts index 872dc1daa..291d5f68b 100644 --- a/src/permissionless/bindings/market-configurator.ts +++ b/src/permissionless/bindings/market-configurator.ts @@ -1,8 +1,6 @@ -// External libraries - -// Viem imports import { type Address, + type Chain, type DecodeFunctionDataReturnType, decodeAbiParameters, encodeAbiParameters, @@ -15,18 +13,16 @@ import { type PublicClient, parseAbi, stringToHex, + type Transport, toBytes, } from "viem"; import { creditFacadeParamsAbi, creditManagerParamsAbi, } from "../../abi/310/configure/creditSuiteParams.js"; -// Permissionless SDK imports import { iMarketConfiguratorV310Abi } from "../../abi/310/generated.js"; -import type { RawTx } from "../../sdk/types/index.js"; -import { json_stringify } from "../../sdk/utils/index.js"; -// Local imports -import type { ParsedCall } from "../core/proposal.js"; +import type { ParsedCallArgs, RawTx } from "../../sdk/index.js"; +import { BaseContract, json_stringify } from "../../sdk/index.js"; import { parseIrmDeployParams, parseLossPolicyDeployParams, @@ -37,7 +33,7 @@ import { convertPercent } from "../utils/index.js"; import { CreditFactory } from "./factory/credit-factory.js"; import { PoolFactory } from "./factory/pool-factory.js"; import { PriceOracleFactory } from "./factory/price-oracle-factory.js"; -import { AddressProviderContract, BaseContract } from "./index.js"; +import { AddressProviderContract } from "./index.js"; import type { AddAssetParams, AllowTokenParams, @@ -61,8 +57,8 @@ export class MarketConfiguratorContract extends BaseContract { public readonly poolFactory: PoolFactory; public readonly priceOracleFactory: PriceOracleFactory; - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "MarketConfigurator"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "MarketConfigurator" }); this.creditFactory = new CreditFactory(); this.poolFactory = new PoolFactory(); this.priceOracleFactory = new PriceOracleFactory(); @@ -715,9 +711,9 @@ export class MarketConfiguratorContract extends BaseContract { return markets; } - public parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { const { functionName, args } = params; switch (functionName) { @@ -766,32 +762,26 @@ export class MarketConfiguratorContract extends BaseContract { lossPolicyParams.constructorParams, ); return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - minorVersion: minorVersion.toString(), - underlying, - name, - symbol, - interestRateModelParams: json_stringify({ - postfix: irmParsedPostfix, - salt: interestRateModelParams.salt, - constructorParams: irmParsedParams, - }), - rateKeeperParams: json_stringify({ - postfix: rateKeeperParsedPostfix, - salt: rateKeeperParams.salt, - constructorParams: rateKeeperParsedParams, - }), - lossPolicyParams: json_stringify({ - postfix: lossPolicyParsedPostfix, - salt: lossPolicyParams.salt, - constructorParams: lossPolicyParsedParams, - }), - underlyingPriceFeed, - }, + minorVersion: minorVersion.toString(), + underlying, + name, + symbol, + interestRateModelParams: json_stringify({ + postfix: irmParsedPostfix, + salt: interestRateModelParams.salt, + constructorParams: irmParsedParams, + }), + rateKeeperParams: json_stringify({ + postfix: rateKeeperParsedPostfix, + salt: rateKeeperParams.salt, + constructorParams: rateKeeperParsedParams, + }), + lossPolicyParams: json_stringify({ + postfix: lossPolicyParsedPostfix, + salt: lossPolicyParams.salt, + constructorParams: lossPolicyParsedParams, + }), + underlyingPriceFeed, }; } @@ -807,33 +797,27 @@ export class MarketConfiguratorContract extends BaseContract { ); const accountFactoryParams = decoded[0].accountFactoryParams; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - minorVersion: minorVersion.toString(), - pool, - creditSuiteParams: json_stringify({ - ...decoded[0], - minDebt: decoded[0].minDebt.toString(), - maxDebt: decoded[0].maxDebt.toString(), - accountFactoryParams: { - postfix: hexToString(accountFactoryParams.postfix).replace( - /\0/g, - "", - ), - salt: accountFactoryParams.salt, - // TODO: tmp solution, move AccountFactory decoding to plugins - constructorParams: { - addressProvider: decodeAbiParameters( - [{ type: "address" }], - accountFactoryParams.constructorParams, - )[0], - }, + minorVersion: minorVersion.toString(), + pool, + creditSuiteParams: json_stringify({ + ...decoded[0], + minDebt: decoded[0].minDebt.toString(), + maxDebt: decoded[0].maxDebt.toString(), + accountFactoryParams: { + postfix: hexToString(accountFactoryParams.postfix).replace( + /\0/g, + "", + ), + salt: accountFactoryParams.salt, + // TODO: tmp solution, move AccountFactory decoding to plugins + constructorParams: { + addressProvider: decodeAbiParameters( + [{ type: "address" }], + accountFactoryParams.constructorParams, + )[0], }, - }), - }, + }, + }), }; } @@ -842,25 +826,13 @@ export class MarketConfiguratorContract extends BaseContract { const decoded = this.priceOracleFactory.decodeConfig(config); if (decoded) { return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - data: json_stringify(decoded), - }, + pool, + data: json_stringify(decoded), }; } return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - config, - }, + pool, + config, }; } @@ -869,25 +841,13 @@ export class MarketConfiguratorContract extends BaseContract { const decoded = this.poolFactory.decodeConfig(calldata); if (decoded) { return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - data: json_stringify(decoded), - }, + pool, + data: json_stringify(decoded), }; } return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - calldata, - }, + pool, + calldata, }; } @@ -896,86 +856,50 @@ export class MarketConfiguratorContract extends BaseContract { const decoded = this.creditFactory.decodeConfig(calldata); if (decoded) { return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - creditManager, - data: json_stringify(decoded), - }, + creditManager, + data: json_stringify(decoded), }; } return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - creditManager, - calldata, - }, + creditManager, + calldata, }; } case "updateInterestRateModel": { const [pool, deployParams] = args as [Address, DeployParams]; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - deployParams: json_stringify(deployParams), - }, + pool, + deployParams: json_stringify(deployParams), }; } case "updateRateKeeper": { const [pool, deployParams] = args as [Address, DeployParams]; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - deployParams: json_stringify(deployParams), - }, + pool, + deployParams: json_stringify(deployParams), }; } case "updateLossPolicy": { const [pool, deployParams] = args as [Address, DeployParams]; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - pool, - deployParams: json_stringify(deployParams), - }, + pool, + deployParams: json_stringify(deployParams), }; } case "grantRole": { const [role, address] = args as [Hex, Address]; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - address, - role: hexToString(role, { size: 32 }), - }, + address, + role: hexToString(role, { size: 32 }), }; } default: - return undefined; + return super.parseFunctionParams(params); } } diff --git a/src/permissionless/bindings/price-feed-store.ts b/src/permissionless/bindings/price-feed-store.ts index 86def2937..e6ac7bdb6 100644 --- a/src/permissionless/bindings/price-feed-store.ts +++ b/src/permissionless/bindings/price-feed-store.ts @@ -1,6 +1,7 @@ import { type AbiParameter, type Address, + type Chain, type DecodeFunctionDataReturnType, encodeAbiParameters, formatUnits, @@ -8,29 +9,29 @@ import { hexToString, type PublicClient, recoverTypedDataAddress, + type Transport, } from "viem"; import { iPriceFeedStoreAbi } from "../../abi/310/iPriceFeedStore.js"; -import type { RawTx } from "../../sdk/types/index.js"; -import { json_stringify } from "../../sdk/utils/index.js"; +import type { RawTx } from "../../sdk/index.js"; +import { + BaseContract, + json_stringify, + type ParsedCallArgs, +} from "../../sdk/index.js"; import type { InputValueParams, - ParsedCall, PriceFeed, PriceFeedParams, } from "../core/index.js"; import { PRICE_FEED_STORE } from "../utils/index.js"; -import { BaseContract } from "./base-contract.js"; import { priceFeedSetupParams } from "./pricefeeds/index.js"; import type { PriceUpdate } from "./types.js"; const abi = iPriceFeedStoreAbi; export class PriceFeedStoreContract extends BaseContract { - chainId: number; - - constructor(address: Address, client: PublicClient, chainId: number = 1) { - super(abi, address, client, "PriceFeedStore"); - this.chainId = chainId; + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "PriceFeedStore" }); } async getZeroPriceFeed(): Promise
{ @@ -464,9 +465,9 @@ export class PriceFeedStoreContract extends BaseContract { }); } - parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { switch (params.functionName) { case "configurePriceFeeds": { const [priceFeedCalls] = params.args; @@ -492,17 +493,11 @@ export class PriceFeedStoreContract extends BaseContract { }); } } - return { - chainId: 0, - target: this.address, - label: this.name, - functionName: params.functionName, - args: { calls: json_stringify(calls) }, - }; + return { calls: json_stringify(calls) }; } default: - return undefined; + return super.parseFunctionParams(params); } } } diff --git a/src/permissionless/bindings/router/routing-manager.ts b/src/permissionless/bindings/router/routing-manager.ts index 23deaa4ba..c230bc040 100644 --- a/src/permissionless/bindings/router/routing-manager.ts +++ b/src/permissionless/bindings/router/routing-manager.ts @@ -1,23 +1,24 @@ import { type Address, + type Chain, type DecodeFunctionDataReturnType, hexToString, type PublicClient, + type Transport, } from "viem"; import { routingManagerAbi } from "../../../abi/router/routingManager.js"; -import type { ParsedCall } from "../../core/index.js"; -import { BaseContract } from "../base-contract.js"; +import { BaseContract, type ParsedCallArgs } from "../../../sdk/index.js"; const abi = routingManagerAbi; export class RoutingManagerContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "RoutingManager"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "RoutingManager" }); } - public parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { const { functionName, args } = params; switch (functionName) { @@ -25,21 +26,15 @@ export class RoutingManagerContract extends BaseContract { const [adapterType, workerType] = args; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - adapterType: hexToString(adapterType as `0x${string}`, { - size: 32, - }), - workerType: hexToString(workerType as `0x${string}`, { size: 32 }), - }, + adapterType: hexToString(adapterType as `0x${string}`, { + size: 32, + }), + workerType: hexToString(workerType as `0x${string}`, { size: 32 }), }; } default: - return undefined; + return super.parseFunctionParams(params); } } } diff --git a/src/permissionless/bindings/treasury-splitter.ts b/src/permissionless/bindings/treasury-splitter.ts index 7ea793865..a1feca1b7 100644 --- a/src/permissionless/bindings/treasury-splitter.ts +++ b/src/permissionless/bindings/treasury-splitter.ts @@ -1,20 +1,21 @@ -import type { - Address, - DecodeFunctionDataReturnType, - Hex, - PublicClient, +import { + type Address, + type Chain, + type DecodeFunctionDataReturnType, + decodeFunctionData, + type Hex, + type PublicClient, + type Transport, } from "viem"; import { ITreasurySplitterAbi } from "../../abi/310/iTreasurySplitter.js"; -import type { RawTx } from "../../sdk/types/index.js"; -import type { ParsedCall } from "../core/index.js"; -import { decodeFunctionWithNamedArgs } from "../utils/abi-decoder.js"; -import { BaseContract } from "./base-contract.js"; +import type { ParsedCallArgs, RawTx } from "../../sdk/index.js"; +import { BaseContract } from "../../sdk/index.js"; const abi = ITreasurySplitterAbi; export class TreasurySplitterContract extends BaseContract { - constructor(address: Address, client: PublicClient) { - super(abi, address, client, "TreasurySplitter"); + constructor(addr: Address, client: PublicClient) { + super({ client }, { abi, addr, name: "TreasurySplitter" }); } async defaultSplit() { @@ -91,45 +92,36 @@ export class TreasurySplitterContract extends BaseContract { }); } - public parseFunctionParams( + protected override parseFunctionParams( params: DecodeFunctionDataReturnType, - ): ParsedCall | undefined { + ): ParsedCallArgs { const { functionName, args } = params; switch (functionName) { case "distribute": { const [token] = args as [Address]; return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - token, - }, + token, }; } case "configure": { const [callData] = args as [Hex]; - const decoded = decodeFunctionWithNamedArgs(abi, callData); + const decoded = decodeFunctionData({ + abi, + data: callData, + }); if (decoded) { return { - chainId: 0, - target: this.address, - label: this.name, - functionName, - args: { - functionName: decoded.functionName, - ...decoded.args, - }, + functionName: decoded.functionName, + ...super.parseFunctionParams(params), }; } - return undefined; + return super.parseFunctionParams(params); } default: - return undefined; + return super.parseFunctionParams(params); } } } diff --git a/src/permissionless/core/proposal.ts b/src/permissionless/core/proposal.ts index 2ae116570..95f4075ae 100644 --- a/src/permissionless/core/proposal.ts +++ b/src/permissionless/core/proposal.ts @@ -1,4 +1,5 @@ import type { Address, Hex } from "viem"; +import type { ParsedCall } from "../../sdk/index.js"; export interface Signature { signer: Address; @@ -11,14 +12,6 @@ export interface CrossChainCall { target: Address; } -export interface ParsedCall { - chainId: number; - target: Address; - label: string; - functionName: string; - args: Record; -} - export interface Batch { name: string; prevHash: Hex; diff --git a/src/permissionless/core/raw-tx.ts b/src/permissionless/core/raw-tx.ts index 4dccabe35..9b7fb20a2 100644 --- a/src/permissionless/core/raw-tx.ts +++ b/src/permissionless/core/raw-tx.ts @@ -4,7 +4,7 @@ import type { EncodeFunctionDataParameters, Hex, } from "viem"; -import { createRawTx } from "../../sdk/utils/index.js"; +import { createRawTx } from "../../sdk/index.js"; export function createCallData< abi extends Abi | readonly unknown[], diff --git a/src/permissionless/utils/abi-decoder.ts b/src/permissionless/utils/abi-decoder.ts deleted file mode 100644 index 6287a0da2..000000000 --- a/src/permissionless/utils/abi-decoder.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { - type Abi, - type AbiFunction, - type DecodeFunctionDataReturnType, - decodeFunctionData, - type Hex, -} from "viem"; -import { json_stringify } from "../../sdk/utils/index.js"; - -export interface DecodedFunctionCall { - functionName: string; - args: Record; - originalDecoded: DecodeFunctionDataReturnType; -} - -/** - * Decodes function calldata and maps arguments to their parameter names from the ABI - * @param abi - The contract ABI - * @param calldata - The encoded function call data - * @returns Decoded function with named arguments and original decoded data, or null if decoding fails - */ -export function decodeFunctionWithNamedArgs( - abi: T, - calldata: Hex, -): DecodedFunctionCall | null { - try { - const decoded = decodeFunctionData({ - abi, - data: calldata, - }); - - const abiItem = (abi as Array).find( - item => item?.name === decoded.functionName && item?.type === "function", - ); - - if (!abiItem) { - return { - functionName: decoded.functionName, - args: {}, - originalDecoded: decoded, - }; - } - - const namedArgs: Record = {}; - - if (Array.isArray(decoded.args)) { - decoded.args.forEach((value, i) => { - const input = abiItem.inputs?.[i]; - if (input?.name) { - namedArgs[input.name] = input.type.startsWith("tuple") - ? json_stringify(value) - : String(value); - } - }); - } else { - // Handle object-like args (fallback) - Object.entries(decoded.args || {}).forEach(([key, value]) => { - // Try to find the actual parameter name if key is numeric - const index = parseInt(key, 10); - if (!Number.isNaN(index) && abiItem.inputs?.[index]?.name) { - namedArgs[abiItem.inputs[index].name] = String(value); - } else { - namedArgs[key] = String(value); - } - }); - } - - return { - functionName: decoded.functionName, - args: namedArgs, - originalDecoded: decoded, - }; - } catch { - return null; - } -} diff --git a/src/permissionless/utils/create2.ts b/src/permissionless/utils/create2.ts index c82d83a90..6b67390d3 100644 --- a/src/permissionless/utils/create2.ts +++ b/src/permissionless/utils/create2.ts @@ -7,7 +7,7 @@ import { stringToHex, type WalletClient, } from "viem"; -import type { ContractMethod, RawTx } from "../../sdk/types/index.js"; +import type { ContractMethod, RawTx } from "../../sdk/index.js"; export const PUBLIC_CREATE2_FACTORY = "0x4e59b44847b379578588920ca78fbf26c0b4956c" as const; diff --git a/src/permissionless/utils/format.ts b/src/permissionless/utils/format.ts index c5c7fb198..34fc8f8da 100644 --- a/src/permissionless/utils/format.ts +++ b/src/permissionless/utils/format.ts @@ -1,4 +1,4 @@ -import { json_parse } from "../../sdk/utils/index.js"; +import { json_parse } from "../../sdk/index.js"; export function formatBytecodeSize(size: number) { return `${(size / 1024).toFixed(2)} KB`; diff --git a/src/permissionless/utils/governance/batch.ts b/src/permissionless/utils/governance/batch.ts index 45c5d99b4..7005cfcdf 100644 --- a/src/permissionless/utils/governance/batch.ts +++ b/src/permissionless/utils/governance/batch.ts @@ -1,5 +1,5 @@ import { type Address, keccak256, toBytes } from "viem"; -import type { RawTx } from "../../../sdk/types/index.js"; +import type { RawTx } from "../../../sdk/index.js"; import type { SafeBatch, SafeTx } from "../../bindings/index.js"; export function convertRawTxToSafeMultisigTx(tx: RawTx): SafeTx { diff --git a/src/permissionless/utils/governance/timelock-txs.ts b/src/permissionless/utils/governance/timelock-txs.ts index 348011122..53087b263 100644 --- a/src/permissionless/utils/governance/timelock-txs.ts +++ b/src/permissionless/utils/governance/timelock-txs.ts @@ -1,6 +1,6 @@ import type { Address } from "viem"; import { governorAbi } from "../../../abi/governance/governor.js"; -import { createRawTx } from "../../../sdk/utils/index.js"; +import { createRawTx } from "../../../sdk/index.js"; import type { SafeTx, TimelockTxParams } from "../../bindings/index.js"; import { convertRawTxToSafeMultisigTx } from "./batch.js"; diff --git a/src/permissionless/utils/index.ts b/src/permissionless/utils/index.ts index ba6731e0a..000df3d9b 100644 --- a/src/permissionless/utils/index.ts +++ b/src/permissionless/utils/index.ts @@ -1,4 +1,3 @@ -export * from "./abi-decoder.js"; export * from "./abi-encoder.js"; export * from "./block-utils.js"; diff --git a/src/permissionless/utils/price-update/get-price-feeds.ts b/src/permissionless/utils/price-update/get-price-feeds.ts index acc4bccd4..3152636b1 100644 --- a/src/permissionless/utils/price-update/get-price-feeds.ts +++ b/src/permissionless/utils/price-update/get-price-feeds.ts @@ -1,9 +1,11 @@ -import type { Address, PublicClient, Transport } from "viem"; -import type { GearboxChain } from "../../../sdk/chain/index.js"; -import { AP_PRICE_FEED_COMPRESSOR } from "../../../sdk/constants/index.js"; -import { GearboxSDK } from "../../../sdk/index.js"; +import type { Address, Chain, PublicClient, Transport } from "viem"; +import type { GearboxChain } from "../../../sdk/index.js"; +import { + AP_PRICE_FEED_COMPRESSOR, + GearboxSDK, + type ParsedCall, +} from "../../../sdk/index.js"; import { AddressProviderContract } from "../../bindings/index.js"; -import type { ParsedCall } from "../../core/index.js"; import { Addresses } from "../../deployment/addresses.js"; import { deepJsonParse } from "../format.js"; import { getUpdatablePriceFeeds } from "./get-updatable-feeds.js"; @@ -64,7 +66,7 @@ export async function getCallsTouchedUpdatablePriceFeeds({ client, gasLimit, }: { - client: PublicClient; + client: PublicClient; parsedCalls: ParsedCall[]; gasLimit?: bigint; }): Promise { diff --git a/src/permissionless/utils/price-update/get-price-update-tx.ts b/src/permissionless/utils/price-update/get-price-update-tx.ts index bcdac16e3..5594311b9 100644 --- a/src/permissionless/utils/price-update/get-price-update-tx.ts +++ b/src/permissionless/utils/price-update/get-price-update-tx.ts @@ -1,5 +1,6 @@ import { type Address, + type Chain, decodeFunctionData, type Hex, multicall3Abi, @@ -7,13 +8,13 @@ import { parseAbi, type Transport, } from "viem"; -import type { GearboxChain } from "../../../sdk/chain/index.js"; +import type { GearboxChain } from "../../../sdk/index.js"; import { + createRawTx, GearboxSDK, type IPriceUpdateTx, type RawTx, } from "../../../sdk/index.js"; -import { createRawTx } from "../../../sdk/utils/index.js"; import { PriceFeedStoreContract, type PriceUpdate, @@ -37,7 +38,7 @@ export async function getPriceUpdateTx({ useMulticall3 = false, gasLimit, }: { - client: PublicClient; + client: PublicClient; priceFeeds: Address[]; useMulticall3?: boolean; gasLimit?: bigint; diff --git a/src/permissionless/utils/price-update/get-prices.ts b/src/permissionless/utils/price-update/get-prices.ts index c244705b2..38776bff3 100644 --- a/src/permissionless/utils/price-update/get-prices.ts +++ b/src/permissionless/utils/price-update/get-prices.ts @@ -4,9 +4,8 @@ import { type PublicClient, type Transport, } from "viem"; -import type { GearboxChain } from "../../../sdk/chain/index.js"; -import { GearboxSDK } from "../../../sdk/index.js"; -import { simulateMulticall } from "../../../sdk/utils/viem/index.js"; +import type { GearboxChain } from "../../../sdk/index.js"; +import { GearboxSDK, simulateMulticall } from "../../../sdk/index.js"; const latestRoundDataAbi = [ { diff --git a/src/permissionless/utils/price-update/get-updatable-feeds.ts b/src/permissionless/utils/price-update/get-updatable-feeds.ts index 3c339be87..cf0301e1f 100644 --- a/src/permissionless/utils/price-update/get-updatable-feeds.ts +++ b/src/permissionless/utils/price-update/get-updatable-feeds.ts @@ -1,13 +1,13 @@ import { type Address, getContract, type PublicClient } from "viem"; import { priceFeedCompressorAbi } from "../../../abi/compressors/priceFeedCompressor.js"; import { + bytes32ToString, type GearboxSDK, type IPriceFeedContract, type PriceFeedTreeNode, PythPriceFeed, RedstonePriceFeedContract, } from "../../../sdk/index.js"; -import { bytes32ToString } from "../../../sdk/utils/index.js"; export async function getUpdatablePriceFeeds(args: { sdk: GearboxSDK; diff --git a/src/plugins/adapters/contracts/AbstractAdapter.ts b/src/plugins/adapters/contracts/AbstractAdapter.ts index 87c26cce6..8e9f8c7fe 100644 --- a/src/plugins/adapters/contracts/AbstractAdapter.ts +++ b/src/plugins/adapters/contracts/AbstractAdapter.ts @@ -1,5 +1,5 @@ import type { Abi, Address } from "viem"; -import type { AdapterData, GearboxSDK } from "../../../sdk/index.js"; +import type { AdapterData, ConstructOptions } from "../../../sdk/index.js"; import { BaseContract } from "../../../sdk/index.js"; import type { AdapterContractType } from "../types.js"; @@ -15,9 +15,12 @@ export class AbstractAdapterContract< > extends BaseContract { public readonly targetContract: Address; - constructor(sdk: GearboxSDK, args: AbstractAdapterContractOptions) { + constructor( + options: ConstructOptions, + args: AbstractAdapterContractOptions, + ) { const { baseParams, targetContract, ...rest } = args; - super(sdk, { ...rest, ...baseParams }); + super(options, { ...rest, ...baseParams }); this.targetContract = targetContract; } diff --git a/src/plugins/adapters/contracts/AccountMigratorAdapterContract.ts b/src/plugins/adapters/contracts/AccountMigratorAdapterContract.ts index 6810f117c..5da3f6e4d 100644 --- a/src/plugins/adapters/contracts/AccountMigratorAdapterContract.ts +++ b/src/plugins/adapters/contracts/AccountMigratorAdapterContract.ts @@ -1,5 +1,5 @@ import { accountMigratorAbi } from "../../../abi/AccountMigrator.js"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -8,9 +8,9 @@ type abi = typeof abi; export class AccountMigratorAdapterContract extends AbstractAdapterContract { constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); } } diff --git a/src/plugins/adapters/contracts/BalancerV2VaultAdapterContract.ts b/src/plugins/adapters/contracts/BalancerV2VaultAdapterContract.ts index 063ffc65c..1f3dcd962 100644 --- a/src/plugins/adapters/contracts/BalancerV2VaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/BalancerV2VaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iBalancerV2VaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; import type { BalancerV2PoolStatus } from "./types.js"; @@ -13,10 +13,10 @@ export class BalancerV2VaultAdapterContract extends AbstractAdapterContract public readonly poolStatuses: BalancerV2PoolStatus[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/BalancerV3RouterAdapterContract.ts b/src/plugins/adapters/contracts/BalancerV3RouterAdapterContract.ts index dfd46dae3..cd7171ef6 100644 --- a/src/plugins/adapters/contracts/BalancerV3RouterAdapterContract.ts +++ b/src/plugins/adapters/contracts/BalancerV3RouterAdapterContract.ts @@ -1,6 +1,6 @@ import { iBalancerV3RouterAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; import type { BalancerV3PoolStatus } from "./types.js"; @@ -17,10 +17,10 @@ export class BalancerV3RouterAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); const version = Number(args.baseParams.version); if (version === 310) { diff --git a/src/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.ts b/src/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.ts index 24b3d8b97..bf0ce9fae 100644 --- a/src/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.ts +++ b/src/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.ts @@ -1,6 +1,6 @@ import { iBalancerV3WrapperAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class BalancerV3WrapperAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/CamelotV3AdapterContract.ts b/src/plugins/adapters/contracts/CamelotV3AdapterContract.ts index 87246d8eb..801a2fa49 100644 --- a/src/plugins/adapters/contracts/CamelotV3AdapterContract.ts +++ b/src/plugins/adapters/contracts/CamelotV3AdapterContract.ts @@ -1,6 +1,6 @@ import { iCamelotV3AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -14,10 +14,10 @@ export class CamelotV3AdapterContract extends AbstractAdapterContract { }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.ts b/src/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.ts index f3ef4b808..449c18a7e 100644 --- a/src/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.ts +++ b/src/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.ts @@ -1,6 +1,6 @@ import { iConvexV1BaseRewardPoolAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -14,10 +14,10 @@ export class ConvexV1BaseRewardPoolAdapterContract extends AbstractAdapterContra public readonly extraRewards: [Address, Address, Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.ts b/src/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.ts index 97463b7d1..9ff6b5730 100644 --- a/src/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.ts +++ b/src/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.ts @@ -1,6 +1,6 @@ import { iConvexV1BoosterAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class ConvexV1BoosterAdapterContract extends AbstractAdapterContract }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/Curve2AssetsAdapterContract.ts b/src/plugins/adapters/contracts/Curve2AssetsAdapterContract.ts index 247007d5b..187e1486e 100644 --- a/src/plugins/adapters/contracts/Curve2AssetsAdapterContract.ts +++ b/src/plugins/adapters/contracts/Curve2AssetsAdapterContract.ts @@ -1,6 +1,6 @@ import { iCurveV1_2AssetsAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class Curve2AssetsAdapterContract extends AbstractAdapterContract { public readonly underlyings: [Address, Address, Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/Curve3AssetsAdapterContract.ts b/src/plugins/adapters/contracts/Curve3AssetsAdapterContract.ts index e638e49b2..875c80937 100644 --- a/src/plugins/adapters/contracts/Curve3AssetsAdapterContract.ts +++ b/src/plugins/adapters/contracts/Curve3AssetsAdapterContract.ts @@ -1,6 +1,6 @@ import { iCurveV1_3AssetsAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class Curve3AssetsAdapterContract extends AbstractAdapterContract { public readonly underlyings: [Address, Address, Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/Curve4AssetsAdapterContract.ts b/src/plugins/adapters/contracts/Curve4AssetsAdapterContract.ts index 5bc0245a1..c6187f54d 100644 --- a/src/plugins/adapters/contracts/Curve4AssetsAdapterContract.ts +++ b/src/plugins/adapters/contracts/Curve4AssetsAdapterContract.ts @@ -1,6 +1,6 @@ import { iCurveV1_4AssetsAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class Curve4AssetsAdapterContract extends AbstractAdapterContract { public readonly underlyings: [Address, Address, Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/CurveV1AdapterDeposit.ts b/src/plugins/adapters/contracts/CurveV1AdapterDeposit.ts index d8c08a5cb..63c72c857 100644 --- a/src/plugins/adapters/contracts/CurveV1AdapterDeposit.ts +++ b/src/plugins/adapters/contracts/CurveV1AdapterDeposit.ts @@ -1,6 +1,6 @@ import { iCurveV1AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -17,10 +17,10 @@ export class CurveV1AdapterDeposit extends AbstractAdapterContract { public readonly underlyings: [Address, Address, Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/CurveV1AdapterStETHContract.ts b/src/plugins/adapters/contracts/CurveV1AdapterStETHContract.ts index 40c1c20c6..75ae0dec0 100644 --- a/src/plugins/adapters/contracts/CurveV1AdapterStETHContract.ts +++ b/src/plugins/adapters/contracts/CurveV1AdapterStETHContract.ts @@ -1,6 +1,6 @@ import { iCurveV1_2AssetsAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class CurveV1AdapterStETHContract extends AbstractAdapterContract { public readonly tokens: [Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/CurveV1StableNGAdapterContract.ts b/src/plugins/adapters/contracts/CurveV1StableNGAdapterContract.ts index 18f29cae1..29c7cbee5 100644 --- a/src/plugins/adapters/contracts/CurveV1StableNGAdapterContract.ts +++ b/src/plugins/adapters/contracts/CurveV1StableNGAdapterContract.ts @@ -1,6 +1,6 @@ import { iCurveV1StableNgAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -17,10 +17,10 @@ export class CurveV1StableNGAdapterContract extends AbstractAdapterContract public readonly underlyings: [Address, Address, Address, Address]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/DaiUsdsAdapterContract.ts b/src/plugins/adapters/contracts/DaiUsdsAdapterContract.ts index 148db6259..fd2d80a7b 100644 --- a/src/plugins/adapters/contracts/DaiUsdsAdapterContract.ts +++ b/src/plugins/adapters/contracts/DaiUsdsAdapterContract.ts @@ -1,6 +1,6 @@ import { iDaiUsdsAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -14,10 +14,10 @@ export class DaiUsdsAdapterContract extends AbstractAdapterContract< public readonly usds: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/ERC4626AdapterContract.ts b/src/plugins/adapters/contracts/ERC4626AdapterContract.ts index d23e349b2..9350d119c 100644 --- a/src/plugins/adapters/contracts/ERC4626AdapterContract.ts +++ b/src/plugins/adapters/contracts/ERC4626AdapterContract.ts @@ -1,6 +1,6 @@ import { ierc4626AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters, zeroAddress } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -12,10 +12,10 @@ export class ERC4626AdapterContract extends AbstractAdapterContract { public readonly asset: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); const version = Number(args.baseParams.version); if (version <= 311) { diff --git a/src/plugins/adapters/contracts/ERC4626ReferralAdapterContract.ts b/src/plugins/adapters/contracts/ERC4626ReferralAdapterContract.ts index 6145c4a25..14d43475c 100644 --- a/src/plugins/adapters/contracts/ERC4626ReferralAdapterContract.ts +++ b/src/plugins/adapters/contracts/ERC4626ReferralAdapterContract.ts @@ -1,6 +1,6 @@ import { erc4626ReferralAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -12,10 +12,10 @@ export class ERC4626ReferralAdapterContract extends AbstractAdapterContract public readonly referral: number; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/EqualizerRouterAdapterContract.ts b/src/plugins/adapters/contracts/EqualizerRouterAdapterContract.ts index cb0eb1c5c..30721880e 100644 --- a/src/plugins/adapters/contracts/EqualizerRouterAdapterContract.ts +++ b/src/plugins/adapters/contracts/EqualizerRouterAdapterContract.ts @@ -1,6 +1,6 @@ import { iEqualizerRouterAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -15,10 +15,10 @@ export class EqualizerRouterAdapterContract extends AbstractAdapterContract }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/FluidDexAdapterContract.ts b/src/plugins/adapters/contracts/FluidDexAdapterContract.ts index 537fb0f56..462057d56 100644 --- a/src/plugins/adapters/contracts/FluidDexAdapterContract.ts +++ b/src/plugins/adapters/contracts/FluidDexAdapterContract.ts @@ -1,6 +1,6 @@ import { iFluidDexAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -12,10 +12,10 @@ export class FluidDexAdapterContract extends AbstractAdapterContract { public readonly token1: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/InfinifiGatewayAdapterContract.ts b/src/plugins/adapters/contracts/InfinifiGatewayAdapterContract.ts index 2f3831c47..df1e1e450 100644 --- a/src/plugins/adapters/contracts/InfinifiGatewayAdapterContract.ts +++ b/src/plugins/adapters/contracts/InfinifiGatewayAdapterContract.ts @@ -1,6 +1,6 @@ import { iInfinifiGatewayAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -14,10 +14,10 @@ export class InfinifiGatewayAdapterContract extends AbstractAdapterContract public readonly allowedLockedTokens: Address[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/InfinifiUnwindingGatewayAdapterContract.ts b/src/plugins/adapters/contracts/InfinifiUnwindingGatewayAdapterContract.ts index 0de076a1c..6c6dc63ca 100644 --- a/src/plugins/adapters/contracts/InfinifiUnwindingGatewayAdapterContract.ts +++ b/src/plugins/adapters/contracts/InfinifiUnwindingGatewayAdapterContract.ts @@ -1,6 +1,6 @@ import { iInfinifiUnwindingGatewayAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class InfinifiUnwindingGatewayAdapterContract extends AbstractAdapterCont public readonly allowedLockedTokens: Address[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/InfraredVaultAdapterContract.ts b/src/plugins/adapters/contracts/InfraredVaultAdapterContract.ts index d7ec5d0a8..3e1bc112a 100644 --- a/src/plugins/adapters/contracts/InfraredVaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/InfraredVaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iInfraredVaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -12,10 +12,10 @@ export class InfraredVaultAdapterContract extends AbstractAdapterContract { public readonly stakedPhantomToken: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.ts b/src/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.ts index d3239aa9f..ebb786242 100644 --- a/src/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.ts +++ b/src/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.ts @@ -1,5 +1,5 @@ import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class KelpLRTDepositPoolAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/KelpLRTWithdrawalManagerAdapterContract.ts b/src/plugins/adapters/contracts/KelpLRTWithdrawalManagerAdapterContract.ts index 0f882d432..937af7fb2 100644 --- a/src/plugins/adapters/contracts/KelpLRTWithdrawalManagerAdapterContract.ts +++ b/src/plugins/adapters/contracts/KelpLRTWithdrawalManagerAdapterContract.ts @@ -1,5 +1,5 @@ import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -14,10 +14,10 @@ export class KelpLRTWithdrawalManagerAdapterContract extends AbstractAdapterCont }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/KodiakIslandGatewayAdapterContract.ts b/src/plugins/adapters/contracts/KodiakIslandGatewayAdapterContract.ts index 0ac2641f7..00214c07f 100644 --- a/src/plugins/adapters/contracts/KodiakIslandGatewayAdapterContract.ts +++ b/src/plugins/adapters/contracts/KodiakIslandGatewayAdapterContract.ts @@ -1,6 +1,6 @@ import { iKodiakIslandGatewayAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; import type { KodiakIslandStatus } from "./types.js"; @@ -15,10 +15,10 @@ export class KodiakIslandGatewayAdapterContract extends AbstractAdapterContract< }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/LidoV1AdapterContract.ts b/src/plugins/adapters/contracts/LidoV1AdapterContract.ts index 7c5c07d5f..d5710ff4b 100644 --- a/src/plugins/adapters/contracts/LidoV1AdapterContract.ts +++ b/src/plugins/adapters/contracts/LidoV1AdapterContract.ts @@ -1,6 +1,6 @@ import { iLidoV1AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -13,10 +13,10 @@ export class LidoV1AdapterContract extends AbstractAdapterContract { public readonly treasury: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MellowClaimerAdapterContract.ts b/src/plugins/adapters/contracts/MellowClaimerAdapterContract.ts index 43fa42d56..413a45bf6 100644 --- a/src/plugins/adapters/contracts/MellowClaimerAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowClaimerAdapterContract.ts @@ -1,6 +1,6 @@ import { iMellowClaimerAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class MellowClaimerAdapterContract extends AbstractAdapterContract { public readonly allowedMultiVaults: Address[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MellowDVVAdapterContract.ts b/src/plugins/adapters/contracts/MellowDVVAdapterContract.ts index 3a3954dbc..02db40ca5 100644 --- a/src/plugins/adapters/contracts/MellowDVVAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowDVVAdapterContract.ts @@ -1,6 +1,6 @@ import { mellowDvvAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -12,10 +12,10 @@ export class MellowDVVAdapterContract extends AbstractAdapterContract { public readonly asset: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MellowDepositQueueAdapterContract.ts b/src/plugins/adapters/contracts/MellowDepositQueueAdapterContract.ts index 95dabafb4..ce21ba3b5 100644 --- a/src/plugins/adapters/contracts/MellowDepositQueueAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowDepositQueueAdapterContract.ts @@ -1,5 +1,5 @@ import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -13,10 +13,10 @@ export class MellowDepositQueueAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.ts b/src/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.ts index e559ce8ed..462bc1c76 100644 --- a/src/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iMellow4626VaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters, zeroAddress } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -13,10 +13,10 @@ export class MellowERC4626VaultAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); this.asset = zeroAddress; this.vault = zeroAddress; diff --git a/src/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.ts b/src/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.ts index 3b71fbb7f..e1724ea62 100644 --- a/src/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.ts @@ -1,5 +1,5 @@ import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -12,10 +12,10 @@ export class MellowRedeemQueueAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MellowVaultAdapterContract.ts b/src/plugins/adapters/contracts/MellowVaultAdapterContract.ts index e6fc75736..bfa421769 100644 --- a/src/plugins/adapters/contracts/MellowVaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowVaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iMellowVaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class MellowVaultAdapterContract extends AbstractAdapterContract { public readonly allowedUnderlyings: Address[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MellowWrapperAdapterContract.ts b/src/plugins/adapters/contracts/MellowWrapperAdapterContract.ts index 8b00b3fb4..c0c4497cd 100644 --- a/src/plugins/adapters/contracts/MellowWrapperAdapterContract.ts +++ b/src/plugins/adapters/contracts/MellowWrapperAdapterContract.ts @@ -1,6 +1,6 @@ import { iMellowWrapperAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class MellowWrapperAdapterContract extends AbstractAdapterContract { public readonly allowedVaults: Address[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.ts b/src/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.ts index ff7306e64..edf6aa402 100644 --- a/src/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iMidasIssuanceVaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -13,10 +13,10 @@ export class MidasIssuanceVaultAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.ts b/src/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.ts index cd09bc8df..804674ab5 100644 --- a/src/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iMidasRedemptionVaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -13,10 +13,10 @@ export class MidasRedemptionVaultAdapterContract extends AbstractAdapterContract public readonly allowedTokens: { token: Address; phantomToken: Address }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/PendleRouterAdapterContract.ts b/src/plugins/adapters/contracts/PendleRouterAdapterContract.ts index 4a61c734f..5390266ad 100644 --- a/src/plugins/adapters/contracts/PendleRouterAdapterContract.ts +++ b/src/plugins/adapters/contracts/PendleRouterAdapterContract.ts @@ -1,6 +1,6 @@ import { iPendleRouterAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; import type { PendlePairStatus, PendleTokenType } from "./types.js"; @@ -27,10 +27,10 @@ export class PendleRouterAdapterContract extends AbstractAdapterContract< }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); const version = Number(args.baseParams.version); if (version === 310) { diff --git a/src/plugins/adapters/contracts/StakingRewardsAdapterContract.ts b/src/plugins/adapters/contracts/StakingRewardsAdapterContract.ts index 394dbb31a..c8a6b0f79 100644 --- a/src/plugins/adapters/contracts/StakingRewardsAdapterContract.ts +++ b/src/plugins/adapters/contracts/StakingRewardsAdapterContract.ts @@ -1,6 +1,6 @@ import { iStakingRewardsAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class StakingRewardsAdapterContract extends AbstractAdapterContract< public readonly referral: number; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); const version = Number(args.baseParams.version); if (version === 310) { diff --git a/src/plugins/adapters/contracts/TraderJoeRouterAdapterContract.ts b/src/plugins/adapters/contracts/TraderJoeRouterAdapterContract.ts index 15ae9975a..ead4da489 100644 --- a/src/plugins/adapters/contracts/TraderJoeRouterAdapterContract.ts +++ b/src/plugins/adapters/contracts/TraderJoeRouterAdapterContract.ts @@ -1,6 +1,6 @@ import { iTraderJoeRouterAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; import type { TraderJoePoolVersion } from "./types.js"; @@ -17,10 +17,10 @@ export class TraderJoeRouterAdapterContract extends AbstractAdapterContract }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/UniswapV2AdapterContract.ts b/src/plugins/adapters/contracts/UniswapV2AdapterContract.ts index 6f7543421..d23418a75 100644 --- a/src/plugins/adapters/contracts/UniswapV2AdapterContract.ts +++ b/src/plugins/adapters/contracts/UniswapV2AdapterContract.ts @@ -4,7 +4,7 @@ import { type DecodeFunctionDataReturnType, decodeAbiParameters, } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import { formatBN } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -19,10 +19,10 @@ export class UniswapV2AdapterContract extends AbstractAdapterContract { }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( @@ -47,14 +47,14 @@ export class UniswapV2AdapterContract extends AbstractAdapterContract { })); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): string[] | undefined { + ): string[] { switch (params.functionName) { case "swapDiffTokensForTokens": { const [leftoverAmount, rateMinRAY, path, _deadline] = params.args; - const leftoverAmountStr = this.sdk.tokensMeta.formatBN( + const leftoverAmountStr = this.tokensMeta.formatBN( path[0], leftoverAmount, ); @@ -70,7 +70,7 @@ export class UniswapV2AdapterContract extends AbstractAdapterContract { } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/plugins/adapters/contracts/UniswapV3AdapterContract.ts b/src/plugins/adapters/contracts/UniswapV3AdapterContract.ts index 9d806c34e..5411ac139 100644 --- a/src/plugins/adapters/contracts/UniswapV3AdapterContract.ts +++ b/src/plugins/adapters/contracts/UniswapV3AdapterContract.ts @@ -4,7 +4,7 @@ import { type DecodeFunctionDataReturnType, decodeAbiParameters, } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import { formatBN } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -20,10 +20,10 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( @@ -50,18 +50,18 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { })); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): string[] | undefined { + ): string[] { switch (params.functionName) { case "exactInputSingle": { const [{ tokenIn, tokenOut, fee, amountIn, amountOutMinimum }] = params.args; - const tokenInSym = this.sdk.tokensMeta.symbol(tokenIn); - const tokenOutSym = this.sdk.tokensMeta.symbol(tokenOut); + const tokenInSym = this.tokensMeta.symbol(tokenIn); + const tokenOutSym = this.tokensMeta.symbol(tokenOut); - const amountInStr = this.sdk.tokensMeta.formatBN(tokenIn, amountIn); - const amountOutMinimumStr = this.sdk.tokensMeta.formatBN( + const amountInStr = this.tokensMeta.formatBN(tokenIn, amountIn); + const amountOutMinimumStr = this.tokensMeta.formatBN( tokenOut, amountOutMinimum, ); @@ -73,10 +73,10 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { case "exactDiffInputSingle": { const [{ tokenIn, tokenOut, fee, leftoverAmount, rateMinRAY }] = params.args; - const tokenInSym = this.sdk.tokensMeta.symbol(tokenIn); - const tokenOutSym = this.sdk.tokensMeta.symbol(tokenOut); + const tokenInSym = this.tokensMeta.symbol(tokenIn); + const tokenOutSym = this.tokensMeta.symbol(tokenOut); - const leftoverAmountStr = this.sdk.tokensMeta.formatBN( + const leftoverAmountStr = this.tokensMeta.formatBN( tokenIn, leftoverAmount, ); @@ -90,9 +90,9 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { const pathStr = this.trackInputPath(path); const token = `0x${path.replace("0x", "").slice(0, 40)}` as Address; - const amountInStr = this.sdk.tokensMeta.formatBN(token, amountIn); + const amountInStr = this.tokensMeta.formatBN(token, amountIn); - const amountOutMinimumStr = this.sdk.tokensMeta.formatBN( + const amountOutMinimumStr = this.tokensMeta.formatBN( `0x${path.slice(-40, path.length)}`, amountOutMinimum, ); @@ -104,7 +104,7 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { case "exactDiffInput": { const [{ leftoverAmount, rateMinRAY, path }] = params.args; - const leftoverAmountStr = this.sdk.tokensMeta.formatBN( + const leftoverAmountStr = this.tokensMeta.formatBN( `0x${path.replace("0x", "").slice(0, 40)}`, leftoverAmount, ); @@ -122,12 +122,12 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { const [{ amountInMaximum, amountOut, path }] = params.args; const pathStr = this.trackOutputPath(path); - const amountInMaximumStr = this.sdk.tokensMeta.formatBN( + const amountInMaximumStr = this.tokensMeta.formatBN( `0x${path.slice(-40, path.length)}`, amountInMaximum, ); - const amountOutStr = this.sdk.tokensMeta.formatBN( + const amountOutStr = this.tokensMeta.formatBN( `0x${path.replace("0x", "").slice(0, 40)}`, amountOut, ); @@ -140,14 +140,14 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { const [{ tokenIn, tokenOut, fee, amountOut, amountInMaximum }] = params.args; - const tokenInSym = this.sdk.tokensMeta.symbol(tokenIn); - const tokenOutSym = this.sdk.tokensMeta.symbol(tokenOut); + const tokenInSym = this.tokensMeta.symbol(tokenIn); + const tokenOutSym = this.tokensMeta.symbol(tokenOut); - const amountInMaximumStr = this.sdk.tokensMeta.formatBN( + const amountInMaximumStr = this.tokensMeta.formatBN( tokenIn, amountInMaximum, ); - const amountOutStr = this.sdk.tokensMeta.formatBN(tokenOut, amountOut); + const amountOutStr = this.tokensMeta.formatBN(tokenOut, amountOut); return [ `(amountInMaximum: ${amountInMaximumStr}, amountOut: ${amountOutStr}, path: ${tokenInSym} ==(fee: ${fee})==> ${tokenOutSym})`, @@ -155,7 +155,7 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { } default: - return undefined; + return super.stringifyFunctionParams(params); } } @@ -167,7 +167,7 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { pointer, pointer + 40, )}`.toLowerCase() as Address; - result += this.sdk.tokensMeta.symbol(from) || from; + result += this.tokensMeta.symbol(from) || from; pointer += 40; if (pointer > path.length - 6) return result; @@ -187,7 +187,7 @@ export class UniswapV3AdapterContract extends AbstractAdapterContract { while (pointer >= 40) { pointer -= 40; const from = `0x${path.slice(pointer, pointer + 40)}` as Address; - result += this.sdk.tokensMeta.symbol(from) || from; + result += this.tokensMeta.symbol(from) || from; if (pointer < 6) return result; pointer -= 6; diff --git a/src/plugins/adapters/contracts/UniswapV4AdapterContract.ts b/src/plugins/adapters/contracts/UniswapV4AdapterContract.ts index 1397185a4..aaf73099d 100644 --- a/src/plugins/adapters/contracts/UniswapV4AdapterContract.ts +++ b/src/plugins/adapters/contracts/UniswapV4AdapterContract.ts @@ -1,6 +1,6 @@ import { iUniswapV4AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -17,10 +17,10 @@ export class UniswapV4AdapterContract extends AbstractAdapterContract { }[]; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/UpshiftVaultAdapterContract.ts b/src/plugins/adapters/contracts/UpshiftVaultAdapterContract.ts index 167749863..1f76e765d 100644 --- a/src/plugins/adapters/contracts/UpshiftVaultAdapterContract.ts +++ b/src/plugins/adapters/contracts/UpshiftVaultAdapterContract.ts @@ -1,6 +1,6 @@ import { iUpshiftVaultAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -13,10 +13,10 @@ export class UpshiftVaultAdapterContract extends AbstractAdapterContract { public readonly stakedPhantomToken: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/VelodromeV2AdapterContract.ts b/src/plugins/adapters/contracts/VelodromeV2AdapterContract.ts index 77717803a..ff01308ee 100644 --- a/src/plugins/adapters/contracts/VelodromeV2AdapterContract.ts +++ b/src/plugins/adapters/contracts/VelodromeV2AdapterContract.ts @@ -1,6 +1,6 @@ import { iVelodromeV2RouterAdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -16,10 +16,10 @@ export class VelodromeV2RouterAdapterContract extends AbstractAdapterContract, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/WstETHV1AdapterContract.ts b/src/plugins/adapters/contracts/WstETHV1AdapterContract.ts index d40ccf3c6..1b183cf51 100644 --- a/src/plugins/adapters/contracts/WstETHV1AdapterContract.ts +++ b/src/plugins/adapters/contracts/WstETHV1AdapterContract.ts @@ -1,6 +1,6 @@ import { iwstEthv1AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class WstETHV1AdapterContract extends AbstractAdapterContract { public readonly stETH: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/adapters/contracts/YearnV2AdapterContract.ts b/src/plugins/adapters/contracts/YearnV2AdapterContract.ts index 97b25dfae..8c211965c 100644 --- a/src/plugins/adapters/contracts/YearnV2AdapterContract.ts +++ b/src/plugins/adapters/contracts/YearnV2AdapterContract.ts @@ -1,6 +1,6 @@ import { iYearnV2AdapterAbi } from "@gearbox-protocol/integrations-v3"; import { type Address, decodeAbiParameters } from "viem"; -import type { GearboxSDK } from "../../../sdk/index.js"; +import type { ConstructOptions } from "../../../sdk/index.js"; import type { AbstractAdapterContractOptions } from "./AbstractAdapter.js"; import { AbstractAdapterContract } from "./AbstractAdapter.js"; @@ -11,10 +11,10 @@ export class YearnV2RouterAdapterContract extends AbstractAdapterContract { public readonly token: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, args: Omit, "abi">, ) { - super(sdk, { ...args, abi }); + super(options, { ...args, abi }); // Decode parameters directly using ABI decoding const decoded = decodeAbiParameters( diff --git a/src/plugins/bots/BotsPlugin.ts b/src/plugins/bots/BotsPlugin.ts index 78040c8b0..e6b16b15f 100644 --- a/src/plugins/bots/BotsPlugin.ts +++ b/src/plugins/bots/BotsPlugin.ts @@ -10,6 +10,7 @@ import { TypedObjectUtils, VERSION_RANGE_310, } from "../../sdk/index.js"; +import deserializePartialLiquidationBotParams from "./deserializePartialLiquidationBotParams.js"; import { PartialLiquidationBotV300Contract } from "./PartialLiquidationBotV300Contract.js"; import { PartialLiquidationBotV310Contract } from "./PartialLiquidationBotV310Contract.js"; import { @@ -83,18 +84,17 @@ export class BotsPlugin #loadStateMarketState(mc: Address, state: readonly BotState[]): void { // for v300, assume that each market configurator has exactly 4 bots // sort them by minHealthFactor and assign type based on index - const bots = state - .map(state => this.#createBot(mc, state)) - .sort((a, b) => a.minHealthFactor - b.minHealthFactor); - if (bots.length && isV300(Number(bots[0].version))) { - if (bots.length !== 4) { + const states = [...state].sort( + (a, b) => + deserializePartialLiquidationBotParams(a.baseParams).minHealthFactor - + deserializePartialLiquidationBotParams(b.baseParams).minHealthFactor, + ); + if (states.length && isV300(states[0].baseParams.version)) { + if (states.length !== 4) { throw new Error(`expected 4 bots v300 for market configurator ${mc}`); } - for (let i = 0; i < bots.length; i++) { - (bots[i] as PartialLiquidationBotV300Contract).botType = - LIQUIDATION_BOT_TYPES[i]; - } } + const bots = states.map((s, i) => this.#createBot(mc, s, i)); this.botsByMarket.upsert(mc, bots); } @@ -148,13 +148,16 @@ export class BotsPlugin #createBot( marketConfigurator: Address, data: BotState, + index: number, ): PartialLiquidationBotContract { const v = Number(data.baseParams.version); if (isV300(v)) { + const botType = LIQUIDATION_BOT_TYPES[index]; return new PartialLiquidationBotV300Contract( this.sdk, data, marketConfigurator, + botType, ); } else if (isV310(v)) { return new PartialLiquidationBotV310Contract( diff --git a/src/plugins/bots/PartialLiquidationBotBaseContract.ts b/src/plugins/bots/PartialLiquidationBotBaseContract.ts index e55b4794c..e913620b2 100644 --- a/src/plugins/bots/PartialLiquidationBotBaseContract.ts +++ b/src/plugins/bots/PartialLiquidationBotBaseContract.ts @@ -4,6 +4,7 @@ import { decodeAbiParameters } from "viem"; import type { GearboxSDK } from "../../sdk/index.js"; import { BaseContract, formatPercentage } from "../../sdk/index.js"; +import deserializePartialLiquidationBotParams from "./deserializePartialLiquidationBotParams.js"; import type { BotParameters, BotState, BotStateBaseHuman } from "./types.js"; export interface PartialLiquidationBotBaseArgs< @@ -37,27 +38,12 @@ export abstract class PartialLiquidationBotBaseContract< super(sdk, args); this.#serializedParams = args.serializedParams; // same for v300 and v310 bots - const [ - treasury, - minHealthFactor, - maxHealthFactor, - premiumScaleFactor, - feeScaleFactor, - ] = decodeAbiParameters( - [ - { name: "treasury", type: "address" }, - { name: "minHealthFactor", type: "uint16" }, - { name: "maxHealthFactor", type: "uint16" }, - { name: "premiumScaleFactor", type: "uint16" }, - { name: "feeScaleFactor", type: "uint16" }, - ], - args.serializedParams, - ); - this.treasury = treasury; - this.minHealthFactor = minHealthFactor; - this.maxHealthFactor = maxHealthFactor; - this.premiumScaleFactor = premiumScaleFactor; - this.feeScaleFactor = feeScaleFactor; + const bp = deserializePartialLiquidationBotParams(args); + this.treasury = bp.treasury; + this.minHealthFactor = bp.minHealthFactor; + this.maxHealthFactor = bp.maxHealthFactor; + this.premiumScaleFactor = bp.premiumScaleFactor; + this.feeScaleFactor = bp.feeScaleFactor; this.marketConfigurator = args.marketConfigurator; this.requiredPermissions = args.requiredPermissions; diff --git a/src/plugins/bots/PartialLiquidationBotV300Contract.ts b/src/plugins/bots/PartialLiquidationBotV300Contract.ts index 5125fd1ec..8498d826e 100644 --- a/src/plugins/bots/PartialLiquidationBotV300Contract.ts +++ b/src/plugins/bots/PartialLiquidationBotV300Contract.ts @@ -13,16 +13,22 @@ const abi = iPartialLiquidationBotV300Abi; type abi = typeof abi; export class PartialLiquidationBotV300Contract extends PartialLiquidationBotBaseContract { - #botType: LiquidationBotType | undefined; + public readonly botType: LiquidationBotType; - constructor(sdk: GearboxSDK, args: BotState, marketConfigurator: Address) { + constructor( + sdk: GearboxSDK, + args: BotState, + marketConfigurator: Address, + botType: LiquidationBotType, + ) { super(sdk, { abi, ...args.baseParams, requiredPermissions: args.requiredPermissions, marketConfigurator, - name: "PartialLiquidationBotV300", + name: `PartialLiquidationBotV300 (${botType})`, }); + this.botType = botType; } public stateHuman(raw?: boolean): BotStateV300Human { @@ -31,23 +37,4 @@ export class PartialLiquidationBotV300Contract extends PartialLiquidationBotBase botType: this.botType, }; } - - /** - * Set the bot type - * This method should only be called once from BotsPlugin - */ - public set botType(type: LiquidationBotType) { - if (this.#botType) { - throw new Error("bot type already set"); - } - this.#botType = type; - this.name = `PartialLiquidationBotV300 (${type})`; - } - - public get botType(): LiquidationBotType { - if (!this.#botType) { - throw new Error("bot type not set"); - } - return this.#botType; - } } diff --git a/src/plugins/bots/deserializePartialLiquidationBotParams.ts b/src/plugins/bots/deserializePartialLiquidationBotParams.ts new file mode 100644 index 000000000..0406cc59f --- /dev/null +++ b/src/plugins/bots/deserializePartialLiquidationBotParams.ts @@ -0,0 +1,31 @@ +import { decodeAbiParameters } from "viem"; +import type { BaseParams } from "../../sdk/index.js"; +import type { BotParameters } from "./types.js"; + +export default function deserializePartialLiquidationBotParams( + params: Pick, +): BotParameters { + const [ + treasury, + minHealthFactor, + maxHealthFactor, + premiumScaleFactor, + feeScaleFactor, + ] = decodeAbiParameters( + [ + { name: "treasury", type: "address" }, + { name: "minHealthFactor", type: "uint16" }, + { name: "maxHealthFactor", type: "uint16" }, + { name: "premiumScaleFactor", type: "uint16" }, + { name: "feeScaleFactor", type: "uint16" }, + ], + params.serializedParams, + ); + return { + treasury, + minHealthFactor, + maxHealthFactor, + premiumScaleFactor, + feeScaleFactor, + }; +} diff --git a/src/plugins/zappers/ZappersPlugin.ts b/src/plugins/zappers/ZappersPlugin.ts index 6f1f46a18..04f9b88c3 100644 --- a/src/plugins/zappers/ZappersPlugin.ts +++ b/src/plugins/zappers/ZappersPlugin.ts @@ -148,7 +148,7 @@ export class ZappersPlugin for (const t of [...zappersTokens, ...extraZappersTokens]) { this.sdk.tokensMeta.upsert(t.addr, t); - this.sdk.addressLabels.set(t.addr as Address, t.symbol); + this.sdk.setAddressLabel(t.addr, t.symbol); } } } diff --git a/src/sdk/GearboxSDK.ts b/src/sdk/GearboxSDK.ts index b3770805d..c274baf6a 100644 --- a/src/sdk/GearboxSDK.ts +++ b/src/sdk/GearboxSDK.ts @@ -1,4 +1,4 @@ -import type { Address, Hex } from "viem"; +import type { Address } from "viem"; import { createPublicClient, defineChain, @@ -9,8 +9,8 @@ import { type Transport, } from "viem"; import type { HttpRpcClientOptions } from "viem/utils"; -import type { BaseContract, BaseState, IBaseContract } from "./base/index.js"; -import { AddressLabeller, TokensMeta } from "./base/index.js"; +import type { BaseState, IBaseContract } from "./base/index.js"; +import { ChainContractsRegister } from "./base/index.js"; import type { GearboxChain, NetworkType } from "./chain/chains.js"; import { detectNetwork, getChain } from "./chain/index.js"; import type { VersionRange } from "./constants/index.js"; @@ -41,14 +41,9 @@ import { type PluginsMap, } from "./plugins/index.js"; import { createRouter, type IRouterContract } from "./router/index.js"; -import type { - GearboxState, - GearboxStateHuman, - ILogger, - MultiCall, -} from "./types/index.js"; +import type { GearboxState, GearboxStateHuman } from "./types/index.js"; import type { PickSomeRequired } from "./utils/index.js"; -import { AddressMap, TypedObjectUtils, toAddress } from "./utils/index.js"; +import { TypedObjectUtils, toAddress } from "./utils/index.js"; import { Hooks } from "./utils/internal/index.js"; import { getLogsSafe } from "./utils/viem/index.js"; @@ -188,12 +183,12 @@ export type SDKHooks = { rehydrate: [SyncStateOptions]; }; -export class GearboxSDK { +export class GearboxSDK< + const Plugins extends PluginsMap = {}, +> extends ChainContractsRegister { readonly #hooks = new Hooks(); readonly plugins: Plugins; - #client: PublicClient; - // Block which was use for data query #currentBlock?: bigint; #timestamp?: bigint; @@ -207,34 +202,12 @@ export class GearboxSDK { #marketRegister?: MarketRegister; #priceFeeds?: PriceFeedRegister; - public readonly logger?: ILogger; public readonly gasLimit: bigint | undefined; - public readonly addressLabels = new AddressLabeller(); - - /** - * Interest rate models can be reused across chain (and SDK operates on chain level) - * TODO: use whatever interface is necessary for InterestRateModels - */ - public readonly interestRateModels = new AddressMap< - BaseContract - >(); - /** * Will throw an error if contract type is not supported, otherwise will try to use generic contract first, if possible */ public readonly strictContractTypes: boolean; - /** - * All contracts known to sdk - */ - public readonly contracts = new AddressMap>( - undefined, - "contracts", - ); - /** - * Token metadata such as symbol and decimals - */ - public readonly tokensMeta: TokensMeta; public addHook = this.#hooks.addHook.bind(this.#hooks); public removeHook = this.#hooks.removeHook.bind(this.#hooks); @@ -300,11 +273,9 @@ export class GearboxSDK { } private constructor(options: SDKContructorArgs) { - this.logger = options.logger; + super(options.client, options.logger); this.strictContractTypes = options.strictContractTypes ?? false; this.plugins = options.plugins ?? ({} as Plugins); - // need to explicitly set chain id on testnets (e.g. 7878 = mainnet) - this.#client = options.client; for (const plugin of Object.values(this.plugins)) { plugin.sdk = this; @@ -313,7 +284,8 @@ export class GearboxSDK { if (options.gasLimit !== null) { this.gasLimit = options.gasLimit || 550_000_000n; } - this.tokensMeta = new TokensMeta(this); + // this is essentiag, we need sdk be present in static contracts register + Object.assign(this, ChainContractsRegister.for(this.client, this.logger)); } async #attach(opts: AttachOptionsInternal): Promise { @@ -494,88 +466,8 @@ export class GearboxSDK { }); } - public get client(): PublicClient { - return this.#client; - } - - /** - * Replaces client inflight - * You're responsible for all inconsistencies between new and old client - * @param options - */ - public replaceClient(options: ClientOptions, network?: NetworkOptions) { - this.#client = createClient(options, network); - } - public get networkType(): NetworkType { - return this.client.chain.network; - } - - public get chain(): GearboxChain { - return this.client.chain; - } - - public get chainId(): number { - return this.client.chain.id; - } - - /** - * Converts contract call into some human-friendly string - * This method is safe and should not throw - * @param address - * @param calldata - * @returns - */ - public parseFunctionData(address: Address, calldata: Hex): string { - const contract = this.contracts.get(address); - // TODO: fallback to 4bytes directory - return contract - ? contract.parseFunctionData(calldata) - : `unknown: ${address}.${calldata.slice(0, 10)}`; - } - - /** - * Converts multicalls into some human-friendly strings - * This method is safe and should not throw - * @param address - * @param calldata - * @returns - */ - public parseMultiCall(calls: MultiCall[]): string[] { - return calls.map(call => - this.parseFunctionData(call.target, call.callData), - ); - } - - /** - * Return args, function, type and address name from contract call - * @param address - * @param calldata - * @returns - */ - public parseFunctionDataToObject(address: Address, calldata: Hex) { - const contract = this.contracts.get(address); - // TODO: fallback to 4bytes directory - - return contract - ? { - ...contract.parseFunctionDataToObject(calldata), - address, - type: contract.contractType, - } - : null; - } - - /** - * Converts multicalls into call info - * @param address - * @param calldata - * @returns - */ - public parseMultiCallToObject(calls: MultiCall[]) { - return calls.map(call => - this.parseFunctionDataToObject(call.target, call.callData), - ); + return (this.client.chain as GearboxChain).network; } public stateHuman(raw = true): GearboxStateHuman { @@ -678,7 +570,7 @@ export class GearboxSDK { }); for (const log of logs) { - const contract = this.contracts.get(log.address); + const contract = this.getContract(log.address); if (contract) { const event = parseEventLogs({ abi: contract.abi, @@ -784,20 +676,17 @@ export class GearboxSDK { public get botListContract(): BotListContract | undefined { const addr = this.addressProvider.getAddress(AP_BOT_LIST, NO_VERSION); - if (!this.contracts.has(addr)) { - // this registers it in sdk.contracts as constructor's side-effect - return new BotListContract(this, addr); - } - return this.contracts.get(addr) as unknown as BotListContract; + return ( + this.getContract(addr) ?? new BotListContract(this, addr) + ); } public get gearStakingContract(): GearStakingContract | undefined { const addr = this.addressProvider.getAddress(AP_GEAR_STAKING, NO_VERSION); - if (!this.contracts.has(addr)) { - // this registers it in sdk.contracts as constructor's side-effect - return new GearStakingContract(this, addr); - } - return this.contracts.get(addr) as unknown as GearStakingContract; + return ( + this.getContract(addr) ?? + new GearStakingContract(this, addr) + ); } public get marketRegister(): MarketRegister { @@ -831,7 +720,7 @@ export class GearboxSDK { ); facadeAddr = cm.creditFacade.address; } - const facadeV = this.contracts.mustGet(facadeAddr).version; + const facadeV = this.mustGetContract(facadeAddr).version; routerRange = isV310(facadeV) ? VERSION_RANGE_310 : VERSION_RANGE_300; } const routerEntry = this.addressProvider.getLatest(AP_ROUTER, routerRange); @@ -839,19 +728,6 @@ export class GearboxSDK { throw new Error(`router not found in version range ${routerRange}`); } const [routerAddr, routerV] = routerEntry; - if (!this.contracts.has(routerAddr)) { - // router is added to this.contracts as constructor's side-effect - return createRouter(this, routerAddr, routerV); - } - return this.contracts.get(routerAddr) as unknown as IRouterContract; - } - - /** - * Helper to get human-friendly label for address - * @param address - * @returns - */ - public labelAddress(address: Address): string { - return this.addressLabels.get(address); + return createRouter(this, routerAddr, routerV); } } diff --git a/src/sdk/accountMigration/AbstractMigrateCreditAccountsService.ts b/src/sdk/accountMigration/AbstractMigrateCreditAccountsService.ts index 686dc82b3..eda3d936c 100644 --- a/src/sdk/accountMigration/AbstractMigrateCreditAccountsService.ts +++ b/src/sdk/accountMigration/AbstractMigrateCreditAccountsService.ts @@ -17,8 +17,6 @@ import type { CreditAccountData_Legacy, CreditManagerData_Legacy, } from "../sdk-legacy/index.js"; -import type { ILogger } from "../types/index.js"; -import { childLogger } from "../utils/index.js"; import type { MigrateCreditAccountProps, MigrationBotState, @@ -27,7 +25,6 @@ import type { } from "./types.js"; export abstract class AbstractMigrateCreditAccountsService extends SDKConstruct { - #logger?: ILogger; #version: number; #service: ICreditAccountsService; @@ -62,8 +59,7 @@ export abstract class AbstractMigrateCreditAccountsService extends SDKConstruct this.#version = version; this.#service = createCreditAccountService(this.sdk, version); - this.#logger = childLogger("MigrateCreditAccountsService", sdk.logger); - this.#logger?.debug( + this.logger?.debug( `Created MigrateCreditAccountsService with version: ${this.#version}`, ); } diff --git a/src/sdk/accountMigration/types.ts b/src/sdk/accountMigration/types.ts index 3a472273a..dab484bea 100644 --- a/src/sdk/accountMigration/types.ts +++ b/src/sdk/accountMigration/types.ts @@ -6,7 +6,6 @@ import type { } from "viem"; import type { accountMigratorPreviewerV310Abi } from "../../abi/migration.js"; -import type { SDKConstruct } from "../base/SDKConstruct.js"; import type { Asset, RouterCASlice } from "../router/index.js"; export type MigrationBotState = { @@ -78,7 +77,7 @@ export type PreviewMigrationResult = Awaited< > >["result"]; -export interface IMigrateCreditAccountsService extends SDKConstruct { +export interface IMigrateCreditAccountsService { /** * Preview delayed withdrawal for a given credit account * @param props - {@link PreviewCreditAccountMigrationProps} diff --git a/src/sdk/accounts/AbstractCreditAccountsService.ts b/src/sdk/accounts/AbstractCreditAccountsService.ts index 05f958ab0..269978629 100644 --- a/src/sdk/accounts/AbstractCreditAccountsService.ts +++ b/src/sdk/accounts/AbstractCreditAccountsService.ts @@ -36,8 +36,8 @@ import type { } from "../market/index.js"; import { type Asset, assetsMap, type RouterCASlice } from "../router/index.js"; import { BigIntMath } from "../sdk-legacy/index.js"; -import type { ILogger, IPriceUpdateTx, MultiCall } from "../types/index.js"; -import { AddressMap, childLogger } from "../utils/index.js"; +import type { IPriceUpdateTx, MultiCall } from "../types/index.js"; +import { AddressMap } from "../utils/index.js"; import { simulateWithPriceUpdates } from "../utils/viem/index.js"; import type { AddCollateralProps, @@ -85,7 +85,6 @@ export function getWithdrawalCompressorAddress(chainId: number) { export abstract class AbstractCreditAccountService extends SDKConstruct { #compressor: Address; #batchSize?: number; - #logger?: ILogger; constructor(sdk: GearboxSDK, options?: CreditAccountServiceOptions) { super(sdk); @@ -94,8 +93,7 @@ export abstract class AbstractCreditAccountService extends SDKConstruct { VERSION_RANGE_310, ); this.#batchSize = options?.batchSize; - this.#logger = childLogger("CreditAccountsService", sdk.logger); - this.#logger?.debug( + this.logger?.debug( `credit account compressor address: ${this.#compressor}`, ); } @@ -214,7 +212,7 @@ export abstract class AbstractCreditAccountService extends SDKConstruct { offset = newOffset; } while (offset !== 0n); } - this.#logger?.debug( + this.logger?.debug( `loaded ${allCAs.length} credit accounts (${ allCAs.length - revertingOffset } reverting)`, @@ -388,7 +386,7 @@ export abstract class AbstractCreditAccountService extends SDKConstruct { lossPolicyData = await market.lossPolicy.getLiquidationData( account.creditAccount, ); - this.#logger?.debug({ lossPolicyData }, "loss policy data"); + this.logger?.debug({ lossPolicyData }, "loss policy data"); } const tx = cm.creditFacade.liquidateCreditAccount( @@ -1054,7 +1052,7 @@ export abstract class AbstractCreditAccountService extends SDKConstruct { }); } - this.#logger?.debug( + this.logger?.debug( { accounts: resp[0]?.length ?? 0, nextOffset: Number(resp[1]), @@ -1163,7 +1161,7 @@ export abstract class AbstractCreditAccountService extends SDKConstruct { .map(t => this.labelAddress(t)) .join(", "); const remark = ignoreReservePrices ? " main" : ""; - this.#logger?.debug( + this.logger?.debug( { account: creditAccount?.creditAccount, manager: cm.name }, `generating price feed updates for ${tStr} from ${priceFeeds.length}${remark} price feeds`, ); @@ -1182,7 +1180,7 @@ export abstract class AbstractCreditAccountService extends SDKConstruct { const market = this.sdk.marketRegister.findByCreditManager(creditManager); const cm = this.sdk.marketRegister.findCreditManager(creditManager); const update = await this.getUpdateForAccount(options); - this.#logger?.debug( + this.logger?.debug( { account: creditAccount?.creditAccount, manager: cm.name }, `getting on demand price updates from ${update.txs.length} txs`, ); diff --git a/src/sdk/accounts/types.ts b/src/sdk/accounts/types.ts index fa5c91fcf..459a86b8b 100644 --- a/src/sdk/accounts/types.ts +++ b/src/sdk/accounts/types.ts @@ -9,8 +9,12 @@ import type { creditAccountCompressorAbi } from "../../abi/compressors/creditAcc import type { iWithdrawalCompressorV310Abi } from "../../abi/IWithdrawalCompressorV310.js"; import type { LiquidationBotType as LiquidationBotTypeSDK } from "../../plugins/bots/types.js"; import type { MigrationBotType } from "../accountMigration/types.js"; -import type { ConnectedBotData, CreditAccountData } from "../base/index.js"; -import type { SDKConstruct } from "../base/SDKConstruct.js"; +import type { + ConnectedBotData, + Construct, + CreditAccountData, +} from "../base/index.js"; +import type { GearboxSDK } from "../GearboxSDK.js"; import type { CreditSuite, OnDemandPriceUpdates, @@ -498,7 +502,8 @@ export type GetConnectedMigrationBotsResult = } | undefined; -export interface ICreditAccountsService extends SDKConstruct { +export interface ICreditAccountsService extends Construct { + sdk: GearboxSDK; /** * Returns single credit account data, or undefined if it's not found * Performs all necessary price feed updates under the hood diff --git a/src/sdk/base/AddressLabeller.ts b/src/sdk/base/AddressLabeller.ts deleted file mode 100644 index fed6766f0..000000000 --- a/src/sdk/base/AddressLabeller.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { Address } from "viem"; - -import { NOT_DEPLOYED } from "../constants/index.js"; -import { AddressMap } from "../utils/index.js"; -import type { IAddressLabeller } from "./IAddressLabeller.js"; - -/** - * Helper class to be used during transition from v3 to v3.1 - */ -export class AddressLabeller implements IAddressLabeller { - #labels = new AddressMap(undefined, "addressLabeller"); - - public set( - address: Address, - label: string | ((oldLabel?: string) => string), - ): void { - if (address === NOT_DEPLOYED) { - return; - } - if (typeof label === "string") { - this.#labels.upsert(address, label); - } else { - this.#labels.upsert(address, label(this.#labels.get(address))); - } - } - - public get(address: Address): string { - const label = this.#labels.get(address); - return label ? `${address} [${label}]` : address; - } - - public get all(): Record { - return this.#labels.asRecord(); - } -} diff --git a/src/sdk/base/BaseContract.ts b/src/sdk/base/BaseContract.ts index 801771596..6745ac170 100644 --- a/src/sdk/base/BaseContract.ts +++ b/src/sdk/base/BaseContract.ts @@ -2,31 +2,41 @@ import type { Abi, AbiFunction, Address, - Client, + Chain, ContractEventName, ContractFunctionName, DecodeFunctionDataReturnType, EncodeFunctionDataParameters, + GetAbiItemParameters, GetContractReturnType, Hex, Log, + PublicClient, + Transport, +} from "viem"; +import { + BaseError, + type ContractEventArgs, + decodeFunctionData, + type GetContractEventsReturnType, + getAbiItem, + getAddress, + getContract, + isHex, } from "viem"; -import { decodeFunctionData, getAddress, getContract, isHex } from "viem"; import { errorAbis } from "../../abi/errors.js"; -import { iVersionAbi } from "../../abi/iVersion.js"; -import { ADDRESS_0X0 } from "../constants/index.js"; -import type { GearboxSDK } from "../GearboxSDK.js"; -import type { BaseContractStateHuman, ILogger, RawTx } from "../types/index.js"; +import type { BaseContractStateHuman, RawTx } from "../types/index.js"; import { bytes32ToString, - childLogger, createRawTx, + functionArgsToMap, json_stringify, } from "../utils/index.js"; -import { SDKConstruct } from "./SDKConstruct.js"; +import { Construct, type ConstructOptions } from "./Construct.js"; +import type { IBaseContract, ParsedCall, ParsedCallArgs } from "./types.js"; -export interface BaseContractOptions { +export interface BaseContractArgs { abi: abi; addr: Address; name?: string; @@ -34,82 +44,77 @@ export interface BaseContractOptions { contractType?: string; } -export interface IBaseContract { +export interface ContractParseErrorOptions { address: Address; - contractType: string; - version: number; - name: string; - dirty: boolean; + callData: Hex; + contractName?: string; +} + +export class ContractParseError extends BaseError { + public readonly address: Address; + public readonly callData: Hex; + public readonly selector: Hex; + + constructor(cause: Error, options: ContractParseErrorOptions) { + const { address, callData, contractName } = options; + const selector = callData.slice(0, 10) as Hex; + super( + `failed to parse function data for ${contractName ?? "unknown contract"} at ${address} with selector ${selector}`, + { + cause, + }, + ); + this.callData = callData; + this.selector = selector; + this.address = address; + } } -export abstract class BaseContract - extends SDKConstruct +export class BaseContract + extends Construct implements IBaseContract { public readonly contract: GetContractReturnType< abi, - { public: Client }, + PublicClient, Address >; public readonly abi: abi; - public readonly logger?: ILogger; public readonly contractType: string; - public version: number; + public readonly version: number; + public readonly address: Address; + public readonly name: string; - #name: string; - #address: Address; - - constructor(sdk: GearboxSDK, args: BaseContractOptions) { - super(sdk); + constructor( + { client, logger }: ConstructOptions, + args: BaseContractArgs, + ) { + super({ client, logger }); this.abi = args.abi; - this.#address = getAddress(args.addr); + this.address = getAddress(args.addr); this.contract = getContract({ address: this.address, // add exceptions for better error decoding abi: [...this.abi, ...errorAbis], - client: { - public: sdk.client, - }, + client, }) as any; this.version = Number(args.version || 0); this.contractType = args.contractType ?? ""; if (isHex(this.contractType)) { this.contractType = bytes32ToString(this.contractType); } - this.name = this.#name = args.name || this.contractType || this.#address; - this.logger = childLogger(this.name, sdk.logger); - - // register contract by address: this is used for system-wide call parsing - sdk.contracts.upsert(this.address, this); - } - - public get address(): Address { - return this.#address; - } - - public set address(address: Address) { - if (this.#address !== ADDRESS_0X0) { - throw new Error(`Address can't be changed, currently: ${this.#address}`); - } - this.#address = getAddress(address); - this.sdk.addressLabels.set(address, this.#name); - } + this.name = + args.name || this.contractType || this.address || this.constructor.name; - public get name(): string { - return this.#name; - } - - public set name(name: string) { - this.#name = name; - if (this.#address !== ADDRESS_0X0) { - this.sdk.addressLabels.set(this.#address, name); - } + // register contract by address: this is used for chain-wide call parsing + this.register.setContract(this.address, this); + this.register.setAddressLabel(this.address, this.name); } public stateHuman(_ = true): BaseContractStateHuman { return { - address: this.sdk.labelAddress(this.address), + address: this.labelAddress(this.address), version: this.version, contractType: this.contractType, }; @@ -131,15 +136,74 @@ export abstract class BaseContract >, ): void {} + /** + * Return parsed args and function name from calldata belonging to this contract + * Target of the call is always this contract, but args can be parsed into calls to other contracts (de-facto recursive ParsedCall) + * @param calldata + * @returns + */ + public parseFunctionData(calldata: Hex): ParsedCall { + try { + return this.mustParseFunctionData(calldata); + } catch (e) { + this.logger?.warn(e); + return { + chainId: this.chainId, + target: this.address, + contractType: this.contractType, + label: this.name, + functionName: `Unknown function: ${calldata}`, + args: {}, + }; + } + } + + /** + * Same as {@link parseFunctionData}, but throws {@link ContractParseError} if error occurs + * @param callData + * @returns + */ + public mustParseFunctionData(callData: Hex): ParsedCall { + try { + const decoded = decodeFunctionData({ + abi: this.abi, + data: callData, + }); + return this.wrapParseCall( + decoded.functionName, + this.parseFunctionParams(decoded), + ); + } catch (e) { + throw new ContractParseError(e as Error, { + address: this.address, + callData, + contractName: this.name, + }); + } + } + + /** + * Parses viem-decoded contract function arguments to a map of named arguments + * This default implementation uses abi-based parsing, you can override it, + * but use this super implementation as fallback + * @param params + * @returns + */ + protected parseFunctionParams( + params: DecodeFunctionDataReturnType, + ): ParsedCallArgs { + return functionArgsToMap(this.abi, params.functionName, params.args); + } + /** * Converts contract calldata to some human-friendly string * This is safe function which should not throw * @param calldata * @returns */ - public parseFunctionData(calldata: Hex): string { + public stringifyFunctionData(calldata: Hex): string { try { - return this.mustParseFunctionData(calldata); + return this.mustStringifyFunctionData(calldata); } catch (e) { const selector = calldata.slice(0, 10); this.logger?.warn( @@ -149,71 +213,80 @@ export abstract class BaseContract } } - public mustParseFunctionData(calldata: Hex): string { + /** + * Same as {@link stingifyFunctionData}, but throws if error occurs + * @param calldata + * @returns + */ + public mustStringifyFunctionData(calldata: Hex): string { const decoded = decodeFunctionData({ abi: this.abi, data: calldata, }); - const abiItem = (this.abi as Array).find( - abiItem => - abiItem?.name === decoded.functionName && abiItem?.type === "function", - ); + const abiItem = getAbiItem({ + abi: this.abi, + name: decoded.functionName, + args: decoded.args, + } as GetAbiItemParameters); - if (!abiItem) { + if (!abiItem || abiItem.type !== "function") { return `Unknown function: ${decoded.functionName}`; } - let paramsHuman: Array; - const humanParams = this.parseFunctionParams(decoded); - if (humanParams) { - paramsHuman = humanParams.map((value, i) => { - return `${abiItem.inputs[i].name}: ${value}`; - }); - } else if (Array.isArray(decoded.args)) { - paramsHuman = decoded.args.map((value, i) => { - return `${abiItem.inputs[i].name}: ${abiItem.inputs[i].type === "address" ? this.labelAddress(value) : abiItem.inputs[i].type.startsWith("tuple") ? json_stringify(value) : value}`; - }); - } else { - paramsHuman = Object.entries(decoded.args || {}).map( - ([key, value]) => `${key}: ${value}`, - ); - } + const params = this.stringifyFunctionParams(decoded).map( + (v, i) => `${abiItem.inputs[i].name}: ${v}`, + ); - return `${this.name}.${decoded.functionName}({${paramsHuman.join(", ")}})`; + return `${this.name}.${decoded.functionName}({${params.join(", ")}})`; } /** - * Return args and function name from calldata - * @param calldata + * Pretty-prints values of function arguments (do not include parameter names) + * Can be overriden in classes, but use this super implementation as fallback + * + * @param decoded - Function arguments decoded by viem * @returns */ - public parseFunctionDataToObject(calldata: Hex) { - const decoded = decodeFunctionData({ + protected stringifyFunctionParams( + decoded: DecodeFunctionDataReturnType, + ): string[] { + const abiItem = getAbiItem({ abi: this.abi, - data: calldata, - }); - return decoded; - } - - protected parseFunctionParams( - _params: DecodeFunctionDataReturnType, - ): Array | undefined { - return undefined; + name: decoded.functionName, + args: decoded.args, + } as GetAbiItemParameters) as AbiFunction; + if (Array.isArray(decoded.args)) { + return decoded.args.map((v, i) => { + return abiItem.inputs[i].type === "address" + ? this.labelAddress(v) + : abiItem.inputs[i].type.startsWith("tuple") + ? json_stringify(v) + : `${v}`; + }); + } + return Object.entries(decoded.args || {}).map(v => `${v}`); } - public async getVersion(): Promise { - this.version = Number( - await this.sdk.client.readContract({ - abi: iVersionAbi, - functionName: "version", - address: this.address, - }), - ); - - return this.version; + protected wrapParseCall( + functionName: string, + args: Record, + ): ParsedCall { + return { + chainId: this.chainId, + target: this.address, + contractType: this.contractType, + label: this.register.labelAddress(this.address), + functionName, + args, + }; } + /** + * Creates a raw transaction for a function in this contract + * @param parameters + * @returns + */ public createRawTx< functionName extends ContractFunctionName | undefined = undefined, >( @@ -232,8 +305,90 @@ export abstract class BaseContract argsDescription, ); - tx.description = argsDescription || this.parseFunctionData(tx.callData); // `${this.name}.${parameters.functionName}(${argsDescription || (args && args.length > 0) ? args!.join(", ") : ""})`; + tx.description = argsDescription || this.stringifyFunctionData(tx.callData); return tx; } + + /** + * Get events in safe manner, by bisecting block range if needed + * + * @deprecated TODO: this should be moved to viem transport + * + * @param eventName + * @param fromBlock + * @param toBlock + * @param args + * @param chunkSize + * @returns + */ + public async getEvents>( + eventName: EventName, + fromBlock: bigint, + toBlock: bigint, + args?: + | ContractEventArgs< + abi, + EventName extends ContractEventName + ? EventName + : ContractEventName + > + | undefined, + chunkSize?: number, + ): Promise< + GetContractEventsReturnType + > { + if (chunkSize) { + const chunkSizeBigint = BigInt(chunkSize); + + const getEventPromises = []; + for (let i = fromBlock; i < toBlock; i += chunkSizeBigint) { + getEventPromises.push( + this.client.getContractEvents({ + address: this.address, + fromBlock: i, + toBlock: i + chunkSizeBigint, + abi: this.abi, + eventName, + args, + }), + ); + } + const events = (await Promise.all(getEventPromises)).flat(); + return events; + } + + try { + const events = await this.client.getContractEvents({ + address: this.address, + fromBlock, + toBlock, + abi: this.abi, + eventName, + args, + }); + return events; + } catch (e) { + const blockRangeErrors = [ + "query exceeds max block", + "range is too large", + "eth_getLogs is limited to", + "Unable to perform request", + "Block range limit exceeded", + ]; + + if ( + e instanceof Error && + blockRangeErrors.some(errorText => e.message.includes(errorText)) + ) { + const middle = (fromBlock + toBlock) / 2n; + const [firstHalfEvents, secondHalfEvents] = await Promise.all([ + this.getEvents(eventName, fromBlock, middle, args), + this.getEvents(eventName, middle + 1n, toBlock, args), + ]); + return [...firstHalfEvents, ...secondHalfEvents]; + } + throw e; + } + } } diff --git a/src/sdk/base/ChainContractsRegister.ts b/src/sdk/base/ChainContractsRegister.ts new file mode 100644 index 000000000..2720ec270 --- /dev/null +++ b/src/sdk/base/ChainContractsRegister.ts @@ -0,0 +1,145 @@ +import type { Abi, Address, Chain, Hex, PublicClient, Transport } from "viem"; +import { NOT_DEPLOYED } from "../constants/addresses.js"; +import type { MultiCall } from "../types/index.js"; +import type { ILogger } from "../types/logger.js"; +import { AddressMap } from "../utils/AddressMap.js"; +import type { BaseContract } from "./BaseContract.js"; +import { TokensMeta } from "./TokensMeta.js"; +import type { ParsedCall } from "./types.js"; + +export type ContractOrInterface = T extends Abi | readonly unknown[] + ? BaseContract + : T; + +export class ChainContractsRegister { + static #chains = new Map(); + + public static for( + client: PublicClient, + logger?: ILogger, + ): ChainContractsRegister { + const chainId = client.chain.id; + let result = ChainContractsRegister.#chains.get(chainId); + if (!result) { + result = new ChainContractsRegister(client, logger); + ChainContractsRegister.#chains.set(chainId, result); + } + return result; + } + + private readonly contracts = new AddressMap>( + [], + "contracts", + ); + private readonly labels = new AddressMap([], "labels"); + + public readonly client: PublicClient; + /** + * Token metadata such as symbol and decimals + */ + public readonly tokensMeta: TokensMeta; + public readonly logger?: ILogger; + + constructor(client: PublicClient, logger?: ILogger) { + this.client = client; + this.tokensMeta = new TokensMeta(client); + this.logger = logger; + } + + public getContract( + address: Address, + ): ContractOrInterface | undefined { + return this.contracts.get(address) as ContractOrInterface | undefined; + } + + public mustGetContract( + address: Address, + ): ContractOrInterface { + const contract = this.contracts.mustGet(address); + if (!contract) { + throw new Error(`contract ${address} not found on chain ${this.chainId}`); + } + return contract as ContractOrInterface; + } + + public setContract(address: Address, contract: BaseContract): void { + this.contracts.upsert(address, contract); + } + + public setAddressLabel( + address: Address, + label: string | ((oldLabel?: string) => string), + ): void { + if (address === NOT_DEPLOYED) { + return; + } + if (typeof label === "string") { + this.labels.upsert(address, label); + } else { + this.labels.upsert(address, label(this.labels.get(address))); + } + } + + public labelAddress(address: Address): string { + const label = this.labels.get(address); + return label ? `${address} [${label}]` : address; + } + + public get chain(): Chain { + return this.client.chain; + } + + public get chainId(): number { + return this.client.chain.id; + } + + /** + * Converts contract call into some human-friendly string + * This method is safe and should not throw + * @param address + * @param calldata + * @returns + */ + public stringifyFunctionData(address: Address, calldata: Hex): string { + const contract = this.contracts.get(address); + return contract + ? contract.stringifyFunctionData(calldata) + : `unknown: ${address}.${calldata.slice(0, 10)}`; + } + + /** + * Converts multicalls into some human-friendly strings + * This method is safe and should not throw + * @param address + * @param calldata + * @returns + */ + public stringifyMultiCall(calls: MultiCall[]): string[] { + return calls.map(call => + this.stringifyFunctionData(call.target, call.callData), + ); + } + + /** + * Return args, function, type and address name from contract call + * @param address + * @param calldata + * @returns + */ + public parseFunctionData(address: Address, calldata: Hex): ParsedCall { + const contract = this.mustGetContract(address); + return contract.parseFunctionData(calldata); + } + + /** + * Converts multicalls into call info + * @param address + * @param calldata + * @returns + */ + public parseMultiCall(calls: MultiCall[]): ParsedCall[] { + return calls.map(call => + this.parseFunctionData(call.target, call.callData), + ); + } +} diff --git a/src/sdk/base/Construct.ts b/src/sdk/base/Construct.ts new file mode 100644 index 000000000..9dd3fac0c --- /dev/null +++ b/src/sdk/base/Construct.ts @@ -0,0 +1,80 @@ +import type { Address, Chain, PublicClient, Transport } from "viem"; + +import type { GearboxChain, NetworkType } from "../chain/index.js"; +import type { ILogger } from "../types/index.js"; +import { childLogger } from "../utils/index.js"; +import { ChainContractsRegister } from "./ChainContractsRegister.js"; +import type { TokensMeta } from "./TokensMeta.js"; + +export interface ConstructOptions { + client: PublicClient; + logger?: ILogger; +} + +export class Construct { + public readonly logger?: ILogger; + public readonly client: PublicClient; + public readonly register: ChainContractsRegister; + /** + * Indicates that contract state needs to be updated + */ + #dirty = false; + + constructor({ client, logger }: ConstructOptions) { + this.client = client; + this.register = ChainContractsRegister.for(client, logger); + this.logger = childLogger( + this.constructor.name, + this.register.logger ?? logger, + ); + } + + public get chain(): Chain { + return this.client.chain; + } + + public get chainId(): number { + return this.client.chain.id; + } + + public get networkType(): NetworkType { + if ("network" in this.chain) { + return (this.chain as GearboxChain).network; + } + throw new Error(`chain ${this.chain.id} is not a Gearbox SDK chain`); + } + + /** + * Indicates that contract state diverged from onchain state and needs to be updated + */ + public get dirty(): boolean { + return this.#dirty; + } + + protected set dirty(value: boolean) { + this.#dirty = value; + } + + /** + * Syntax sugar for rgister.tokensMeta + */ + protected get tokensMeta(): TokensMeta { + return this.register.tokensMeta; + } + + /** + * Syntax suggar for getting contract labels + * @param address + * @returns + */ + protected labelAddress(address: Address): string { + return this.register.labelAddress(address); + } + + /** + * Returns list of addresses that should be watched for events to sync state + */ + public get watchAddresses(): Set
{ + return new Set(); + } +} diff --git a/src/sdk/base/IAddressLabeller.ts b/src/sdk/base/IAddressLabeller.ts deleted file mode 100644 index cf5c068b3..000000000 --- a/src/sdk/base/IAddressLabeller.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Address } from "viem"; - -/** - * Helper interface to ease v3.1 refactoring and migration from static methods - */ -export interface IAddressLabeller { - set: ( - address: Address, - label: string | ((oldLabel?: string) => string), - ) => void; - get: (address: Address) => string; - all: Record; -} diff --git a/src/sdk/base/PlaceholderContract.ts b/src/sdk/base/PlaceholderContract.ts index 629396319..cb67b92e0 100644 --- a/src/sdk/base/PlaceholderContract.ts +++ b/src/sdk/base/PlaceholderContract.ts @@ -1,12 +1,12 @@ import type { GearboxSDK } from "../GearboxSDK.js"; -import type { BaseContractOptions } from "./BaseContract.js"; +import type { BaseContractArgs } from "./BaseContract.js"; import { BaseContract } from "./BaseContract.js"; const abi = [] as unknown[]; type abi = typeof abi; export class PlaceholderContract extends BaseContract { - constructor(sdk: GearboxSDK, args: Omit, "abi">) { + constructor(sdk: GearboxSDK, args: Omit, "abi">) { super(sdk, { ...args, abi }); } } diff --git a/src/sdk/base/SDKConstruct.ts b/src/sdk/base/SDKConstruct.ts index b97c328d6..d9b991c6c 100644 --- a/src/sdk/base/SDKConstruct.ts +++ b/src/sdk/base/SDKConstruct.ts @@ -1,47 +1,14 @@ -import type { Address, PublicClient } from "viem"; - -import type { NetworkType } from "../chain/index.js"; import type { GearboxSDK } from "../GearboxSDK.js"; import type { PluginsMap } from "../plugins/index.js"; +import { Construct } from "./Construct.js"; -export class SDKConstruct { +export class SDKConstruct< + const Plugins extends PluginsMap = {}, +> extends Construct { public readonly sdk: GearboxSDK; - /** - * Indicates that contract state needs to be updated - */ - #dirty = false; constructor(sdk: GearboxSDK) { + super(sdk); this.sdk = sdk; } - - public get networkType(): NetworkType { - return this.sdk.networkType; - } - - public get client(): PublicClient { - return this.sdk.client; - } - - /** - * Indicates that contract state needs to be updated - */ - public get dirty(): boolean { - return this.#dirty; - } - - protected set dirty(value: boolean) { - this.#dirty = value; - } - - protected labelAddress(address: Address): string { - return this.sdk.labelAddress(address); - } - - /** - * Returns list of addresses that should be watched for events to sync state - */ - public get watchAddresses(): Set
{ - return new Set(); - } } diff --git a/src/sdk/base/TokensMeta.ts b/src/sdk/base/TokensMeta.ts index 67afb18c3..0ace2ab7b 100644 --- a/src/sdk/base/TokensMeta.ts +++ b/src/sdk/base/TokensMeta.ts @@ -1,6 +1,5 @@ -import type { Address, Hex } from "viem"; +import type { Address, Chain, Hex, PublicClient, Transport } from "viem"; import { iVersionAbi } from "../../abi/iVersion.js"; -import type { GearboxSDK } from "../GearboxSDK.js"; import { bytes32ToString, type PhantomTokenContractType } from "../index.js"; import type { Asset } from "../router/index.js"; import { AddressMap, AddressSet, formatBN } from "../utils/index.js"; @@ -19,12 +18,12 @@ export interface TokenMetaDataExtended extends TokenMetaData { } export class TokensMeta extends AddressMap { - #sdk: GearboxSDK; + #client: PublicClient; #phantomTokensLoaded?: AddressSet; - constructor(sdk: GearboxSDK) { + constructor(client: PublicClient) { super(undefined, "tokensMeta"); - this.#sdk = sdk; + this.#client = client; } public symbol(token: Address): string { @@ -103,7 +102,7 @@ export class TokensMeta extends AddressMap { public async loadPhantomTokens(): Promise { this.#phantomTokensLoaded = new AddressSet(); const tokens = this.keys(); - const resp = await this.#sdk.client.multicall({ + const resp = await this.#client.multicall({ contracts: tokens.map( t => ({ diff --git a/src/sdk/base/index.ts b/src/sdk/base/index.ts index ca403eee3..43f30fd81 100644 --- a/src/sdk/base/index.ts +++ b/src/sdk/base/index.ts @@ -1,5 +1,6 @@ -export * from "./AddressLabeller.js"; export * from "./BaseContract.js"; +export * from "./ChainContractsRegister.js"; +export * from "./Construct.js"; export * from "./PlaceholderContract.js"; export * from "./SDKConstruct.js"; export * from "./TokensMeta.js"; diff --git a/src/sdk/base/types.ts b/src/sdk/base/types.ts index a83721221..99f2ed56c 100644 --- a/src/sdk/base/types.ts +++ b/src/sdk/base/types.ts @@ -86,3 +86,61 @@ export enum VotingContractStatus { ALLOWED = 1, UNVOTE_ONLY = 2, } + +// TODO: make this into recursive type +export type ParsedCallArgs = Record; + +export interface ParsedCall { + chainId: number; + target: Address; + contractType: string; + label: string; + functionName: string; + args: ParsedCallArgs; +} + +export interface IBaseContract { + /** + * Contract address + **/ + readonly address: Address; + /** + * Contract type (parsed bytes32 or empty string) + **/ + readonly contractType: string; + /** + * Contract version + **/ + readonly version: number; + /** + * Internal name, for labeling purposes + * However, other contracts may add more labels, so prefer use labeling methods instead + **/ + readonly name: string; + /** + * Indicates that contract state diverged from onchain state and needs to be updated + */ + dirty: boolean; + + /** + * Return parsed args and function name from calldata belonging to this contract + * Target of the call is always this contract, but args can be parsed into calls to other contracts (de-facto recursive ParsedCall) + **/ + parseFunctionData: (calldata: Hex) => ParsedCall; + + /** + * Same as {@link parseFunctionData}, but throws if error occurs + **/ + mustParseFunctionData: (calldata: Hex) => ParsedCall; + + /** + * Converts contract calldata to some human-friendly string + * This is safe function which should not throw + **/ + stringifyFunctionData: (calldata: Hex) => string; + + /** + * Same as {@link stringifyFunctionData}, but throws if error occurs + **/ + mustStringifyFunctionData: (calldata: Hex) => string; +} diff --git a/src/sdk/core/BotListV3Contract.ts b/src/sdk/core/BotListV3Contract.ts index 73d311edf..dffa022a7 100644 --- a/src/sdk/core/BotListV3Contract.ts +++ b/src/sdk/core/BotListV3Contract.ts @@ -7,6 +7,7 @@ import type { import { iBotListV300Abi } from "../../abi/v300.js"; import { BaseContract } from "../base/index.js"; +import type { GearboxChain } from "../chain/chains.js"; import { botPermissionsToString } from "../constants/index.js"; import type { GearboxSDK } from "../GearboxSDK.js"; import type { BotListStateHuman } from "../types/index.js"; @@ -20,12 +21,12 @@ export class BotListContract extends BaseContract { constructor(sdk: GearboxSDK, address: Address) { super(sdk, { addr: address, name: "BotListV3", abi }); - this.#currentBlock = sdk.chain.firstBlock ?? 0n; + this.#currentBlock = (sdk.chain as GearboxChain).firstBlock ?? 0n; } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "setCreditManagerApprovedStatus": { const [creditManager, status] = params.args; @@ -40,7 +41,7 @@ export class BotListContract extends BaseContract { ]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } diff --git a/src/sdk/core/GearStakingV3Contract.ts b/src/sdk/core/GearStakingV3Contract.ts index 52f85e5b0..23e93d141 100644 --- a/src/sdk/core/GearStakingV3Contract.ts +++ b/src/sdk/core/GearStakingV3Contract.ts @@ -22,16 +22,16 @@ export class GearStakingContract extends BaseContract { super(sdk, { addr: address, name: "GearStakingV3", abi }); } - parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "setVotingContractStatus": { const [address, status] = params.args; return [this.labelAddress(address), VotingContractStatus[status]]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } diff --git a/src/sdk/core/address-provider/AbstractAddressProviderContract.ts b/src/sdk/core/address-provider/AbstractAddressProviderContract.ts index 02bfbca27..5a69a2a30 100644 --- a/src/sdk/core/address-provider/AbstractAddressProviderContract.ts +++ b/src/sdk/core/address-provider/AbstractAddressProviderContract.ts @@ -1,10 +1,9 @@ import { type Abi, type Address, hexToString, isHex, stringToHex } from "viem"; -import type { BaseContractOptions } from "../../base/BaseContract.js"; -import { BaseContract } from "../../base/index.js"; +import type { BaseContractArgs } from "../../base/BaseContract.js"; +import { BaseContract, type ConstructOptions } from "../../base/index.js"; import type { VersionRange } from "../../constants/index.js"; import { NO_VERSION } from "../../constants/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { AddressProviderV3StateHuman } from "../../types/index.js"; import { TypedObjectUtils } from "../../utils/mappers.js"; import type { AddressProviderState } from "./types.js"; @@ -15,11 +14,11 @@ export default abstract class AbstractAddressProviderContract< #addresses: Record> = {}; constructor( - sdk: GearboxSDK, - args: BaseContractOptions, + options: ConstructOptions, + args: BaseContractArgs, addresses: Record> = {}, ) { - super(sdk, args); + super(options, args); this.#addresses = addresses; } diff --git a/src/sdk/core/address-provider/AddressProviderV300Contract.ts b/src/sdk/core/address-provider/AddressProviderV300Contract.ts index 1d66ef2d3..9a769a1b7 100644 --- a/src/sdk/core/address-provider/AddressProviderV300Contract.ts +++ b/src/sdk/core/address-provider/AddressProviderV300Contract.ts @@ -7,7 +7,8 @@ import type { import { bytesToString, getAbiItem, parseEventLogs, toBytes } from "viem"; import { iAddressProviderV300Abi } from "../../../abi/v300.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; +import type { GearboxChain } from "../../chain/index.js"; import { getLogsSafe } from "../../utils/viem/index.js"; import AbstractAddressProviderContract from "./AbstractAddressProviderContract.js"; import type { IAddressProviderContract } from "./types.js"; @@ -20,13 +21,13 @@ export class AddressProviderV300Contract implements IAddressProviderContract { constructor( - sdk: GearboxSDK, + options: ConstructOptions, address: Address, version: number, addresses: Record> = {}, ) { super( - sdk, + options, { addr: address, name: "AddressProviderV300", @@ -37,9 +38,9 @@ export class AddressProviderV300Contract ); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "setAddress": { if (params.args.length !== 3) { @@ -50,7 +51,7 @@ export class AddressProviderV300Contract return [bytesToString(toBytes(key)), value, `${saveVersion}`]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } @@ -88,11 +89,16 @@ export class AddressProviderV300Contract } public async syncState(blockNumber?: bigint): Promise { - const fromBlock = this.sdk.chain.firstBlock; + if (!("firstBlock" in this.chain)) { + throw new Error( + `address provider v300 requires gearbox chain for ${this.chain.id} `, + ); + } + const fromBlock = (this.chain as GearboxChain).firstBlock; this.logger?.debug( `loading events from block ${fromBlock} to ${blockNumber}`, ); - const events = await getLogsSafe(this.sdk.client, { + const events = await getLogsSafe(this.client, { address: this.address, event: getAbiItem({ abi: this.abi, name: "SetAddress" }), fromBlock, diff --git a/src/sdk/core/address-provider/AddressProviderV310Contract.ts b/src/sdk/core/address-provider/AddressProviderV310Contract.ts index 37c4dd6b0..be555b1a1 100644 --- a/src/sdk/core/address-provider/AddressProviderV310Contract.ts +++ b/src/sdk/core/address-provider/AddressProviderV310Contract.ts @@ -7,7 +7,7 @@ import type { import { bytesToString, parseEventLogs, toBytes } from "viem"; import { iAddressProviderV310Abi } from "../../../abi/310/generated.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import AbstractAddressProviderContract from "./AbstractAddressProviderContract.js"; import type { IAddressProviderContract } from "./types.js"; @@ -19,13 +19,13 @@ export class AddressProviderV310Contract implements IAddressProviderContract { constructor( - sdk: GearboxSDK, + options: ConstructOptions, address: Address, - version: number, + version: number = 310, addresses: Record> = {}, ) { super( - sdk, + options, { addr: address, name: "AddressProviderV310", @@ -36,9 +36,9 @@ export class AddressProviderV310Contract ); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "setAddress": { if (params.args.length !== 3) { @@ -49,7 +49,7 @@ export class AddressProviderV310Contract return [bytesToString(toBytes(key)), value, `${saveVersion}`]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } diff --git a/src/sdk/market/MarketConfiguratorContract.ts b/src/sdk/market/MarketConfiguratorContract.ts index 81ac07239..d9f8ead6c 100644 --- a/src/sdk/market/MarketConfiguratorContract.ts +++ b/src/sdk/market/MarketConfiguratorContract.ts @@ -6,10 +6,10 @@ import { } from "viem"; import { iMarketConfiguratorV310Abi } from "../../abi/310/generated.js"; +import type { ConstructOptions } from "../base/Construct.js"; import { BaseContract } from "../base/index.js"; import type { PeripheryContract } from "../constants/index.js"; import { AP_MARKET_CONFIGURATOR } from "../constants/index.js"; -import type { GearboxSDK } from "../GearboxSDK.js"; const abi = iMarketConfiguratorV310Abi; type abi = typeof abi; @@ -17,8 +17,8 @@ type abi = typeof abi; export class MarketConfiguratorContract extends BaseContract { #curatorName?: string; - constructor(sdk: GearboxSDK, address: Address) { - super(sdk, { + constructor(options: ConstructOptions, address: Address) { + super(options, { abi, addr: address, contractType: AP_MARKET_CONFIGURATOR, @@ -27,12 +27,12 @@ export class MarketConfiguratorContract extends BaseContract { } public async loadCuratorName(): Promise { - this.#curatorName = await this.sdk.client.readContract({ + this.#curatorName = await this.client.readContract({ address: this.address, abi: this.abi, functionName: "curatorName", }); - this.sdk.addressLabels.set( + this.register.setAddressLabel( this.address, `Market configurator ${this.#curatorName}`, ); @@ -41,7 +41,7 @@ export class MarketConfiguratorContract extends BaseContract { public async getPeripheryContract( contract: PeripheryContract, ): Promise
{ - const resp = await this.sdk.client.readContract({ + const resp = await this.client.readContract({ address: this.address, abi: this.abi, functionName: "getPeripheryContracts", diff --git a/src/sdk/market/MarketRegister.ts b/src/sdk/market/MarketRegister.ts index 35a9862dc..061a94aa9 100644 --- a/src/sdk/market/MarketRegister.ts +++ b/src/sdk/market/MarketRegister.ts @@ -9,12 +9,8 @@ import { VERSION_RANGE_310, } from "../constants/index.js"; import type { GearboxSDK } from "../GearboxSDK.js"; -import type { - ILogger, - IPriceUpdateTx, - MarketStateHuman, -} from "../types/index.js"; -import { AddressMap, childLogger } from "../utils/index.js"; +import type { IPriceUpdateTx, MarketStateHuman } from "../types/index.js"; +import { AddressMap } from "../utils/index.js"; import { simulateWithPriceUpdates } from "../utils/viem/index.js"; import type { CreditSuite } from "./credit/index.js"; import { MarketConfiguratorContract } from "./MarketConfiguratorContract.js"; @@ -23,7 +19,6 @@ import type { IPriceOracleContract } from "./oracle/index.js"; import type { PoolSuite } from "./pool/index.js"; export class MarketRegister extends SDKConstruct { - #logger?: ILogger; /** * Mapping pool.address -> MarketSuite */ @@ -37,7 +32,6 @@ export class MarketRegister extends SDKConstruct { constructor(sdk: GearboxSDK, ignoreMarkets: Address[] = []) { super(sdk); - this.#logger = childLogger("MarketRegister", sdk.logger); this.#ignoreMarkets = new Set( ignoreMarkets.map(m => m.toLowerCase() as Address), ); @@ -50,7 +44,7 @@ export class MarketRegister extends SDKConstruct { for (const data of state) { const pool = data.pool.baseParams.addr; if (this.#ignoreMarkets.has(pool.toLowerCase() as Address)) { - this.#logger?.debug( + this.logger?.debug( `ignoring market of pool ${pool} (${data.pool.name})`, ); continue; @@ -67,7 +61,7 @@ export class MarketRegister extends SDKConstruct { ignoreUpdateablePrices?: boolean, ): Promise { if (!marketConfigurators.length) { - this.#logger?.warn( + this.logger?.warn( "no market configurators provided, skipping loadMarkets", ); return; @@ -115,7 +109,7 @@ export class MarketRegister extends SDKConstruct { this.marketConfigurators.some(c => c.dirty); if (dirty) { - this.#logger?.debug( + this.logger?.debug( "some markets or market configurators are dirty, reloading everything", ); // this will also update prices @@ -154,7 +148,7 @@ export class MarketRegister extends SDKConstruct { await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(updatables); txs = updates.txs; } - this.#logger?.debug( + this.logger?.debug( { configurators, pools }, `calling getMarkets with ${txs.length} price updates in block ${this.sdk.currentBlock}`, ); @@ -190,7 +184,7 @@ export class MarketRegister extends SDKConstruct { for (const data of markets) { const pool = data.pool.baseParams.addr; if (this.#ignoreMarkets.has(pool.toLowerCase() as Address)) { - this.#logger?.debug( + this.logger?.debug( `ignoring market of pool ${pool} (${data.pool.name})`, ); continue; @@ -198,7 +192,7 @@ export class MarketRegister extends SDKConstruct { this.#markets.upsert(pool, new MarketSuite(this.sdk, data)); } - this.#logger?.info( + this.logger?.info( `loaded ${this.#markets.size} markets in block ${this.sdk.currentBlock}`, ); } @@ -219,7 +213,7 @@ export class MarketRegister extends SDKConstruct { if (!multicalls.length) { return; } - this.#logger?.debug(`syncing prices on ${multicalls.length} oracles`); + this.logger?.debug(`syncing prices on ${multicalls.length} oracles`); const { txs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(); const oraclesStates = await simulateWithPriceUpdates(this.client, { priceUpdates: txs, diff --git a/src/sdk/market/MarketSuite.ts b/src/sdk/market/MarketSuite.ts index 2c5af9246..73c88df5e 100644 --- a/src/sdk/market/MarketSuite.ts +++ b/src/sdk/market/MarketSuite.ts @@ -1,7 +1,7 @@ import type { Address } from "viem"; import type { MarketData } from "../base/index.js"; -import { SDKConstruct } from "../base/index.js"; +import { Construct, SDKConstruct } from "../base/index.js"; import type { GearboxSDK } from "../GearboxSDK.js"; import type { MarketStateHuman } from "../types/index.js"; import { CreditSuite } from "./credit/index.js"; @@ -32,7 +32,7 @@ export class MarketSuite extends SDKConstruct { this.state = marketData; // must be already created in MarketRegister - const mc = sdk.contracts.mustGet(marketData.configurator); + const mc = sdk.mustGetContract(marketData.configurator); if (!(mc instanceof MarketConfiguratorContract)) { throw new Error( `Market configurator ${marketData.configurator} is not a market configurator`, @@ -45,7 +45,7 @@ export class MarketSuite extends SDKConstruct { for (const t of marketData.tokens) { sdk.tokensMeta.upsert(t.addr, t); - sdk.addressLabels.set(t.addr as Address, t.symbol); + sdk.setAddressLabel(t.addr, t.symbol); } this.pool = new PoolSuite(sdk, marketData); diff --git a/src/sdk/market/credit/CreditConfiguratorV300Contract.ts b/src/sdk/market/credit/CreditConfiguratorV300Contract.ts index 3e12e76cb..ee10116ca 100644 --- a/src/sdk/market/credit/CreditConfiguratorV300Contract.ts +++ b/src/sdk/market/credit/CreditConfiguratorV300Contract.ts @@ -1,5 +1,4 @@ import type { - Address, ContractEventName, DecodeFunctionDataReturnType, GetEventArgs, @@ -32,7 +31,7 @@ export class CreditConfiguratorV300Contract extends BaseContract implements ICreditConfiguratorContract { - public readonly adapters: Address[] = []; + public readonly sdk: GearboxSDK; public isPaused = false; constructor( @@ -44,6 +43,7 @@ export class CreditConfiguratorV300Contract name: `CreditConfigurator(${creditManager.name})`, abi, }); + this.sdk = sdk; } public override processLog( @@ -106,9 +106,9 @@ export class CreditConfiguratorV300Contract return logs.map(({ args }) => args); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "addCollateralToken": case "setLiquidationThreshold": { @@ -157,7 +157,7 @@ export class CreditConfiguratorV300Contract } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/sdk/market/credit/CreditConfiguratorV310Contract.ts b/src/sdk/market/credit/CreditConfiguratorV310Contract.ts index b22e5a1c3..f58c71a11 100644 --- a/src/sdk/market/credit/CreditConfiguratorV310Contract.ts +++ b/src/sdk/market/credit/CreditConfiguratorV310Contract.ts @@ -1,5 +1,4 @@ import type { - Address, ContractEventName, DecodeFunctionDataReturnType, Log, @@ -21,7 +20,7 @@ export class CreditConfiguratorV310Contract extends BaseContract implements ICreditConfiguratorContract { - public readonly adapters: Address[] = []; + public readonly sdk: GearboxSDK; public isPaused = false; constructor( @@ -33,6 +32,7 @@ export class CreditConfiguratorV310Contract name: `CreditConfigurator(${creditManager.name})`, abi, }); + this.sdk = sdk; } public override processLog( @@ -83,9 +83,9 @@ export class CreditConfiguratorV310Contract return logs.map(({ args }) => args); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "addCollateralToken": case "setLiquidationThreshold": { @@ -132,7 +132,7 @@ export class CreditConfiguratorV310Contract } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/sdk/market/credit/CreditFacadeV300Contract.ts b/src/sdk/market/credit/CreditFacadeV300Contract.ts index a674867ba..ff7e6a0a8 100644 --- a/src/sdk/market/credit/CreditFacadeV300Contract.ts +++ b/src/sdk/market/credit/CreditFacadeV300Contract.ts @@ -11,10 +11,13 @@ import { iCreditFacadeV300Abi, iCreditFacadeV300MulticallAbi, } from "../../../abi/v300.js"; -import type { CreditFacadeState, CreditSuiteState } from "../../base/index.js"; +import type { + ConstructOptions, + CreditFacadeState, + CreditSuiteState, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; import { ADDRESS_0X0 } from "../../constants/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { CreditFacadeStateHuman, MultiCall, @@ -38,11 +41,11 @@ export class CreditFacadeV300Contract extends BaseContract { public readonly underlying: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, { creditFacade, creditManager }: CreditSuiteState, ) { const { baseParams, ...rest } = creditFacade; - super(sdk, { + super(options, { ...baseParams, name: `CreditFacadeV3(${creditManager.name})`, abi, @@ -52,7 +55,7 @@ export class CreditFacadeV300Contract extends BaseContract { } public override stateHuman(raw?: boolean): CreditFacadeStateHuman { - const decimals = this.sdk.tokensMeta.decimals(this.underlying); + const decimals = this.tokensMeta.decimals(this.underlying); return { ...super.stateHuman(raw), expirable: this.expirable, @@ -141,15 +144,15 @@ export class CreditFacadeV300Contract extends BaseContract { }); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): string[] | undefined { + ): string[] { switch (params.functionName) { case "openCreditAccount": { const [onBehalfOf, calls, referralCode] = params.args; return [ this.labelAddress(onBehalfOf), - this.sdk.parseMultiCall([...calls]).join(","), + this.register.parseMultiCall([...calls]).join(","), `${referralCode}`, ]; } @@ -157,7 +160,7 @@ export class CreditFacadeV300Contract extends BaseContract { const [creditAccount, calls] = params.args; return [ this.labelAddress(creditAccount), - this.sdk.parseMultiCall([...calls]).join(","), + this.register.parseMultiCall([...calls]).join(","), ]; } case "liquidateCreditAccount": { @@ -165,7 +168,7 @@ export class CreditFacadeV300Contract extends BaseContract { return [ this.labelAddress(creditAccount), this.labelAddress(to), - this.sdk.parseMultiCall([...calls]).join(","), + this.register.parseMultiCall([...calls]).join(","), ]; } case "setBotPermissions": { @@ -184,7 +187,7 @@ export class CreditFacadeV300Contract extends BaseContract { return ( this.labelAddress(token) + ": " + - this.sdk.tokensMeta.formatBN(token, amount) + this.tokensMeta.formatBN(token, amount) ); }) .join(","), @@ -192,7 +195,7 @@ export class CreditFacadeV300Contract extends BaseContract { } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/sdk/market/credit/CreditFacadeV310Contract.ts b/src/sdk/market/credit/CreditFacadeV310Contract.ts index 77e8d0e3a..6055f7e36 100644 --- a/src/sdk/market/credit/CreditFacadeV310Contract.ts +++ b/src/sdk/market/credit/CreditFacadeV310Contract.ts @@ -11,10 +11,13 @@ import { iCreditFacadeV310Abi, } from "../../../abi/310/generated.js"; import { iPausableAbi } from "../../../abi/iPausable.js"; -import type { CreditFacadeState, CreditSuiteState } from "../../base/index.js"; +import type { + ConstructOptions, + CreditFacadeState, + CreditSuiteState, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; import { ADDRESS_0X0 } from "../../constants/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { CreditFacadeStateHuman, MultiCall, @@ -38,11 +41,11 @@ export class CreditFacadeV310Contract extends BaseContract { public readonly underlying: Address; constructor( - sdk: GearboxSDK, + options: ConstructOptions, { creditFacade, creditManager }: CreditSuiteState, ) { const { baseParams, ...rest } = creditFacade; - super(sdk, { + super(options, { ...baseParams, name: `CreditFacadeV310(${creditManager.name})`, abi, @@ -52,7 +55,7 @@ export class CreditFacadeV310Contract extends BaseContract { } public override stateHuman(raw?: boolean): CreditFacadeStateHuman { - const decimals = this.sdk.tokensMeta.decimals(this.underlying); + const decimals = this.tokensMeta.decimals(this.underlying); return { ...super.stateHuman(raw), expirable: this.expirable, @@ -138,15 +141,15 @@ export class CreditFacadeV310Contract extends BaseContract { }); } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): string[] | undefined { + ): string[] { switch (params.functionName) { case "openCreditAccount": { const [onBehalfOf, calls, referralCode] = params.args; return [ this.labelAddress(onBehalfOf), - this.sdk.parseMultiCall([...calls]).join(","), + this.register.parseMultiCall([...calls]).join(","), `${referralCode}`, ]; } @@ -154,7 +157,7 @@ export class CreditFacadeV310Contract extends BaseContract { const [creditAccount, calls] = params.args; return [ this.labelAddress(creditAccount), - this.sdk.parseMultiCall([...calls]).join(","), + this.register.parseMultiCall([...calls]).join(","), ]; } case "liquidateCreditAccount": { @@ -162,11 +165,11 @@ export class CreditFacadeV310Contract extends BaseContract { return [ this.labelAddress(creditAccount), this.labelAddress(to), - this.sdk.parseMultiCall([...calls]).join(","), + this.register.parseMultiCall([...calls]).join(","), ]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/sdk/market/credit/CreditManagerV300Contract.ts b/src/sdk/market/credit/CreditManagerV300Contract.ts index e76a6ee86..0232df990 100644 --- a/src/sdk/market/credit/CreditManagerV300Contract.ts +++ b/src/sdk/market/credit/CreditManagerV300Contract.ts @@ -17,7 +17,7 @@ const abi = iCreditManagerV300Abi; export interface CreditManagerV300Contract extends Omit< CreditManagerState, - "baseParams" | "collateralTokens" | "liquidationThresholds" + "baseParams" | "collateralTokens" | "liquidationThresholds" | "name" >, BaseContract {} @@ -51,9 +51,12 @@ export class CreditManagerV300Contract this.adapters = new AddressMap(undefined, "adapters"); for (const adapterData of adapters) { try { - const adapter = createAdapter(this.sdk, adapterData); - adapter.name = `${adapter.name}(${this.name})`; + const adapter = createAdapter(sdk, adapterData); this.adapters.upsert(adapter.targetContract, adapter); + this.register.setAddressLabel( + adapter.address, + `${adapter.name}(${this.name})`, + ); } catch (e) { throw new Error(`cannot attach adapter: ${e}`, { cause: e }); } diff --git a/src/sdk/market/credit/CreditManagerV310Contract.ts b/src/sdk/market/credit/CreditManagerV310Contract.ts index 2c54db430..8b257b578 100644 --- a/src/sdk/market/credit/CreditManagerV310Contract.ts +++ b/src/sdk/market/credit/CreditManagerV310Contract.ts @@ -17,7 +17,7 @@ type abi = typeof iCreditManagerV310Abi; export interface CreditManagerV310Contract extends Omit< CreditManagerState, - "baseParams" | "collateralTokens" | "liquidationThresholds" + "baseParams" | "collateralTokens" | "liquidationThresholds" | "name" >, BaseContract {} @@ -51,9 +51,12 @@ export class CreditManagerV310Contract this.adapters = new AddressMap(undefined, "adapters"); for (const adapterData of adapters) { try { - const adapter = createAdapter(this.sdk, adapterData); - adapter.name = `${adapter.name}(${this.name})`; + const adapter = createAdapter(sdk, adapterData); this.adapters.upsert(adapter.targetContract, adapter); + this.register.setAddressLabel( + adapter.address, + `${adapter.name}(${this.name})`, + ); } catch (e) { throw new Error(`cannot attach adapter: ${e}`, { cause: e }); } diff --git a/src/sdk/market/credit/CreditSuite.ts b/src/sdk/market/credit/CreditSuite.ts index d960ed776..7cddb166b 100644 --- a/src/sdk/market/credit/CreditSuite.ts +++ b/src/sdk/market/credit/CreditSuite.ts @@ -15,7 +15,6 @@ import type { } from "./types.js"; export class CreditSuite extends SDKConstruct { - public readonly name: string; public readonly pool: Address; public readonly underlying: Address; @@ -25,14 +24,14 @@ export class CreditSuite extends SDKConstruct { public readonly marketConfigurator: Address; public readonly state: CreditSuiteState; + public readonly name: string; constructor(sdk: GearboxSDK, marketData: MarketData, index: number) { super(sdk); const { creditManagers, pool } = marketData; - this.state = creditManagers[index]; - const { name } = this.state.creditManager; + this.name = creditManagers[index].creditManager.name; - this.name = name; + this.state = creditManagers[index]; this.pool = pool.baseParams.addr; this.underlying = pool.underlying; diff --git a/src/sdk/market/credit/types.ts b/src/sdk/market/credit/types.ts index 779a6e878..b566eb7c4 100644 --- a/src/sdk/market/credit/types.ts +++ b/src/sdk/market/credit/types.ts @@ -14,7 +14,6 @@ import type { import type { RampEvent } from "./CreditConfiguratorV300Contract.js"; export interface ICreditConfiguratorContract extends IBaseContract { - adapters: Address[]; isPaused: boolean; checkRamps: () => Promise; @@ -23,7 +22,7 @@ export interface ICreditConfiguratorContract extends IBaseContract { export interface ICreditManagerContract extends IBaseContract, - Omit { + Omit { /** * Mapping targetContract => adapter */ diff --git a/src/sdk/market/loss-policy/AliasLossPolicyV310Contract.ts b/src/sdk/market/loss-policy/AliasLossPolicyV310Contract.ts index 8cab61010..4f969accc 100644 --- a/src/sdk/market/loss-policy/AliasLossPolicyV310Contract.ts +++ b/src/sdk/market/loss-policy/AliasLossPolicyV310Contract.ts @@ -30,6 +30,7 @@ export class AliasLossPolicyV310Contract public readonly checksEnabled: boolean; public readonly tokens: readonly Address[]; public readonly priceFeedParams: readonly AliasedPriceFeedParams[]; + public readonly sdk: GearboxSDK; constructor(sdk: GearboxSDK, params: BaseParams) { super(sdk, { @@ -38,6 +39,7 @@ export class AliasLossPolicyV310Contract contractType: params.contractType, version: params.version, }); + this.sdk = sdk; [this.accessMode, this.checksEnabled, this.tokens, this.priceFeedParams] = decodeAbiParameters( [ @@ -63,7 +65,7 @@ export class AliasLossPolicyV310Contract creditAccount: Address, blockNumber?: bigint, ): Promise { - const pfs = await this.sdk.client.readContract({ + const pfs = await this.client.readContract({ address: this.address, abi: this.abi, functionName: "getRequiredAliasPriceFeeds", diff --git a/src/sdk/market/loss-policy/LossPolicyContract.ts b/src/sdk/market/loss-policy/LossPolicyContract.ts index bf8b8ad78..2e3d89635 100644 --- a/src/sdk/market/loss-policy/LossPolicyContract.ts +++ b/src/sdk/market/loss-policy/LossPolicyContract.ts @@ -1,7 +1,10 @@ import type { Address, Hex } from "viem"; import { iLossPolicyV310Abi } from "../../../abi/310/generated.js"; -import { BaseContract, type BaseParams } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { + BaseContract, + type BaseParams, + type ConstructOptions, +} from "../../base/index.js"; import type { ILossPolicyContract } from "./types.js"; const abi = iLossPolicyV310Abi; @@ -11,8 +14,8 @@ export class LossPolicyContract extends BaseContract implements ILossPolicyContract { - constructor(sdk: GearboxSDK, params: BaseParams) { - super(sdk, { + constructor(options: ConstructOptions, params: BaseParams) { + super(options, { abi, addr: params.addr, contractType: params.contractType, diff --git a/src/sdk/market/loss-policy/createLossPolicy.ts b/src/sdk/market/loss-policy/createLossPolicy.ts index 4f06ec5cd..4af6c9f46 100644 --- a/src/sdk/market/loss-policy/createLossPolicy.ts +++ b/src/sdk/market/loss-policy/createLossPolicy.ts @@ -22,9 +22,9 @@ export function createLossPolicy( sdk: GearboxSDK, { baseParams }: BaseState, ): ILossPolicyContract { - const existing = sdk.contracts.get(baseParams.addr); + const existing = sdk.getContract(baseParams.addr); if (existing) { - return existing as unknown as ILossPolicyContract; + return existing; } const contractType = bytes32ToString(baseParams.contractType); diff --git a/src/sdk/market/oracle/PriceOracleBaseContract.ts b/src/sdk/market/oracle/PriceOracleBaseContract.ts index 2bf6c8ceb..ff1bdf942 100644 --- a/src/sdk/market/oracle/PriceOracleBaseContract.ts +++ b/src/sdk/market/oracle/PriceOracleBaseContract.ts @@ -7,7 +7,7 @@ import type { } from "viem"; import { stringToHex } from "viem"; import { priceFeedCompressorAbi } from "../../../abi/compressors/priceFeedCompressor.js"; -import type { BaseContractOptions } from "../../base/BaseContract.js"; +import type { BaseContractArgs } from "../../base/BaseContract.js"; import type { PriceFeedMapEntry, PriceFeedTreeNode, @@ -47,6 +47,7 @@ export abstract class PriceOracleBaseContract< extends BaseContract implements IPriceOracleContract { + public readonly sdk: GearboxSDK; /** * Mapping Token => [PriceFeed Address, stalenessPeriod] */ @@ -80,10 +81,11 @@ export abstract class PriceOracleBaseContract< constructor( sdk: GearboxSDK, - args: BaseContractOptions, + args: BaseContractArgs, data: PriceOracleData, ) { super(sdk, args); + this.sdk = sdk; const { priceFeedMap, priceFeedTree } = data; this.#loadState(priceFeedMap, priceFeedTree, true); } @@ -108,20 +110,6 @@ export abstract class PriceOracleBaseContract< .filter((f): f is IPriceFeedContract => !!f); } - /** - * Generates updates for all updateable price feeds in this oracle (including dependencies) - * @returns - */ - public async updatePriceFeeds(): Promise { - const updatables: IPriceFeedContract[] = []; - for (const node of this.#priceFeedTree.values()) { - if (node.updatable) { - updatables.push(this.sdk.priceFeeds.mustGet(node.baseParams.addr)); - } - } - return this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(updatables); - } - public abstract onDemandPriceUpdates( creditFacade: Address, updates?: UpdatePriceFeedsResult, @@ -174,9 +162,9 @@ export abstract class PriceOracleBaseContract< return amount; } const fromPrice = reserve ? this.reservePrice(from) : this.mainPrice(from); - const fromScale = 10n ** BigInt(this.sdk.tokensMeta.decimals(from)); + const fromScale = 10n ** BigInt(this.tokensMeta.decimals(from)); const toPrice = reserve ? this.reservePrice(to) : this.mainPrice(to); - const toScale = 10n ** BigInt(this.sdk.tokensMeta.decimals(to)); + const toScale = 10n ** BigInt(this.tokensMeta.decimals(to)); return (amount * fromPrice * toScale) / (toPrice * fromScale); } @@ -189,7 +177,7 @@ export abstract class PriceOracleBaseContract< */ public convertToUSD(from: Address, amount: bigint, reserve = false): bigint { const price = reserve ? this.reservePrice(from) : this.mainPrice(from); - const scale = 10n ** BigInt(this.sdk.tokensMeta.decimals(from)); + const scale = 10n ** BigInt(this.tokensMeta.decimals(from)); return (amount * price) / scale; } @@ -201,18 +189,10 @@ export abstract class PriceOracleBaseContract< */ public convertFromUSD(to: Address, amount: bigint, reserve = false): bigint { const price = reserve ? this.reservePrice(to) : this.mainPrice(to); - const scale = 10n ** BigInt(this.sdk.tokensMeta.decimals(to)); + const scale = 10n ** BigInt(this.tokensMeta.decimals(to)); return (amount * scale) / price; } - /** - * Loads new prices for this oracle from PriceFeedCompressor - * Will (re)create price feeds if needed - */ - public async updatePrices(): Promise { - await this.sdk.marketRegister.updatePrices([this.address]); - } - /** * All price feed tree nodes known to this oracle */ @@ -331,8 +311,8 @@ export abstract class PriceOracleBaseContract< usage: PriceFeedUsageType, token: Address, ): void { - this.sdk.addressLabels.set(address, oldLabel => { - const symbol = this.sdk.tokensMeta.symbol(token); + this.sdk.setAddressLabel(address, oldLabel => { + const symbol = this.tokensMeta.symbol(token); let pricefeedTag = `${symbol}.${usage}`; if (oldLabel) { diff --git a/src/sdk/market/oracle/createPriceOracle.ts b/src/sdk/market/oracle/createPriceOracle.ts index d3d4b3d29..24a025367 100644 --- a/src/sdk/market/oracle/createPriceOracle.ts +++ b/src/sdk/market/oracle/createPriceOracle.ts @@ -23,7 +23,7 @@ export function getOrCreatePriceOracle( data: PriceOracleData, ): IPriceOracleContract { const { version, addr } = data.baseParams; - const existing = sdk.contracts.get(addr); + const existing = sdk.getContract(addr); let result: IPriceOracleContract; if (existing) { diff --git a/src/sdk/market/oracle/types.ts b/src/sdk/market/oracle/types.ts index d3750d0e9..087f5989a 100644 --- a/src/sdk/market/oracle/types.ts +++ b/src/sdk/market/oracle/types.ts @@ -69,11 +69,6 @@ export interface IPriceOracleContract extends IBaseContract { */ reservePrice: (token: Address) => bigint; - /** - * Loads new prices for this oracle from PriceFeedCompressor - * Will (re)create price feeds if needed - */ - updatePrices: () => Promise; /** * Paired method to updatePrices, helps to update prices on all oracles in one multicall */ @@ -109,11 +104,6 @@ export interface IPriceOracleContract extends IBaseContract { tokens: Address[], opts?: PriceFeedsForTokensOptions, ) => IPriceFeedContract[]; - /** - * Generates updates for all updateable price feeds in this oracle (including dependencies) - * @returns - */ - updatePriceFeeds: () => Promise; /** * Converts previously obtained price updates into CreditFacade multicall entries * @param creditFacade diff --git a/src/sdk/market/pool/GaugeContract.ts b/src/sdk/market/pool/GaugeContract.ts index 2cb7f9590..ea7dde412 100644 --- a/src/sdk/market/pool/GaugeContract.ts +++ b/src/sdk/market/pool/GaugeContract.ts @@ -2,10 +2,13 @@ import type { ContractEventName, Log } from "viem"; import { decodeAbiParameters } from "viem"; import { iGaugeV300Abi } from "../../../abi/v300.js"; -import type { PoolState, RateKeeperState } from "../../base/index.js"; +import type { + ConstructOptions, + PoolState, + RateKeeperState, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; import { WAD } from "../../constants/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { GaugeStateHuman } from "../../types/index.js"; import { AddressMap, percentFmt } from "../../utils/index.js"; import type { IRateKeeperContract } from "./types.js"; @@ -30,8 +33,12 @@ export class GaugeContract public readonly epochLastUpdate: number; public readonly rates: AddressMap; - constructor(sdk: GearboxSDK, pool: PoolState, gauge: RateKeeperState) { - super(sdk, { + constructor( + options: ConstructOptions, + pool: PoolState, + gauge: RateKeeperState, + ) { + super(options, { ...gauge.baseParams, name: `Gauge(${pool.name})`, abi: iGaugeV300Abi, diff --git a/src/sdk/market/pool/LinearInterestRateModelContract.ts b/src/sdk/market/pool/LinearInterestRateModelContract.ts index 545f6c12d..07ea9c3f4 100644 --- a/src/sdk/market/pool/LinearInterestRateModelContract.ts +++ b/src/sdk/market/pool/LinearInterestRateModelContract.ts @@ -1,9 +1,8 @@ import { decodeAbiParameters } from "viem"; import { iLinearInterestRateModelV300Abi } from "../../../abi/v300.js"; -import type { BaseState } from "../../base/index.js"; +import type { BaseState, ConstructOptions } from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { LinearInterestRateModelStateHuman } from "../../types/index.js"; import { percentFmt } from "../../utils/index.js"; import type { IInterestRateModelContract } from "./types.js"; @@ -23,8 +22,8 @@ export class LinearInterestRateModelContract public readonly Rslope3: number; public readonly isBorrowingMoreU2Forbidden: boolean; - constructor(sdk: GearboxSDK, params: BaseState) { - super(sdk, { + constructor(options: ConstructOptions, params: BaseState) { + super(options, { ...params.baseParams, name: "LinearInterestRateModel", abi, diff --git a/src/sdk/market/pool/PoolQuotaKeeperV300Contract.ts b/src/sdk/market/pool/PoolQuotaKeeperV300Contract.ts index d776bcf8e..def227f54 100644 --- a/src/sdk/market/pool/PoolQuotaKeeperV300Contract.ts +++ b/src/sdk/market/pool/PoolQuotaKeeperV300Contract.ts @@ -2,13 +2,13 @@ import type { ContractEventName, Log } from "viem"; import { iPoolQuotaKeeperV300Abi } from "../../../abi/v300.js"; import type { + ConstructOptions, IBaseContract, PoolState, QuotaKeeperState, QuotaState, } from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { PoolQuotaKeeperStateHuman } from "../../types/index.js"; import { AddressMap, formatBNvalue, percentFmt } from "../../utils/index.js"; @@ -22,8 +22,12 @@ export class PoolQuotaKeeperV300Contract public readonly decimals: number; public readonly quotas: AddressMap; - constructor(sdk: GearboxSDK, pool: PoolState, pqk: QuotaKeeperState) { - super(sdk, { + constructor( + options: ConstructOptions, + pool: PoolState, + pqk: QuotaKeeperState, + ) { + super(options, { ...pqk.baseParams, name: `PoolQuotaKeeper(${pool.name})`, abi, diff --git a/src/sdk/market/pool/PoolQuotaKeeperV310Contract.ts b/src/sdk/market/pool/PoolQuotaKeeperV310Contract.ts index 15fecdd4c..1b4ef9036 100644 --- a/src/sdk/market/pool/PoolQuotaKeeperV310Contract.ts +++ b/src/sdk/market/pool/PoolQuotaKeeperV310Contract.ts @@ -2,13 +2,13 @@ import type { ContractEventName, Log } from "viem"; import { iPoolQuotaKeeperV310Abi } from "../../../abi/310/generated.js"; import type { + ConstructOptions, IBaseContract, PoolState, QuotaKeeperState, QuotaState, } from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { PoolQuotaKeeperStateHuman } from "../../types/index.js"; import { AddressMap, formatBNvalue, percentFmt } from "../../utils/index.js"; @@ -22,8 +22,12 @@ export class PoolQuotaKeeperV310Contract public readonly decimals: number; public readonly quotas: AddressMap; - constructor(sdk: GearboxSDK, pool: PoolState, pqk: QuotaKeeperState) { - super(sdk, { + constructor( + options: ConstructOptions, + pool: PoolState, + pqk: QuotaKeeperState, + ) { + super(options, { ...pqk.baseParams, name: `PoolQuotaKeeper(${pool.name})`, abi, diff --git a/src/sdk/market/pool/PoolSuite.ts b/src/sdk/market/pool/PoolSuite.ts index 9c92472c6..cf45c4982 100644 --- a/src/sdk/market/pool/PoolSuite.ts +++ b/src/sdk/market/pool/PoolSuite.ts @@ -67,9 +67,9 @@ export class PoolSuite extends SDKConstruct { } public get marketConfigurator(): MarketConfiguratorContract { - return this.sdk.contracts.mustGet( + return this.register.mustGetContract( this.#marketConfigurator, - ) as unknown as MarketConfiguratorContract; + ); } public get underlying(): Address { diff --git a/src/sdk/market/pool/PoolV300Contract.ts b/src/sdk/market/pool/PoolV300Contract.ts index 00284f1d6..1199f6141 100644 --- a/src/sdk/market/pool/PoolV300Contract.ts +++ b/src/sdk/market/pool/PoolV300Contract.ts @@ -6,9 +6,12 @@ import type { import { iPausableAbi } from "../../../abi/iPausable.js"; import { iPoolV300Abi } from "../../../abi/v300.js"; -import type { CreditManagerDebtParams, PoolState } from "../../base/index.js"; +import type { + ConstructOptions, + CreditManagerDebtParams, + PoolState, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { PoolStateHuman } from "../../types/index.js"; import { AddressMap, @@ -22,15 +25,15 @@ type abi = typeof abi; // Augmenting contract class with interface of compressor data object export interface PoolV300Contract - extends Omit, + extends Omit, BaseContract {} export class PoolV300Contract extends BaseContract { public readonly creditManagerDebtParams: AddressMap; - constructor(sdk: GearboxSDK, data: PoolState) { + constructor(options: ConstructOptions, data: PoolState) { const { baseParams, creditManagerDebtParams, ...rest } = data; - super(sdk, { + super(options, { ...data.baseParams, name: `PoolV3(${data.name})`, abi, @@ -40,7 +43,7 @@ export class PoolV300Contract extends BaseContract { creditManagerDebtParams.map(p => [p.creditManager, p]), ); // Put diesel token into tokens meta - sdk.tokensMeta.upsert(data.baseParams.addr, { + this.register.tokensMeta.upsert(data.baseParams.addr, { addr: data.baseParams.addr, decimals: data.decimals, name: data.name, @@ -134,16 +137,16 @@ export class PoolV300Contract extends BaseContract { } } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "deposit": { const [amount, onBehalfOf] = params.args; return [formatBN(amount, this.decimals), this.labelAddress(onBehalfOf)]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/sdk/market/pool/PoolV310Contract.ts b/src/sdk/market/pool/PoolV310Contract.ts index 16d514e7a..2d88d0ef1 100644 --- a/src/sdk/market/pool/PoolV310Contract.ts +++ b/src/sdk/market/pool/PoolV310Contract.ts @@ -6,9 +6,12 @@ import type { import { iPoolV310Abi } from "../../../abi/310/generated.js"; import { iPausableAbi } from "../../../abi/iPausable.js"; -import type { CreditManagerDebtParams, PoolState } from "../../base/index.js"; +import type { + ConstructOptions, + CreditManagerDebtParams, + PoolState, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { PoolStateHuman } from "../../types/index.js"; import { AddressMap, @@ -22,15 +25,15 @@ type abi = typeof abi; // Augmenting contract class with interface of compressor data object export interface PoolV310Contract - extends Omit, + extends Omit, BaseContract {} export class PoolV310Contract extends BaseContract { public readonly creditManagerDebtParams: AddressMap; - constructor(sdk: GearboxSDK, data: PoolState) { + constructor(options: ConstructOptions, data: PoolState) { const { baseParams, creditManagerDebtParams, ...rest } = data; - super(sdk, { + super(options, { ...data.baseParams, name: `PoolV3(${data.name})`, abi, @@ -40,7 +43,7 @@ export class PoolV310Contract extends BaseContract { creditManagerDebtParams.map(p => [p.creditManager, p]), ); // Put diesel token into tokens meta - sdk.tokensMeta.upsert(data.baseParams.addr, { + this.register.tokensMeta.upsert(data.baseParams.addr, { addr: data.baseParams.addr, decimals: data.decimals, name: data.name, @@ -134,16 +137,16 @@ export class PoolV310Contract extends BaseContract { } } - protected parseFunctionParams( + protected override stringifyFunctionParams( params: DecodeFunctionDataReturnType, - ): Array | undefined { + ): string[] { switch (params.functionName) { case "deposit": { const [amount, onBehalfOf] = params.args; return [formatBN(amount, this.decimals), this.labelAddress(onBehalfOf)]; } default: - return undefined; + return super.stringifyFunctionParams(params); } } } diff --git a/src/sdk/market/pool/TumblerContract.ts b/src/sdk/market/pool/TumblerContract.ts index a031b30da..521cdb543 100644 --- a/src/sdk/market/pool/TumblerContract.ts +++ b/src/sdk/market/pool/TumblerContract.ts @@ -2,9 +2,12 @@ import type { ContractEventName, Log } from "viem"; import { decodeAbiParameters } from "viem"; import { iTumblerV310Abi } from "../../../abi/310/generated.js"; -import type { PoolState, RateKeeperState } from "../../base/index.js"; +import type { + ConstructOptions, + PoolState, + RateKeeperState, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { TumblerStateHuman } from "../../types/index.js"; import { AddressMap, formatDuration, percentFmt } from "../../utils/index.js"; import type { IRateKeeperContract } from "./types.js"; @@ -19,8 +22,12 @@ export class TumblerContract public readonly epochLength: bigint; public readonly rates: AddressMap; - constructor(sdk: GearboxSDK, pool: PoolState, tumbler: RateKeeperState) { - super(sdk, { + constructor( + options: ConstructOptions, + pool: PoolState, + tumbler: RateKeeperState, + ) { + super(options, { ...tumbler.baseParams, name: `Tumbler(${pool.name})`, abi, diff --git a/src/sdk/market/pool/createInterestRateModel.ts b/src/sdk/market/pool/createInterestRateModel.ts index dc467203f..7b53652bb 100644 --- a/src/sdk/market/pool/createInterestRateModel.ts +++ b/src/sdk/market/pool/createInterestRateModel.ts @@ -12,22 +12,18 @@ export default function createInterestRateModel( data: BaseState, ): IInterestRateModelContract { const { addr, contractType } = data.baseParams; + const existing = sdk.getContract(addr); - if (sdk.interestRateModels.has(addr)) { - return sdk.interestRateModels.mustGet( - addr, - ) as any as IInterestRateModelContract; - } else { - const modelType = bytes32ToString(contractType) as InterestRateModelType; - switch (modelType) { - case "IRM::LINEAR": { - const linearModel = new LinearInterestRateModelContract(sdk, data); - sdk.interestRateModels.insert(addr, linearModel as any); - return linearModel; - } - default: { - throw new Error(`Unknown interest rate model type: ${modelType}`); - } + if (existing) { + return existing; + } + const modelType = bytes32ToString(contractType) as InterestRateModelType; + switch (modelType) { + case "IRM::LINEAR": { + return new LinearInterestRateModelContract(sdk, data); + } + default: { + throw new Error(`Unknown interest rate model type: ${modelType}`); } } } diff --git a/src/sdk/market/pricefeeds/AbstractLPPriceFeed.ts b/src/sdk/market/pricefeeds/AbstractLPPriceFeed.ts index 24d667f40..c3f753848 100644 --- a/src/sdk/market/pricefeeds/AbstractLPPriceFeed.ts +++ b/src/sdk/market/pricefeeds/AbstractLPPriceFeed.ts @@ -1,23 +1,16 @@ import type { Abi, Address, UnionOmit } from "viem"; import { decodeAbiParameters, hexToBytes } from "viem"; -import { ilpPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { isV310 } from "../../constants/versions.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { LPPriceFeedStateHuman } from "../../types/state-human.js"; import { AbstractPriceFeedContract, type PriceFeedConstructorArgs, } from "./AbstractPriceFeed.js"; -import type { ILPPriceFeedContract } from "./types.js"; - -const LOWER_BOUND_FACTOR = 99n; export abstract class AbstractLPPriceFeedContract< - const abi extends Abi | readonly unknown[], - > - extends AbstractPriceFeedContract - implements ILPPriceFeedContract -{ + const abi extends Abi | readonly unknown[], +> extends AbstractPriceFeedContract { public readonly lpContract: Address; public readonly lpToken: Address; public readonly lowerBound: bigint; @@ -27,8 +20,8 @@ export abstract class AbstractLPPriceFeedContract< public readonly aggregatePrice?: bigint; public readonly scale?: bigint; - constructor(sdk: GearboxSDK, args: PriceFeedConstructorArgs) { - super(sdk, { ...args, decimals: 8 }); + constructor(options: ConstructOptions, args: PriceFeedConstructorArgs) { + super(options, { ...args, decimals: 8 }); this.hasLowerBoundCap = true; if (isV310(args.baseParams.version)) { @@ -81,29 +74,6 @@ export abstract class AbstractLPPriceFeedContract< } } - public abstract getValue(): Promise; - - public async getLowerBound(): Promise { - const value = await this.getValue(); - const lowerBound = AbstractLPPriceFeedContract.toLowerBound(value); - this.logger?.debug( - `Lowerbound for ${this.labelAddress(this.address)}: ${lowerBound}`, - ); - return lowerBound; - } - - public async currentLowerBound(): Promise { - return await this.sdk.client.readContract({ - abi: ilpPriceFeedAbi, - address: this.address, - functionName: "lowerBound", - }); - } - - static toLowerBound(value: bigint): bigint { - return (value * LOWER_BOUND_FACTOR) / 100n; - } - public override stateHuman( raw?: boolean, ): UnionOmit { diff --git a/src/sdk/market/pricefeeds/AbstractPriceFeed.ts b/src/sdk/market/pricefeeds/AbstractPriceFeed.ts index 842d28703..2886e54f2 100644 --- a/src/sdk/market/pricefeeds/AbstractPriceFeed.ts +++ b/src/sdk/market/pricefeeds/AbstractPriceFeed.ts @@ -1,8 +1,11 @@ import type { Abi, RequiredBy, UnionOmit } from "viem"; -import type { PriceFeedAnswer, PriceFeedTreeNode } from "../../base/index.js"; +import type { + ConstructOptions, + PriceFeedAnswer, + PriceFeedTreeNode, +} from "../../base/index.js"; import { BaseContract } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { PriceFeedStateHuman } from "../../types/index.js"; import { isUpdatablePriceFeed } from "./isUpdatablePriceFeed.js"; import { PriceFeedRef } from "./PriceFeedRef.js"; @@ -54,8 +57,8 @@ export abstract class AbstractPriceFeedContract< public hasLowerBoundCap = false; public readonly description?: string; - constructor(sdk: GearboxSDK, args: PriceFeedConstructorArgs) { - super(sdk, { + constructor(options: ConstructOptions, args: PriceFeedConstructorArgs) { + super(options, { abi: args.abi, addr: args.baseParams.addr, name: args.name + (args.description ? ` ${args.description}` : ""), @@ -73,7 +76,7 @@ export abstract class AbstractPriceFeedContract< const underlyingStalenessPeriods = args.underlyingStalenessPeriods; this.#underlyingPriceFeeds = args.underlyingFeeds.map( (address, i) => - new PriceFeedRef(this.sdk, address, underlyingStalenessPeriods[i]), + new PriceFeedRef(options, address, underlyingStalenessPeriods[i]), ); } } diff --git a/src/sdk/market/pricefeeds/BalancerStablePriceFeed.ts b/src/sdk/market/pricefeeds/BalancerStablePriceFeed.ts index d730d9f58..d9dcd437f 100644 --- a/src/sdk/market/pricefeeds/BalancerStablePriceFeed.ts +++ b/src/sdk/market/pricefeeds/BalancerStablePriceFeed.ts @@ -1,27 +1,16 @@ -import { - bptStablePriceFeedAbi, - iBalancerStablePoolAbi, -} from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { bptStablePriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof bptStablePriceFeedAbi; export class BalancerStablePriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "BalancerStablePriceFeed", abi: bptStablePriceFeedAbi, }); } - - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iBalancerStablePoolAbi, - address: this.lpContract, - functionName: "getRate", - }); - } } diff --git a/src/sdk/market/pricefeeds/BalancerWeightedPriceFeed.ts b/src/sdk/market/pricefeeds/BalancerWeightedPriceFeed.ts index 592f640e6..e4df3cf52 100644 --- a/src/sdk/market/pricefeeds/BalancerWeightedPriceFeed.ts +++ b/src/sdk/market/pricefeeds/BalancerWeightedPriceFeed.ts @@ -1,11 +1,8 @@ import type { Address, Hex, UnionOmit } from "viem"; import { decodeAbiParameters, hexToBytes } from "viem"; -import { - bptWeightedPriceFeedAbi, - iBalancerWeightedPoolAbi, -} from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { bptWeightedPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { BalancerWeightedPriceFeedStateHuman } from "../../types/state-human.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; @@ -26,7 +23,7 @@ export class BalancerWeightedPriceFeedContract extends AbstractLPPriceFeedContra bigint, ]; - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { // https://github.com/Gearbox-protocol/periphery-v3/blob/8ae4c5f8835de9961c55403fcc810516cea3e29c/contracts/serializers/oracles/BPTWeightedPriceFeedSerializer.sol#L24 // return abi.encode(super.serialize(priceFeed), pf.vault(), pf.poolId(), weights); // https://github.com/Gearbox-protocol/oracles-v3/blob/fc8d3a0ab5bd7eb50ce3f6b87dde5cd3d887bafe/contracts/oracles/balancer/BPTWeightedPriceFeed.sol#L173C9-L173C70 @@ -41,7 +38,7 @@ export class BalancerWeightedPriceFeedContract extends AbstractLPPriceFeedContra hexToBytes(args.baseParams.serializedParams), ); - super(sdk, { + super(options, { ...args, baseParams: { ...args.baseParams, @@ -55,14 +52,6 @@ export class BalancerWeightedPriceFeedContract extends AbstractLPPriceFeedContra this.weights = decoded[3]; } - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iBalancerWeightedPoolAbi, - address: this.lpContract, - functionName: "getRate", - }); - } - public override stateHuman( raw?: boolean, ): UnionOmit { diff --git a/src/sdk/market/pricefeeds/BoundedPriceFeed.ts b/src/sdk/market/pricefeeds/BoundedPriceFeed.ts index cad5cbb49..c24a36cff 100644 --- a/src/sdk/market/pricefeeds/BoundedPriceFeed.ts +++ b/src/sdk/market/pricefeeds/BoundedPriceFeed.ts @@ -1,7 +1,7 @@ import { decodeAbiParameters } from "viem"; import { boundedPriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { BoundedOracleStateHuman } from "../../types/index.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; @@ -11,8 +11,12 @@ type abi = typeof boundedPriceFeedAbi; export class BoundedPriceFeedContract extends AbstractPriceFeedContract { public readonly upperBound: bigint; - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { ...args, name: "BoundedPriceFeed", abi: boundedPriceFeedAbi }); + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { + ...args, + name: "BoundedPriceFeed", + abi: boundedPriceFeedAbi, + }); // https://github.com/Gearbox-protocol/periphery-v3/blob/8ae4c5f8835de9961c55403fcc810516cea3e29c/contracts/serializers/oracles/BoundedPriceFeedSerializer.sol#L13 // abi.encode(pf.upperBound()); // https://github.com/Gearbox-protocol/oracles-v3/blob/fc8d3a0ab5bd7eb50ce3f6b87dde5cd3d887bafe/contracts/oracles/BoundedPriceFeed.sol#L59 diff --git a/src/sdk/market/pricefeeds/CompositePriceFeed.ts b/src/sdk/market/pricefeeds/CompositePriceFeed.ts index fcdf7e878..2ac65321d 100644 --- a/src/sdk/market/pricefeeds/CompositePriceFeed.ts +++ b/src/sdk/market/pricefeeds/CompositePriceFeed.ts @@ -1,5 +1,5 @@ import { compositePriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; import type { PriceFeedRef } from "./PriceFeedRef.js"; @@ -7,8 +7,8 @@ import type { PriceFeedRef } from "./PriceFeedRef.js"; type abi = typeof compositePriceFeedAbi; export class CompositePriceFeedContract extends AbstractPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "CompositePriceFeed", abi: compositePriceFeedAbi, diff --git a/src/sdk/market/pricefeeds/ConstantPriceFeed.ts b/src/sdk/market/pricefeeds/ConstantPriceFeed.ts index bdfc7d169..7fba36bf9 100644 --- a/src/sdk/market/pricefeeds/ConstantPriceFeed.ts +++ b/src/sdk/market/pricefeeds/ConstantPriceFeed.ts @@ -1,6 +1,6 @@ import { decodeAbiParameters } from "viem"; import { constantPriceFeedAbi } from "../../abi/oracles.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { ConstantOracleStateHuman } from "../../types/index.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; @@ -10,8 +10,8 @@ type abi = typeof constantPriceFeedAbi; export class ConstantPriceFeedContract extends AbstractPriceFeedContract { public readonly price: bigint; - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "ConstantPriceFeed", abi: constantPriceFeedAbi, diff --git a/src/sdk/market/pricefeeds/CurveCryptoPriceFeed.ts b/src/sdk/market/pricefeeds/CurveCryptoPriceFeed.ts index ff8e8064f..f032dab14 100644 --- a/src/sdk/market/pricefeeds/CurveCryptoPriceFeed.ts +++ b/src/sdk/market/pricefeeds/CurveCryptoPriceFeed.ts @@ -1,24 +1,16 @@ -import { curveCryptoLpPriceFeedAbi, iCurvePoolAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { curveCryptoLpPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof curveCryptoLpPriceFeedAbi; export class CurveCryptoPriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "CurveCryptoPriceFeed", abi: curveCryptoLpPriceFeedAbi, }); } - - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iCurvePoolAbi, - address: this.lpContract, - functionName: "get_virtual_price", - }); - } } diff --git a/src/sdk/market/pricefeeds/CurveStablePriceFeed.ts b/src/sdk/market/pricefeeds/CurveStablePriceFeed.ts index 5aaae86d9..33811cd85 100644 --- a/src/sdk/market/pricefeeds/CurveStablePriceFeed.ts +++ b/src/sdk/market/pricefeeds/CurveStablePriceFeed.ts @@ -1,24 +1,16 @@ -import { curveStableLpPriceFeedAbi, iCurvePoolAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { curveStableLpPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof curveStableLpPriceFeedAbi; export class CurveStablePriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "CurveStablePriceFeed", abi: curveStableLpPriceFeedAbi, }); } - - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iCurvePoolAbi, - address: this.lpContract, - functionName: "get_virtual_price", - }); - } } diff --git a/src/sdk/market/pricefeeds/CurveUSDPriceFeed.ts b/src/sdk/market/pricefeeds/CurveUSDPriceFeed.ts index b3891d50c..13763da37 100644 --- a/src/sdk/market/pricefeeds/CurveUSDPriceFeed.ts +++ b/src/sdk/market/pricefeeds/CurveUSDPriceFeed.ts @@ -1,24 +1,16 @@ -import { curveUsdPriceFeedAbi, iCurvePoolAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { curveUsdPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof curveUsdPriceFeedAbi; export class CurveUSDPriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "CurveUSDPriceFeed", abi: curveUsdPriceFeedAbi, }); } - - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iCurvePoolAbi, - address: this.lpContract, - functionName: "get_virtual_price", - }); - } } diff --git a/src/sdk/market/pricefeeds/Erc4626PriceFeed.ts b/src/sdk/market/pricefeeds/Erc4626PriceFeed.ts index 6566a97c0..1d66d0f7b 100644 --- a/src/sdk/market/pricefeeds/Erc4626PriceFeed.ts +++ b/src/sdk/market/pricefeeds/Erc4626PriceFeed.ts @@ -1,36 +1,16 @@ -import { erc4626Abi } from "viem"; - -import { ierc20Abi } from "../../../abi/iERC20.js"; import { erc4626PriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof erc4626PriceFeedAbi; export class Erc4626PriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "ERC4626PriceFeed", abi: erc4626PriceFeedAbi, }); } - - public override async getValue(): Promise { - const decimals = await this.sdk.client.readContract({ - abi: ierc20Abi, - address: this.lpContract, - functionName: "decimals", - }); - - const price = await this.sdk.client.readContract({ - abi: erc4626Abi, - address: this.lpContract, - functionName: "convertToAssets", - args: [10n ** BigInt(decimals)], - }); - - return price; - } } diff --git a/src/sdk/market/pricefeeds/ExternalPriceFeed.ts b/src/sdk/market/pricefeeds/ExternalPriceFeed.ts index 9e78f805b..71cf0f543 100644 --- a/src/sdk/market/pricefeeds/ExternalPriceFeed.ts +++ b/src/sdk/market/pricefeeds/ExternalPriceFeed.ts @@ -1,13 +1,13 @@ import { chainlinkReadableAggregatorAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; type abi = typeof chainlinkReadableAggregatorAbi; export class ExternalPriceFeedContract extends AbstractPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "ExternalPriceFeed", abi: chainlinkReadableAggregatorAbi, diff --git a/src/sdk/market/pricefeeds/MellowLRTPriceFeed.ts b/src/sdk/market/pricefeeds/MellowLRTPriceFeed.ts index fd8d16969..f62f0a6fc 100644 --- a/src/sdk/market/pricefeeds/MellowLRTPriceFeed.ts +++ b/src/sdk/market/pricefeeds/MellowLRTPriceFeed.ts @@ -1,26 +1,16 @@ -import { iMellowVaultAbi, mellowLrtPriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { mellowLrtPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof mellowLrtPriceFeedAbi; export class MellowLRTPriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "MellowLRTPriceFeed", abi: mellowLrtPriceFeedAbi, }); } - - public override async getValue(): Promise { - const stack = await this.sdk.client.readContract({ - abi: iMellowVaultAbi, - address: this.lpContract, - functionName: "calculateStack", - }); - - return (stack.totalValue * BigInt(1e18)) / stack.totalSupply; - } } diff --git a/src/sdk/market/pricefeeds/PendleTWAPPTPriceFeed.ts b/src/sdk/market/pricefeeds/PendleTWAPPTPriceFeed.ts index 4f3f17f0c..ae5fa27ff 100644 --- a/src/sdk/market/pricefeeds/PendleTWAPPTPriceFeed.ts +++ b/src/sdk/market/pricefeeds/PendleTWAPPTPriceFeed.ts @@ -2,7 +2,7 @@ import type { Address } from "viem"; import { decodeAbiParameters } from "viem"; import { pendleTWAPPTPriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; @@ -17,8 +17,8 @@ export class PendleTWAPPTPriceFeed extends AbstractPriceFeedContract { public readonly twapWindow: number; public readonly priceToSy: boolean; - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "PendleTWAPPTPriceFeed", abi, diff --git a/src/sdk/market/pricefeeds/PriceFeedRef.ts b/src/sdk/market/pricefeeds/PriceFeedRef.ts index d4ab57e1a..39d8e18ab 100644 --- a/src/sdk/market/pricefeeds/PriceFeedRef.ts +++ b/src/sdk/market/pricefeeds/PriceFeedRef.ts @@ -1,7 +1,6 @@ import type { Address } from "viem"; -import { SDKConstruct } from "../../base/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { Construct, type ConstructOptions } from "../../base/index.js"; import type { PriceFeedStateHuman } from "../../types/index.js"; import { formatDuration } from "../../utils/index.js"; import type { IPriceFeedContract } from "./types.js"; @@ -9,21 +8,27 @@ import type { IPriceFeedContract } from "./types.js"; /** * PriceFeedRef is a connector between price feed and oracle, e.g. oracle's entry for price feed + staleness period */ -export class PriceFeedRef extends SDKConstruct { +export class PriceFeedRef extends Construct { public readonly address: Address; public readonly stalenessPeriod: number; #priceFeed?: IPriceFeedContract; - constructor(sdk: GearboxSDK, address: Address, stalenessPeriod: number) { - super(sdk); + constructor( + options: ConstructOptions, + address: Address, + stalenessPeriod: number, + ) { + super(options); this.address = address; this.stalenessPeriod = stalenessPeriod; } public get priceFeed(): IPriceFeedContract { if (!this.#priceFeed) { - this.#priceFeed = this.sdk.priceFeeds.mustGet(this.address); + this.#priceFeed = this.register.mustGetContract( + this.address, + ); } return this.#priceFeed; } diff --git a/src/sdk/market/pricefeeds/PriceFeedsRegister.ts b/src/sdk/market/pricefeeds/PriceFeedsRegister.ts index 0b92c5230..97c77d276 100644 --- a/src/sdk/market/pricefeeds/PriceFeedsRegister.ts +++ b/src/sdk/market/pricefeeds/PriceFeedsRegister.ts @@ -9,13 +9,8 @@ import { VERSION_RANGE_310, } from "../../constants/index.js"; import type { GearboxSDK } from "../../GearboxSDK.js"; -import type { ILogger, IPriceUpdateTx, RawTx } from "../../types/index.js"; -import { - AddressMap, - bytes32ToString, - childLogger, - createRawTx, -} from "../../utils/index.js"; +import type { IPriceUpdateTx, RawTx } from "../../types/index.js"; +import { AddressMap, bytes32ToString, createRawTx } from "../../utils/index.js"; import type { IHooks } from "../../utils/internal/index.js"; import { Hooks } from "../../utils/internal/index.js"; import { @@ -80,7 +75,6 @@ export class PriceFeedRegister extends SDKConstruct implements IHooks { - public readonly logger?: ILogger; readonly #hooks = new Hooks(); #feeds = new AddressMap(undefined, "priceFeeds"); #latestUpdate: LatestUpdate | undefined; @@ -88,7 +82,6 @@ export class PriceFeedRegister constructor(sdk: GearboxSDK, opts: PriceFeedRegisterOptions = {}) { super(sdk); - this.logger = childLogger("PriceFeedRegister", sdk.logger); this.updaters = [ new RedstoneUpdater(sdk, opts?.redstone), new PythUpdater(sdk, opts?.pyth), diff --git a/src/sdk/market/pricefeeds/PythPriceFeed.ts b/src/sdk/market/pricefeeds/PythPriceFeed.ts index 8a021480b..d43a15939 100644 --- a/src/sdk/market/pricefeeds/PythPriceFeed.ts +++ b/src/sdk/market/pricefeeds/PythPriceFeed.ts @@ -2,7 +2,7 @@ import type { Address, Hex } from "viem"; import { decodeAbiParameters } from "viem"; import { pythPriceFeedAbi } from "../../abi/oracles.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { RawTx } from "../../types/index.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; @@ -20,8 +20,8 @@ export class PythPriceFeed public readonly pyth: Address; public readonly maxConfToPriceRatio?: bigint; - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "PythPriceFeed", abi, diff --git a/src/sdk/market/pricefeeds/RedstonePriceFeed.ts b/src/sdk/market/pricefeeds/RedstonePriceFeed.ts index 0bf78eaba..fd61882d9 100644 --- a/src/sdk/market/pricefeeds/RedstonePriceFeed.ts +++ b/src/sdk/market/pricefeeds/RedstonePriceFeed.ts @@ -2,8 +2,8 @@ import type { Address, Hex } from "viem"; import { bytesToString, decodeAbiParameters, toBytes } from "viem"; import { redstonePriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { ADDRESS_0X0, isV310 } from "../../constants/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; import type { RawTx, RedstonePriceFeedStateHuman } from "../../types/index.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; @@ -23,10 +23,10 @@ export class RedstonePriceFeedContract public readonly lastPrice: bigint; public readonly lastPayloadTimestamp: number; - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, - name: `RedstonePriceFeed`, + name: "RedstonePriceFeed", abi: redstonePriceFeedAbi, }); diff --git a/src/sdk/market/pricefeeds/WstETHPriceFeed.ts b/src/sdk/market/pricefeeds/WstETHPriceFeed.ts index d0991404f..dc581c646 100644 --- a/src/sdk/market/pricefeeds/WstETHPriceFeed.ts +++ b/src/sdk/market/pricefeeds/WstETHPriceFeed.ts @@ -1,24 +1,16 @@ -import { iwstEthAbi, wstEthPriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { wstEthPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof wstEthPriceFeedAbi; export class WstETHPriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "WstETHPriceFeed", abi: wstEthPriceFeedAbi, }); } - - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iwstEthAbi, - address: this.lpContract, - functionName: "stEthPerToken", - }); - } } diff --git a/src/sdk/market/pricefeeds/YearnPriceFeed.ts b/src/sdk/market/pricefeeds/YearnPriceFeed.ts index bd6b5f4b8..3b57df3ce 100644 --- a/src/sdk/market/pricefeeds/YearnPriceFeed.ts +++ b/src/sdk/market/pricefeeds/YearnPriceFeed.ts @@ -1,24 +1,16 @@ -import { iyVaultAbi, yearnPriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import { yearnPriceFeedAbi } from "../../abi/index.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; type abi = typeof yearnPriceFeedAbi; export class YearnPriceFeedContract extends AbstractLPPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "YearnPriceFeed", abi: yearnPriceFeedAbi, }); } - - public override async getValue(): Promise { - return await this.sdk.client.readContract({ - abi: iyVaultAbi, - address: this.lpContract, - functionName: "pricePerShare", - }); - } } diff --git a/src/sdk/market/pricefeeds/ZeroPriceFeed.ts b/src/sdk/market/pricefeeds/ZeroPriceFeed.ts index 4a87afb84..134ac567f 100644 --- a/src/sdk/market/pricefeeds/ZeroPriceFeed.ts +++ b/src/sdk/market/pricefeeds/ZeroPriceFeed.ts @@ -1,13 +1,13 @@ import { zeroPriceFeedAbi } from "../../abi/index.js"; -import type { GearboxSDK } from "../../GearboxSDK.js"; +import type { ConstructOptions } from "../../base/Construct.js"; import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed.js"; import { AbstractPriceFeedContract } from "./AbstractPriceFeed.js"; type abi = typeof zeroPriceFeedAbi; export class ZeroPriceFeedContract extends AbstractPriceFeedContract { - constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) { - super(sdk, { + constructor(options: ConstructOptions, args: PartialPriceFeedTreeNode) { + super(options, { ...args, name: "ZeroPriceFeed", abi: zeroPriceFeedAbi, diff --git a/src/sdk/market/pricefeeds/types.ts b/src/sdk/market/pricefeeds/types.ts index 20b99ebf9..0ceaa54c7 100644 --- a/src/sdk/market/pricefeeds/types.ts +++ b/src/sdk/market/pricefeeds/types.ts @@ -84,12 +84,6 @@ export interface IUpdatablePriceFeedContract extends IPriceFeedContract { createPriceUpdateTx: (data: `0x${string}`) => RawTx; } -export interface ILPPriceFeedContract extends IPriceFeedContract { - getValue: () => Promise; - getLowerBound: () => Promise; - currentLowerBound: () => Promise; -} - export interface UpdatePriceFeedsResult { txs: IPriceUpdateTx[]; timestamp: number; diff --git a/src/sdk/market/pricefeeds/updates/PythUpdater.ts b/src/sdk/market/pricefeeds/updates/PythUpdater.ts index f7c2c2d6a..5af4b10b5 100644 --- a/src/sdk/market/pricefeeds/updates/PythUpdater.ts +++ b/src/sdk/market/pricefeeds/updates/PythUpdater.ts @@ -4,8 +4,7 @@ import { encodeAbiParameters, toHex } from "viem"; import { z } from "zod/v4"; import { SDKConstruct } from "../../../base/index.js"; import type { GearboxSDK } from "../../../GearboxSDK.js"; -import type { ILogger } from "../../../types/index.js"; -import { childLogger, retry } from "../../../utils/index.js"; +import { retry } from "../../../utils/index.js"; import type { IPriceFeedContract, IUpdatablePriceFeedContract, @@ -98,7 +97,6 @@ export class PythUpdater extends SDKConstruct implements IPriceUpdater { - #logger?: ILogger; #cache: PriceUpdatesCache; #historicalTimestamp?: number; #api: string; @@ -106,7 +104,6 @@ export class PythUpdater constructor(sdk: GearboxSDK, opts: PythOptions = {}) { super(sdk); - this.#logger = childLogger("PythUpdater", sdk.logger); this.#ignoreMissingFeeds = opts.ignoreMissingFeeds; this.#api = opts.apiProxy ?? "https://hermes.pyth.network/v2/updates/price/"; @@ -115,7 +112,7 @@ export class PythUpdater const ts = opts.historicTimestamp; if (ts) { this.#historicalTimestamp = ts === true ? Number(this.sdk.timestamp) : ts; - this.#logger?.debug( + this.logger?.debug( `using historical timestamp ${this.#historicalTimestamp}`, ); } @@ -134,7 +131,7 @@ export class PythUpdater if (feeds.length === 0) { return []; } - this.#logger?.debug( + this.logger?.debug( `generating update transactions for ${feeds.length} pyth price feeds`, ); const pythFeeds = new Map( @@ -172,7 +169,7 @@ export class PythUpdater tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`; } } - this.#logger?.debug( + this.logger?.debug( `generated ${results.length} update transactions for pyth price feeds: ${Array.from(pythFeeds.keys()).join(", ")}${tsRange}`, ); return results; @@ -186,7 +183,7 @@ export class PythUpdater async #getPayloads( dataFeedsIds: Set, ): Promise { - this.#logger?.debug( + this.logger?.debug( `getting pyth payloads for ${dataFeedsIds.size} price feeds: ${Array.from(dataFeedsIds).join(", ")}`, ); const fromCache: TimestampedCalldata[] = []; @@ -207,7 +204,7 @@ export class PythUpdater for (const resp of fromPyth) { this.#cache.set(resp, resp.dataFeedId); } - this.#logger?.debug( + this.logger?.debug( `got ${fromPyth.length} new pyth updates and ${fromCache.length} from cache`, ); @@ -229,7 +226,7 @@ export class PythUpdater const tsStr = this.#historicalTimestamp ? ` with historical timestamp ${this.#historicalTimestamp}` : ""; - this.#logger?.debug( + this.logger?.debug( `fetching pyth payloads for ${dataFeedsIds.size} price feeds: ${ids.join(", ")}${tsStr}`, ); // https://hermes.pyth.network/docs/#/rest/latest_price_updates diff --git a/src/sdk/market/pricefeeds/updates/RedstoneUpdater.test.ts b/src/sdk/market/pricefeeds/updates/RedstoneUpdater.test.ts index 191c303bf..06223e45e 100644 --- a/src/sdk/market/pricefeeds/updates/RedstoneUpdater.test.ts +++ b/src/sdk/market/pricefeeds/updates/RedstoneUpdater.test.ts @@ -27,9 +27,9 @@ it("should return an empty array when no updates are available", async () => { // this test requires anvil rpc return; } - const ezETHFeed = sdk.contracts.mustGet( + const ezETHFeed = sdk.mustGetContract( "0xa7cB34Cd731486F61cfDb7ff5F6fC7B40537eD76", - ) as unknown as IPriceFeedContract; + ); const updated = new RedstoneUpdater(sdk, { historicTimestamp: true, ignoreMissingFeeds: true, diff --git a/src/sdk/market/pricefeeds/updates/RedstoneUpdater.ts b/src/sdk/market/pricefeeds/updates/RedstoneUpdater.ts index 7ced77c76..99af2d463 100644 --- a/src/sdk/market/pricefeeds/updates/RedstoneUpdater.ts +++ b/src/sdk/market/pricefeeds/updates/RedstoneUpdater.ts @@ -10,8 +10,7 @@ import { encodeAbiParameters, toBytes } from "viem"; import { z } from "zod/v4"; import { SDKConstruct } from "../../../base/index.js"; import type { GearboxSDK } from "../../../GearboxSDK.js"; -import type { ILogger } from "../../../types/index.js"; -import { AddressMap, childLogger, retry } from "../../../utils/index.js"; +import { AddressMap, retry } from "../../../utils/index.js"; import type { IPriceFeedContract, IUpdatablePriceFeedContract, @@ -79,7 +78,6 @@ export class RedstoneUpdater extends SDKConstruct implements IPriceUpdater { - #logger?: ILogger; #cache: PriceUpdatesCache; #historicalTimestampMs?: number; #gateways?: string[]; @@ -88,7 +86,6 @@ export class RedstoneUpdater constructor(sdk: GearboxSDK, opts: RedstoneOptions = {}) { super(sdk); - this.#logger = childLogger("RedstoneUpdater", sdk.logger); this.#ignoreMissingFeeds = opts.ignoreMissingFeeds; this.#enableLogging = opts.enableLogging; this.#gateways = opts.gateways?.length ? opts.gateways : undefined; @@ -97,7 +94,7 @@ export class RedstoneUpdater if (ts) { ts = ts === true ? Number(this.sdk.timestamp) * 1000 : ts; this.#historicalTimestampMs = 60_000 * Math.floor(ts / 60_000); - this.#logger?.debug( + this.logger?.debug( `using historical timestamp ${this.#historicalTimestampMs}`, ); } @@ -116,7 +113,7 @@ export class RedstoneUpdater if (feeds.length === 0) { return []; } - this.#logger?.debug( + this.logger?.debug( `generating update transactions for ${feeds.length} redstone price feeds`, ); @@ -183,7 +180,7 @@ export class RedstoneUpdater tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`; } } - this.#logger?.debug( + this.logger?.debug( `generated ${results.length} update transactions for redstone price feeds: ${Array.from(priceFeeds.keys()).join(", ")}${tsRange}`, ); return results; @@ -217,7 +214,7 @@ export class RedstoneUpdater // if a feed with stalenessPeriod of 12 hours expired by 10 minutes, it's very unlikely that a retry will succeed // plus it'll be very difficult to drill-down and pass stalenessPeriods to this function if (delta >= 240 && delta < 255) { - this.#logger?.warn( + this.logger?.warn( `payload for ${dataFeedId} has expired by ${delta} seconds`, ); expired = true; @@ -246,7 +243,7 @@ export class RedstoneUpdater dataFeedsIds: Set, uniqueSignersCount: number, ): Promise { - this.#logger?.debug( + this.logger?.debug( `getting redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${Array.from(dataFeedsIds).join(", ")}`, ); const fromCache: TimestampedCalldata[] = []; @@ -273,7 +270,7 @@ export class RedstoneUpdater for (const resp of fromRedstone) { this.#cache.set(resp, dataServiceId, resp.dataFeedId, uniqueSignersCount); } - this.#logger?.debug( + this.logger?.debug( `got ${fromRedstone.length} new redstone updates and ${fromCache.length} from cache`, ); @@ -300,7 +297,7 @@ export class RedstoneUpdater const tsStr = this.#historicalTimestampMs ? ` with historical timestamp ${this.#historicalTimestampMs}` : ""; - this.#logger?.debug( + this.logger?.debug( `fetching redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${dataPackagesIds.join(", ")}${tsStr}`, ); const wrapper = new DataServiceWrapper({ @@ -334,14 +331,14 @@ export class RedstoneUpdater const signedDataPackages = packagesByDataFeedId[dataFeedId]; if (!signedDataPackages) { if (this.#ignoreMissingFeeds) { - this.#logger?.warn(`cannot find data packages for ${dataFeedId}`); + this.logger?.warn(`cannot find data packages for ${dataFeedId}`); continue; } throw new Error(`cannot find data packages for ${dataFeedId}`); } if (signedDataPackages.length !== uniqueSignersCount) { if (this.#ignoreMissingFeeds) { - this.#logger?.warn( + this.logger?.warn( `got ${signedDataPackages.length} data packages for ${dataFeedId}, but expected ${uniqueSignersCount}`, ); continue; diff --git a/src/sdk/plugins/V300StalenessPeriodPlugin.ts b/src/sdk/plugins/V300StalenessPeriodPlugin.ts index 3f4ef7d95..14cd31cc7 100644 --- a/src/sdk/plugins/V300StalenessPeriodPlugin.ts +++ b/src/sdk/plugins/V300StalenessPeriodPlugin.ts @@ -2,6 +2,7 @@ import type { Address } from "viem"; import { getAbiItem, getAddress } from "viem"; import { iPriceOracleV300Abi } from "../../abi/v300.js"; +import type { GearboxChain } from "../chain/chains.js"; import { isV300 } from "../constants/index.js"; import type { GearboxSDK } from "../GearboxSDK.js"; import type { IPriceOracleContract } from "../market/index.js"; @@ -40,7 +41,7 @@ export class V300StalenessPeriodPlugin public override set sdk(sdk: GearboxSDK) { super.sdk = sdk; - this.#syncedTo = (sdk.chain.firstBlock ?? 1n) - 1n; + this.#syncedTo = ((sdk.chain as GearboxChain).firstBlock ?? 1n) - 1n; } public override get sdk(): GearboxSDK { diff --git a/src/sdk/router/AbstractRouterContract.ts b/src/sdk/router/AbstractRouterContract.ts index 462cf0987..2935e372b 100644 --- a/src/sdk/router/AbstractRouterContract.ts +++ b/src/sdk/router/AbstractRouterContract.ts @@ -1,6 +1,7 @@ import type { Abi, Address } from "viem"; -import { BaseContract } from "../base/index.js"; +import { BaseContract, type BaseContractArgs } from "../base/index.js"; +import type { GearboxSDK } from "../GearboxSDK.js"; import { AddressMap, isDust } from "../utils/index.js"; import type { IHooks } from "../utils/internal/index.js"; import { Hooks } from "../utils/internal/index.js"; @@ -28,6 +29,12 @@ export abstract class AbstractRouterContract< public readonly addHook = this.hooks.addHook.bind(this.hooks); public readonly removeHook = this.hooks.removeHook.bind(this.hooks); + public readonly sdk: GearboxSDK; + + constructor(sdk: GearboxSDK, args: BaseContractArgs) { + super(sdk, args); + this.sdk = sdk; + } protected getExpectedAndLeftover( ca: RouterCASlice, diff --git a/src/sdk/router/PathOptionFactory.ts b/src/sdk/router/PathOptionFactory.ts index 3de93d172..134cf0ae6 100644 --- a/src/sdk/router/PathOptionFactory.ts +++ b/src/sdk/router/PathOptionFactory.ts @@ -1,3 +1,4 @@ +/** biome-ignore-all lint/complexity/noStaticOnlyClass: */ import type { Address } from "viem"; import type { NetworkType } from "../chain/index.js"; diff --git a/src/sdk/router/RouterV310Contract.ts b/src/sdk/router/RouterV310Contract.ts index 2906f2ee1..01468afc4 100644 --- a/src/sdk/router/RouterV310Contract.ts +++ b/src/sdk/router/RouterV310Contract.ts @@ -376,7 +376,7 @@ export class RouterV310Contract token: Address, amount: bigint, ): bigint { - const scale = 10n ** BigInt(this.sdk.tokensMeta.get(token)?.decimals ?? 0); + const scale = 10n ** BigInt(this.tokensMeta.get(token)?.decimals ?? 0); const price = oracle.mainPrices.get(token)?.price || oracle.reservePrices.get(token)?.price || @@ -387,11 +387,9 @@ export class RouterV310Contract #debugTokenData(tData: TokenData[]): Record[] { return tData.map(t => ({ token: this.labelAddress(t.token), - balance: `${this.sdk.tokensMeta.formatBN(t.token, t.balance)} (${ - t.balance - })`, + balance: `${this.tokensMeta.formatBN(t.token, t.balance)} (${t.balance})`, leftoverBalance: - this.sdk.tokensMeta.formatBN(t.token, t.leftoverBalance) + + this.tokensMeta.formatBN(t.token, t.leftoverBalance) + ` (${t.leftoverBalance})`, numSplits: t.numSplits, claimRewards: t.claimRewards, diff --git a/src/sdk/router/createRouter.ts b/src/sdk/router/createRouter.ts index 0d39860e7..2fc218685 100644 --- a/src/sdk/router/createRouter.ts +++ b/src/sdk/router/createRouter.ts @@ -11,6 +11,10 @@ export function createRouter( address: Address, version: number, ): IRouterContract { + const contract = sdk.getContract(address); + if (contract) { + return contract; + } if (isV300(version)) { return new RouterV300Contract(sdk, address, version); } diff --git a/src/sdk/router/types.ts b/src/sdk/router/types.ts index 0ed06a4be..55888bc30 100644 --- a/src/sdk/router/types.ts +++ b/src/sdk/router/types.ts @@ -1,7 +1,5 @@ import type { Address } from "viem"; - -import type { IBaseContract } from "../base/BaseContract.js"; -import type { CreditAccountData } from "../base/types.js"; +import type { CreditAccountData, IBaseContract } from "../base/index.js"; import type { MultiCall } from "../types/index.js"; import type { Leftovers } from "./AbstractRouterContract.js"; diff --git a/src/sdk/utils/abi-decode.ts b/src/sdk/utils/abi-decode.ts new file mode 100644 index 000000000..b6b7249ab --- /dev/null +++ b/src/sdk/utils/abi-decode.ts @@ -0,0 +1,58 @@ +import { + type Abi, + AbiFunctionNotFoundError, + type DecodeFunctionDataReturnType, + type GetAbiItemParameters, + getAbiItem, +} from "viem"; +import { json_stringify } from "../../sdk/utils/index.js"; + +/** + * Converts decoded function args (as decoded by viem, i.e. as array) to named map of args + * Can return undefined if function is not found in ABI + * @param abi + * @param functionName + * @param args + * @returns + */ +export function functionArgsToMap( + abi: T, + functionName: string, + args: DecodeFunctionDataReturnType["args"], +): Record { + const abiItem = getAbiItem({ + abi, + name: functionName, + args, + } as GetAbiItemParameters); + + if (!abiItem || abiItem.type !== "function") { + throw new AbiFunctionNotFoundError(functionName); + } + + const namedArgs: Record = {}; + + if (Array.isArray(args)) { + args.forEach((value, i) => { + const input = abiItem.inputs?.[i]; + if (input?.name) { + namedArgs[input.name] = input.type.startsWith("tuple") + ? json_stringify(value) + : String(value); + } + }); + } else { + // Handle object-like args (fallback) + Object.entries(args || {}).forEach(([key, value]) => { + // Try to find the actual parameter name if key is numeric + const index = parseInt(key, 10); + if (!Number.isNaN(index) && abiItem.inputs?.[index]?.name) { + namedArgs[abiItem.inputs[index].name] = String(value); + } else { + namedArgs[key] = String(value); + } + }); + } + + return namedArgs; +} diff --git a/src/sdk/utils/index.ts b/src/sdk/utils/index.ts index e7d6a0b6d..0e75f8f93 100644 --- a/src/sdk/utils/index.ts +++ b/src/sdk/utils/index.ts @@ -1,5 +1,6 @@ export * from "./AddressMap.js"; export * from "./AddressSet.js"; +export * from "./abi-decode.js"; export * from "./bytes32ToString.js"; export * from "./childLogger.js"; export * from "./createRawTx.js";