UNPKG

@superfluid-finance/sdk-core

Version:
306 lines 14.1 kB
var _a; import { ethers } from "ethers"; import BatchCall from "./BatchCall"; import ConstantFlowAgreementV1 from "./ConstantFlowAgreementV1"; import GeneralDistributionAgreementV1 from "./GeneralDistributionAgreementV1"; import Governance from "./Governance"; import Host from "./Host"; import InstantDistributionAgreementV1 from "./InstantDistributionAgreementV1"; import Operation from "./Operation"; import Query from "./Query"; import { SFError } from "./SFError"; import SuperToken from "./SuperToken"; import { chainIdToResolverDataMap, networkNameToChainIdMap } from "./constants"; import { getNetworkName, getSubgraphQueriesEndpoint, validateFrameworkConstructorOptions, } from "./frameworkHelpers"; import { Resolver__factory, Superfluid__factory, SuperfluidLoader__factory, } from "./typechain-types"; import { isEthersProvider, isInjectedWeb3 } from "./utils"; const V1 = "v1"; /** * Superfluid Framework Class * @description The entrypoint for the SDK-core, `create` an instance of this for full functionality. */ class Framework { constructor(options, settings) { /** * Create a signer which can be used to sign transactions. * @param options.web3Provider a Web3Provider object (e.g. client side - metamask, web3modal) * @param options.provider an ethers Provider object (e.g. via Hardhat ethers) * @param options.privateKey a test account private key * @param options.signer a signer object (e.g. ethers.Wallet instance) * @returns `ethers.Signer` object */ this.createSigner = (options) => { if (!options.privateKey && !options.provider && !options.signer && !options.web3Provider) { throw new SFError({ type: "CREATE_SIGNER", message: "You must pass in a private key, provider or signer.", }); } /* istanbul ignore else */ if (options.privateKey) { if (!options.provider) { throw new SFError({ type: "CREATE_SIGNER", message: "You must pass in a provider with your private key.", }); } return new ethers.Wallet(options.privateKey, options.provider); } else if (options.signer) { return options.signer; } // NOTE: tested by sdk-redux already else if (options.web3Provider) { return options.web3Provider.getSigner(); } /* istanbul ignore next */ throw new SFError({ type: "CREATE_SIGNER", message: "Something went wrong, this should never occur.", }); }; /** * Create a `BatchCall` class from the `Framework`. * @param operations the list of operations to execute * @returns `BatchCall` class */ this.batchCall = (operations) => { return new BatchCall({ operations, hostAddress: this.settings.config.hostAddress, }); }; /** * Create an `Operation` class from the `Framework`. * @param txn the populated transaction to execute * @param type the operation type * @returns `Operation` class */ this.operation = (txn, type) => { return new Operation(txn, type); }; /** * Loads `NativeAssetSuperToken` class from the `Framework`. Will throw if token is not NativeAssetSuperToken. * @param tokenAddressOrSymbol * @returns `NativeAssetSuperToken` class */ this.loadNativeAssetSuperToken = async (tokenAddressOrSymbol) => { const superToken = await this.loadSuperToken(tokenAddressOrSymbol); // The NativeAssetSuperToken class should have the nativeTokenSymbol property const isNativeAssetSuperToken = !!superToken.nativeTokenSymbol; if (!isNativeAssetSuperToken) { throw new SFError({ type: "SUPERTOKEN_INITIALIZATION", message: "The token is not a native asset supertoken.", }); } return superToken; }; /** * Loads `PureSuperToken` class from the `Framework`. Will throw if token is not PureSuperToken. * @param tokenAddressOrSymbol * @returns `PureSuperToken` class */ this.loadPureSuperToken = async (tokenAddressOrSymbol) => { const superToken = await this.loadSuperToken(tokenAddressOrSymbol); // The PureSuperToken class should not have the downgrade (and upgrade) function // we can just check if downgrade doesn't exist const isPureSuperToken = !!superToken.downgrade === false; if (!isPureSuperToken) { throw new SFError({ type: "SUPERTOKEN_INITIALIZATION", message: "The token is not a pure supertoken.", }); } return superToken; }; /** * Loads `WrapperSuperToken` class from the `Framework`. Will throw if token is not WrapperSuperToken. * @param tokenAddressOrSymbol * @returns `WrapperSuperToken` class */ this.loadWrapperSuperToken = async (tokenAddressOrSymbol) => { const superToken = await this.loadSuperToken(tokenAddressOrSymbol); // The WrapperSuperToken class should have the underlyingToken property const isWrapperSuperToken = !!superToken.underlyingToken; if (!isWrapperSuperToken) { throw new SFError({ type: "SUPERTOKEN_INITIALIZATION", message: "The token is not a wrapper supertoken.", }); } return superToken; }; /** * Loads `SuperToken` class from the `Framework`. Use this when you're unsure of the token type. * @param tokenAddressOrSymbol the `SuperToken` address or symbol (if symbol, it must be on the resolver) * @returns `SuperToken` class */ this.loadSuperToken = async (tokenAddressOrSymbol) => { const address = await this._tryGetTokenAddress(tokenAddressOrSymbol); return await SuperToken.create({ ...this.settings, address, }); }; /** * Try to get the token address given an address (returns if valid) or the token symbol via the resolver. * @param tokenAddressOrSymbol * @returns token address */ this._tryGetTokenAddress = async (tokenAddressOrSymbol) => { const isInputValidAddress = ethers.utils.isAddress(tokenAddressOrSymbol); if (isInputValidAddress) { return tokenAddressOrSymbol; } else { try { const superTokenKey = "supertokens." + this.settings.protocolReleaseVersion + "." + tokenAddressOrSymbol; const resolver = Resolver__factory.connect(this.settings.config.resolverAddress, this.settings.provider); return await resolver.get(superTokenKey); } catch (err) { throw new SFError({ type: "SUPERTOKEN_INITIALIZATION", message: "There was an error with loading the SuperToken with symbol: " + tokenAddressOrSymbol + " with the resolver.", cause: err, }); } } }; this.userInputOptions = options; this.settings = settings; this.cfaV1 = new ConstantFlowAgreementV1(settings.config.hostAddress, settings.config.cfaV1Address, settings.config.cfaV1ForwarderAddress); this.governance = new Governance(settings.config.hostAddress, settings.config.governanceAddress); this.host = new Host(settings.config.hostAddress); this.idaV1 = new InstantDistributionAgreementV1(settings.config.hostAddress, settings.config.idaV1Address); this.gdaV1 = new GeneralDistributionAgreementV1(settings.config.hostAddress, settings.config.gdaV1Address, settings.config.gdaV1ForwarderAddress); this.query = new Query(settings); const resolver = new ethers.Contract(settings.config.resolverAddress, Resolver__factory.abi); this.contracts = { cfaV1: this.cfaV1.contract, governance: this.governance.contract, host: this.host.contract, idaV1: this.idaV1.contract, gdaV1: this.gdaV1.contract, resolver, }; } } _a = Framework; /** * Creates the Framework object based on user provided `options`. * @param options.chainId the chainId of your desired network (e.g. 137 = matic) * @param options.customSubgraphQueriesEndpoint your custom subgraph endpoint * @param options.resolverAddress a custom resolver address (advanced use for testing) * @param options.protocolReleaseVersion a custom release version (advanced use for testing) * @param options.provider a provider object (injected web3, injected ethers, ethers provider) necessary for initializing the framework * @returns `Framework` class */ Framework.create = async (options) => { validateFrameworkConstructorOptions({ ...options, protocolReleaseVersion: options.protocolReleaseVersion || V1, }); const networkName = getNetworkName(options); const chainId = options.chainId || networkNameToChainIdMap.get(networkName); const releaseVersion = options.protocolReleaseVersion || V1; const customSubgraphQueriesEndpoint = options.customSubgraphQueriesEndpoint || getSubgraphQueriesEndpoint(options); const provider = isEthersProvider(options.provider) ? options.provider : isInjectedWeb3(options.provider) ? // must explicitly cast web3 provider type because // ethers.providers.Web3Provider doesn't like // the type passed. new ethers.providers.Web3Provider(options.provider.currentProvider) : options.provider.provider; const network = await provider.getNetwork(); if (network.chainId !== chainId && chainId != null) { throw new SFError({ type: "NETWORK_MISMATCH", message: "Your provider network chainId is: " + network.chainId + " whereas your desired chainId is: " + chainId, }); } try { const networkData = chainIdToResolverDataMap.get(chainId); const resolverAddress = options.resolverAddress ? options.resolverAddress : networkData ? networkData.addresses.resolver : ethers.constants.AddressZero; const resolver = Resolver__factory.connect(resolverAddress, provider); const baseSettings = { chainId, customSubgraphQueriesEndpoint, protocolReleaseVersion: options.protocolReleaseVersion || V1, provider, networkName, }; // supported networks scenario if (networkData && baseSettings.protocolReleaseVersion === V1) { const governanceAddress = networkData.addresses.governance ? networkData.addresses.governance : await Superfluid__factory.connect(networkData.addresses.host, provider).getGovernance(); const settings = { ...baseSettings, config: { resolverAddress, hostAddress: networkData.addresses.host, cfaV1Address: networkData.addresses.cfaV1, idaV1Address: networkData.addresses.idaV1, gdaV1Address: networkData.addresses.gdaV1 || ethers.constants.AddressZero, gdaV1ForwarderAddress: networkData.addresses.gdaV1Forwarder || ethers.constants.AddressZero, governanceAddress, cfaV1ForwarderAddress: networkData.addresses.cfaV1Forwarder, }, }; return new _a(options, settings); } else { // unsupported networks scenario (e.g. local testing) const superfluidLoaderAddress = await resolver.get("SuperfluidLoader-v1"); const cfaV1ForwarderAddress = await resolver.get("CFAv1Forwarder"); const gdaV1ForwarderAddress = await resolver.get("GDAv1Forwarder"); const superfluidLoader = SuperfluidLoader__factory.connect(superfluidLoaderAddress, provider); const framework = await superfluidLoader.loadFramework(releaseVersion); const governanceAddress = await Superfluid__factory.connect(framework.superfluid, provider).getGovernance(); const settings = { ...baseSettings, config: { resolverAddress, hostAddress: framework.superfluid, cfaV1Address: framework.agreementCFAv1, idaV1Address: framework.agreementIDAv1, gdaV1Address: framework.agreementGDAv1, governanceAddress, cfaV1ForwarderAddress, gdaV1ForwarderAddress, }, }; return new _a(options, settings); } } catch (err) { throw new SFError({ type: "FRAMEWORK_INITIALIZATION", message: "There was an error initializing the framework", cause: err, }); } }; export default Framework; //# sourceMappingURL=Framework.js.map