@superfluid-finance/sdk-core
Version:
SDK Core for building with Superfluid Protocol
311 lines • 14.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const ethers_1 = require("ethers");
const BatchCall_1 = __importDefault(require("./BatchCall"));
const ConstantFlowAgreementV1_1 = __importDefault(require("./ConstantFlowAgreementV1"));
const GeneralDistributionAgreementV1_1 = __importDefault(require("./GeneralDistributionAgreementV1"));
const Governance_1 = __importDefault(require("./Governance"));
const Host_1 = __importDefault(require("./Host"));
const InstantDistributionAgreementV1_1 = __importDefault(require("./InstantDistributionAgreementV1"));
const Operation_1 = __importDefault(require("./Operation"));
const Query_1 = __importDefault(require("./Query"));
const SFError_1 = require("./SFError");
const SuperToken_1 = __importDefault(require("./SuperToken"));
const constants_1 = require("./constants");
const frameworkHelpers_1 = require("./frameworkHelpers");
const typechain_types_1 = require("./typechain-types");
const utils_1 = require("./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_1.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_1.SFError({
type: "CREATE_SIGNER",
message: "You must pass in a provider with your private key.",
});
}
return new ethers_1.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_1.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_1.default({
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_1.default(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_1.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_1.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_1.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_1.default.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_1.ethers.utils.isAddress(tokenAddressOrSymbol);
if (isInputValidAddress) {
return tokenAddressOrSymbol;
}
else {
try {
const superTokenKey = "supertokens." +
this.settings.protocolReleaseVersion +
"." +
tokenAddressOrSymbol;
const resolver = typechain_types_1.Resolver__factory.connect(this.settings.config.resolverAddress, this.settings.provider);
return await resolver.get(superTokenKey);
}
catch (err) {
throw new SFError_1.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_1.default(settings.config.hostAddress, settings.config.cfaV1Address, settings.config.cfaV1ForwarderAddress);
this.governance = new Governance_1.default(settings.config.hostAddress, settings.config.governanceAddress);
this.host = new Host_1.default(settings.config.hostAddress);
this.idaV1 = new InstantDistributionAgreementV1_1.default(settings.config.hostAddress, settings.config.idaV1Address);
this.gdaV1 = new GeneralDistributionAgreementV1_1.default(settings.config.hostAddress, settings.config.gdaV1Address, settings.config.gdaV1ForwarderAddress);
this.query = new Query_1.default(settings);
const resolver = new ethers_1.ethers.Contract(settings.config.resolverAddress, typechain_types_1.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) => {
(0, frameworkHelpers_1.validateFrameworkConstructorOptions)({
...options,
protocolReleaseVersion: options.protocolReleaseVersion || V1,
});
const networkName = (0, frameworkHelpers_1.getNetworkName)(options);
const chainId = options.chainId || constants_1.networkNameToChainIdMap.get(networkName);
const releaseVersion = options.protocolReleaseVersion || V1;
const customSubgraphQueriesEndpoint = options.customSubgraphQueriesEndpoint ||
(0, frameworkHelpers_1.getSubgraphQueriesEndpoint)(options);
const provider = (0, utils_1.isEthersProvider)(options.provider)
? options.provider
: (0, utils_1.isInjectedWeb3)(options.provider)
? // must explicitly cast web3 provider type because
// ethers.providers.Web3Provider doesn't like
// the type passed.
new ethers_1.ethers.providers.Web3Provider(options.provider.currentProvider)
: options.provider.provider;
const network = await provider.getNetwork();
if (network.chainId !== chainId && chainId != null) {
throw new SFError_1.SFError({
type: "NETWORK_MISMATCH",
message: "Your provider network chainId is: " +
network.chainId +
" whereas your desired chainId is: " +
chainId,
});
}
try {
const networkData = constants_1.chainIdToResolverDataMap.get(chainId);
const resolverAddress = options.resolverAddress
? options.resolverAddress
: networkData
? networkData.addresses.resolver
: ethers_1.ethers.constants.AddressZero;
const resolver = typechain_types_1.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 typechain_types_1.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_1.ethers.constants.AddressZero,
gdaV1ForwarderAddress: networkData.addresses.gdaV1Forwarder ||
ethers_1.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 = typechain_types_1.SuperfluidLoader__factory.connect(superfluidLoaderAddress, provider);
const framework = await superfluidLoader.loadFramework(releaseVersion);
const governanceAddress = await typechain_types_1.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_1.SFError({
type: "FRAMEWORK_INITIALIZATION",
message: "There was an error initializing the framework",
cause: err,
});
}
};
exports.default = Framework;
//# sourceMappingURL=Framework.js.map