UNPKG

@sfpro/sdk

Version:

TypeScript SDK for Superfluid Protocol - stream money every second

307 lines (276 loc) 10 kB
import { type Config, defineConfig } from "@wagmi/cli"; import { erc20Abi, type Abi } from "viem"; import { react, actions } from "@wagmi/cli/plugins"; // # Main contracts import CFAv1Forwarder from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/utils/CFAv1Forwarder.sol/CFAv1Forwarder.json" with { type: "json", }; import GDAv1Forwarder from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/utils/GDAv1Forwarder.sol/GDAv1Forwarder.json" with { type: "json", }; import SuperToken from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/superfluid/SuperToken.sol/SuperToken.json" with { type: "json", }; import NativeAssetSuperToken from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/interfaces/tokens/ISETH.sol/ISETHCustom.json" with { type: "json", }; // # Protocol contracts import Host from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/superfluid/Superfluid.sol/Superfluid.json" with { type: "json", }; import ConstantFlowAgreementV1 from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/agreements/ConstantFlowAgreementV1.sol/ConstantFlowAgreementV1.json" with { type: "json", }; import GeneralDistributionAgreementV1 from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/agreements/gdav1/GeneralDistributionAgreementV1.sol/GeneralDistributionAgreementV1.json" with { type: "json", }; import SuperfluidPool from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/agreements/gdav1/SuperfluidPool.sol/SuperfluidPool.json" with { type: "json", }; import InstantDistributionAgreementV1 from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/agreements/InstantDistributionAgreementV1.sol/InstantDistributionAgreementV1.json" with { type: "json", }; import SuperTokenFactory from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/superfluid/SuperTokenFactory.sol/SuperTokenFactory.json" with { type: "json", }; import SuperfluidGovernanceII from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/gov/SuperfluidGovernanceII.sol/SuperfluidGovernanceII.json" with { type: "json", }; import TOGA from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/utils/TOGA.sol/TOGA.json" with { type: "json", }; import BatchLiquidator from "@superfluid-finance/ethereum-contracts/build/hardhat/contracts/utils/BatchLiquidator.sol/BatchLiquidator.json" with { type: "json", }; // --- // # Automation contracts import AutoWrapStrategy from "./abis/AutoWrapStrategy.json" with { type: "json" }; import AutoWrapManager from "./abis/AutoWrapManager.json" with { type: "json" }; import FlowScheduler from "./abis/FlowScheduler.json" with { type: "json" }; import VestingSchedulerV1 from "./abis/VestingScheduler.json" with { type: "json" }; import VestingSchedulerV2 from "./abis/VestingSchedulerV2.json" with { type: "json" }; import VestingSchedulerV3 from "./abis/VestingSchedulerV3.json" with { type: "json" }; // --- import superfluidMetadata from "@superfluid-finance/metadata"; const type = process.env.TYPE?.toLowerCase(); const category = process.env.CATEGORY?.toLowerCase(); // # Superfluid error codes const tokenErrors = uniqErrors((erc20Abi as Abi).concat(SuperToken.abi as Abi).filter((x) => x.type === "error")); const cfaErrors = uniqErrors( (ConstantFlowAgreementV1.abi as Abi).concat(tokenErrors).filter((x) => x.type === "error"), ); const gdaErrors = uniqErrors( (GeneralDistributionAgreementV1.abi as Abi) .concat(SuperfluidPool.abi as Abi) .concat(tokenErrors) .filter((x) => x.type === "error"), ); const allErrors = uniqErrors( tokenErrors .concat(cfaErrors) .concat(gdaErrors) .concat(Host.abi as Abi) .concat(InstantDistributionAgreementV1.abi as Abi) .filter((x) => x.type === "error"), ); // --- // # ABI manipulation // The contracts themselves don't include all the error codes that could happen down the line. // Adding the errors to the ABI will make wagmi/viem display the right error code. const HostWithAllErrors = uniqErrors((Host.abi as Abi).concat(allErrors)); const CfaForwarderWithCfaErrors = uniqErrors((CFAv1Forwarder.abi as Abi).concat(cfaErrors)); const GdaForwarderWithGdaErrors = uniqErrors((GDAv1Forwarder.abi as Abi).concat(gdaErrors)); // Combine Native Asset Super Token with Wrapper Super Token to enable a simpler SDK API. // The Pure Super Token is already included. const SuperTokenCombined = SuperToken.abi.concat(NativeAssetSuperToken.abi); // --- // # CLI config const out = (function (): string { switch (type) { case "abi": return `src/abi${category ? `/${category}` : ""}/generated.ts`; case "hook": return `src/hook${category ? `/${category}` : ""}/generated.ts`; case "action": return `src/action${category ? `/${category}` : ""}/generated.ts`; default: throw new Error(`Invalid type [${type}], use "abi", "hook" or "action".`); } })(); const plugins = (function (): Plugins { switch (type) { case "abi": return []; case "hook": return [ react({ getHookName: ({ contractName, type, itemName }) => { const actionName = getActionName({ contractName, type, itemName }); return `use${capitalizeFirstLetter(actionName)}`; }, }), ]; case "action": return [ actions({ overridePackageName: "@wagmi/core", getActionName: ({ contractName, type, itemName }) => getActionName({ contractName, type, itemName }), }), ]; default: throw new Error(`Invalid type [${type}], use "abi", "hook" or "action".`); } })(); export default defineConfig({ out, plugins, contracts: [ ...(!category ? [ { abi: SuperTokenCombined as Abi, name: "superToken", }, { abi: CfaForwarderWithCfaErrors, name: "cfaForwarder", address: getAddressesFromMetadata((network) => network.contractsV1.cfaV1Forwarder), }, { abi: GdaForwarderWithGdaErrors, name: "gdaForwarder", address: getAddressesFromMetadata((network) => network.contractsV1.gdaV1Forwarder), }, { abi: SuperfluidPool.abi as Abi, name: "gdaPool", }, ] : []), ...(category === "core" ? [ { abi: HostWithAllErrors, name: "host", address: getAddressesFromMetadata((network) => network.contractsV1.host), }, { abi: ConstantFlowAgreementV1.abi as Abi, name: "cfa", address: getAddressesFromMetadata((network) => network.contractsV1.cfaV1), }, { abi: GeneralDistributionAgreementV1.abi as Abi, name: "gda", address: getAddressesFromMetadata((network) => network.contractsV1.gdaV1), }, { abi: InstantDistributionAgreementV1.abi as Abi, name: "ida", address: getAddressesFromMetadata((network) => network.contractsV1.idaV1), }, { abi: SuperTokenFactory.abi as Abi, name: "superTokenFactory", address: getAddressesFromMetadata((network) => network.contractsV1.superTokenFactory), }, { abi: TOGA.abi as Abi, name: "toga", address: getAddressesFromMetadata((network) => network.contractsV1.toga), }, { abi: SuperfluidGovernanceII.abi as Abi, name: "governance", address: getAddressesFromMetadata((network) => network.contractsV1.governance), }, { abi: BatchLiquidator.abi as Abi, name: "batchLiquidator", address: getAddressesFromMetadata((network) => network.contractsV1.superfluidLoader), }, ] : []), ...(category === "automation" ? [ { abi: AutoWrapStrategy as Abi, name: "autoWrapStrategy", address: getAddressesFromMetadata((network) => network.contractsV1.autowrap?.wrapStrategy), }, { abi: AutoWrapManager as Abi, name: "autoWrapManager", address: getAddressesFromMetadata((network) => network.contractsV1.autowrap?.manager), }, { abi: FlowScheduler as Abi, name: "flowScheduler", address: getAddressesFromMetadata((network) => network.contractsV1.flowScheduler), }, { abi: VestingSchedulerV1 as Abi, name: "legacyVestingSchedulerV1", address: getAddressesFromMetadata((network) => network.contractsV1.vestingScheduler), }, { abi: VestingSchedulerV2 as Abi, name: "legacyVestingSchedulerV2", address: getAddressesFromMetadata((network) => network.contractsV1.vestingSchedulerV2), }, { // TODO: Should any errors be added here? abi: VestingSchedulerV3 as Abi, name: "vestingSchedulerV3", address: getAddressesFromMetadata((network) => network.contractsV1.vestingSchedulerV3), }, ] : []), ], }); // --- // # Types type Address = `0x${string}`; type Addressish = Address | string; type NetworkMetadata = (typeof superfluidMetadata.networks)[number]; type Plugins = Config["plugins"]; // --- // # Utils function getAddressesFromMetadata(selector: (network: NetworkMetadata) => Addressish | undefined) { return superfluidMetadata.networks.reduce( (obj, network) => { const address = selector(network); if (address) { obj[network.chainId] = address as Address; } return obj; }, {} as Record<number, Address>, ); } function uniqErrors(abi: Abi): Abi { return abi.filter((item, index, self) => { if (item.type !== "error") { return true; } return index === self.findIndex((e) => e.type === "error" && e.name === item.name); }) as Abi; } function getActionName({ contractName, itemName, type, }: { contractName: string; itemName?: string | undefined; type: "read" | "simulate" | "watch" | "write"; }) { let actionName = `${type}${contractName}${itemName ?? ""}`; if (type === "watch") actionName = `${actionName}Event`; actionName = actionName.replace("CfaCfa", "Cfa").replace("IdaIda", "Ida").replace("GdaGda", "Gda"); return actionName; } function capitalizeFirstLetter(val: string) { return String(val).charAt(0).toUpperCase() + String(val).slice(1); } // ---