@allo-team/allo-v2-sdk
Version:
611 lines (476 loc) • 14.1 kB
text/typescript
import {
Chain,
PublicClient,
Transport,
encodeAbiParameters,
encodeFunctionData,
extractChain,
getContract,
parseAbiParameters,
} from "viem";
import { Allo } from "../../Allo/Allo";
import {
ConstructorArgs,
DeployParams,
Metadata,
PayoutSummary,
Recipient,
Status,
TransactionData,
} from "../../types";
import { supportedChains } from "../../chains.config";
import { create } from "../../Client/Client";
import {
abi as superfluidAbi,
bytecode as superfluidBytecode,
} from "./superfluid.config";
import {
AllocationSuperlfuid,
InitializeParamsSuperFluid,
RegisterDataSuperfluid,
ReviewRecipientDataSuperfluid,
} from "./types";
import { abi as alloAbi } from "../../Allo/allo.config";
export class SQFSuperFluidStrategy {
private client: PublicClient<Transport, Chain>;
private contract: any;
private strategy: `0x${string}` | undefined;
private poolId: bigint;
private allo: Allo;
constructor({ chain, rpc, address, poolId }: ConstructorArgs) {
const usedChain = extractChain({
chains: supportedChains,
id: chain as any,
});
this.client = create(usedChain, rpc);
this.allo = new Allo({ chain, rpc });
if (address) {
this.contract = getContract({
address: address,
abi: superfluidAbi,
client: {
public: this.client,
}
});
this.strategy = address;
}
this.poolId = poolId || BigInt(-1);
}
public async setPoolId(poolId: bigint): Promise<void> {
this.poolId = poolId;
const strategyAddress = await this.allo.getStrategy(poolId);
this.setContract(strategyAddress as `0x${string}`);
}
public setContract(address: `0x${string}`): void {
this.contract = getContract({
address: address,
abi: superfluidAbi,
client: {
public: this.client,
}
});
this.strategy = address;
}
private checkPoolId(): void {
if (this.poolId === BigInt(-1))
throw new Error(
"SQFSuperfluidStrategy: No poolId provided. Please call `setPoolId` first.",
);
}
private checkStrategy(): void {
if (!this.strategy)
throw new Error(
"SQFSuperfluidStrategy: No strategy address provided. Please call `setContract` first.",
);
}
// Init and Deploy
public async getInitializeData(
params: InitializeParamsSuperFluid,
): Promise<`0x${string}`> {
const encoded: `0x${string}` = encodeAbiParameters(
parseAbiParameters(
"bool, bool, address, address, address, uint64, uint64, uint64, uint64, uint256, uint256",
),
[
params.useRegistryAnchor,
params.metadataRequired,
params.passportDecoder,
params.superfluidHost,
params.allocationSuperToken,
params.registrationStartTime,
params.registrationEndTime,
params.allocationStartTime,
params.allocationEndTime,
params.minPassportScore,
params.initialSuperAppBalance,
],
);
return encoded;
}
public getDeployParams(): DeployParams {
const constructorArgs: `0x${string}` = encodeAbiParameters(
parseAbiParameters("address, string"),
[this.allo.address(), "SQFSuperfluidv1"],
);
const constructorArgsNo0x = constructorArgs.slice(2);
// create the proper bytecode
const bytecode = superfluidBytecode;
const abi = superfluidAbi;
return {
abi: abi,
bytecode: (bytecode + constructorArgsNo0x) as unknown as `0x${string}`,
};
}
// Getters
public async getNative(): Promise<string> {
this.checkStrategy();
const native = await this.contract.read.NATIVE();
return native;
}
public async getAllocationEndTime(): Promise<bigint> {
this.checkStrategy();
const endTime = await this.contract.read.allocationEndTime();
return endTime;
}
public async getAllocationStartTime(): Promise<bigint> {
this.checkStrategy();
const startTime = await this.contract.read.allocationStartTime();
return startTime;
}
public async getRegistrationEndTime(): Promise<bigint> {
this.checkStrategy();
const endTime = await this.contract.read.registrationEndTime();
return endTime;
}
public async getRegistrationStartTime(): Promise<bigint> {
this.checkStrategy();
const startTime = await this.contract.read.registrationStartTime();
return startTime;
}
public async getAllo(): Promise<Allo> {
return this.allo;
}
public async getPayouts(recipientIds: string[]): Promise<PayoutSummary[]> {
this.checkStrategy();
const emptyData = Array(recipientIds.length).fill("0x");
const payouts = await this.contract.read.getPayouts([
recipientIds,
emptyData,
]);
const payoutSummary: PayoutSummary[] = payouts.map((payout: any) => {
this.checkStrategy();
return {
address: payout.recipientAddress,
amount: payout.amount,
};
});
return payoutSummary;
}
public async getPoolAmount(): Promise<bigint> {
this.checkStrategy();
const amount = await this.contract.read.getPoolAmount();
return amount;
}
public async getPoolId(): Promise<bigint> {
this.checkStrategy();
const poolId = await this.contract.read.getPoolId();
return poolId;
}
public async getRecipient(recipientId: string): Promise<Recipient> {
this.checkStrategy();
const recipient = await this.contract.read.getRecipient([recipientId]);
return recipient;
}
public async getRecipientStatus(recipientId: string): Promise<Status> {
this.checkStrategy();
const status = await this.contract.read.getRecipientStatus([recipientId]);
return status;
}
public async getStrategyId(): Promise<string> {
this.checkStrategy();
const id = await this.contract.read.getStrategyId();
return id;
}
public async isPoolActive(): Promise<boolean> {
this.checkStrategy();
const active = await this.contract.read.isPoolActive();
return active;
}
public async isValidAllocator(allocatorAddress: string): Promise<boolean> {
this.checkStrategy();
const valid = await this.contract.read.isValidAllocator([allocatorAddress]);
return valid;
}
public async useRegistryAnchor(): Promise<boolean> {
this.checkStrategy();
const useRegistryAnchor = await this.contract.read.useRegistryAnchor();
return useRegistryAnchor;
}
public getInitialSuperAppBalance(): Promise<bigint> {
this.checkStrategy();
return this.contract.read.initialSuperAppBalance();
}
public getSuperfluidHost(): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.superfluidHost();
}
public getAllocationSuperToken(): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.allocationSuperToken();
}
public getPoolSuperToken(): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.poolSuperToken();
}
public getGdaPool(): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.gdaPool();
}
public getPassportDecoder(): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.passportDecoder();
}
public getMinPassportScore(): Promise<bigint> {
this.checkStrategy();
return this.contract.read.minPassportScore();
}
public getMetadataRequired(): Promise<boolean> {
this.checkStrategy();
return this.contract.read.metadataRequired();
}
public getRegistry(): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.registry();
}
public getRecipientIdBySuperApp(
superApp: `0x${string}`,
): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.superApps([superApp]);
}
public getTotalUnitsByRecipient(recipientId: `0x${string}`): Promise<bigint> {
this.checkStrategy();
return this.contract.read.totalUnitsByRecipient([recipientId]);
}
public getRecipientFlowRate(recipientId: `0x${string}`): Promise<bigint> {
this.checkStrategy();
return this.contract.read.recipientFlowRate([recipientId]);
}
public getSuperApp(recipientId: `0x${string}`): Promise<`0x${string}`> {
this.checkStrategy();
return this.contract.read.getSuperApp([recipientId]);
}
// Write functions
public getUpdatePoolTimestampsData(
registrationStartTime: bigint,
registrationEndTime: bigint,
allocationStartTime: bigint,
allocationEndTime: bigint,
): TransactionData {
this.checkStrategy();
const encodedData = encodeFunctionData({
abi: superfluidAbi,
functionName: "updatePoolTimestamps",
args: [
registrationStartTime,
registrationEndTime,
allocationStartTime,
allocationEndTime,
],
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
public getUpdateMinPassportScoreData(
minPassportScore: bigint,
): TransactionData {
this.checkStrategy();
const encodedData = encodeFunctionData({
abi: superfluidAbi,
functionName: "updateMinPassportScore",
args: [minPassportScore],
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
public getRegisterRecipientData(data: {
registryAnchor: `0x${string}`;
recipientAddress: `0x${string}`;
metadata: Metadata;
}): TransactionData {
this.checkPoolId();
const encoded: `0x${string}` = encodeAbiParameters(
parseAbiParameters("address, address, (uint256, string)"),
[
data.registryAnchor,
data.recipientAddress,
[data.metadata.protocol, data.metadata.pointer],
],
);
const encodedData = encodeFunctionData({
abi: alloAbi,
functionName: "registerRecipient",
args: [this.poolId, encoded],
});
return {
to: this.allo.address(),
data: encodedData,
value: "0",
};
}
public getBatchRegisterRecipientData(
data: RegisterDataSuperfluid[],
): TransactionData {
this.checkPoolId();
const encodedParams: `0x${string}`[] = [];
data.forEach((registerData) => {
const encoded: `0x${string}` = encodeAbiParameters(
parseAbiParameters("address, address, (uint256, string)"),
[
registerData.registryAnchor,
registerData.recipientAddress,
[registerData.metadata.protocol, registerData.metadata.pointer],
],
);
encodedParams.push(encoded);
});
const poolIds: bigint[] = Array(encodedParams.length).fill(this.poolId);
const encodedData = encodeFunctionData({
abi: alloAbi,
functionName: "batchRegisterRecipient",
args: [poolIds, encodedParams],
});
return {
to: this.allo.address(),
data: encodedData,
value: "0",
};
}
public getDistributeData(flowRate: bigint): TransactionData {
this.checkPoolId();
const encoded: `0x${string}` = encodeAbiParameters(
parseAbiParameters("int96"),
[flowRate],
);
const encodedData = encodeFunctionData({
abi: alloAbi,
functionName: "distribute",
args: [this.poolId, [], encoded],
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
public getAllocationData(
recipientId: `0x${string}`,
flowRate: bigint,
): TransactionData {
this.checkPoolId();
const encoded: `0x${string}` = encodeAbiParameters(
parseAbiParameters("address, int96"),
[recipientId, flowRate],
);
const encodedData = encodeFunctionData({
abi: alloAbi,
functionName: "allocate",
args: [this.poolId, encoded],
});
return {
to: this.allo.address(),
data: encodedData,
value: "0",
};
}
public getBatchAllocationData(
allocations: AllocationSuperlfuid[],
): TransactionData {
this.checkPoolId();
const encodedParams: `0x${string}`[] = [];
allocations.forEach((allocation) => {
const encoded: `0x${string}` = encodeAbiParameters(
parseAbiParameters("address, int96"),
[allocation.recipientId, allocation.flowRate],
);
encodedParams.push(encoded);
});
const poolIds: bigint[] = Array(encodedParams.length).fill(this.poolId);
const encodedData = encodeFunctionData({
abi: alloAbi,
functionName: "batchAllocate",
args: [poolIds, encodedParams],
});
return {
to: this.allo.address(),
data: encodedData,
value: "0",
};
}
public getReviewRecipientData(
data: ReviewRecipientDataSuperfluid[],
): TransactionData {
this.checkStrategy();
const recipientIds = data.map((recipient) => recipient.recipientId);
const statuses = data.map((recipient) => recipient.recipientStatus);
const encodedData = encodeFunctionData({
abi: superfluidAbi,
functionName: "reviewRecipients",
args: [recipientIds, statuses],
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
public getCancelRecipientsData(
recipientIds: `0x${string}`[],
): TransactionData {
this.checkStrategy();
const encodedData = encodeFunctionData({
abi: superfluidAbi,
functionName: "cancelRecipients",
args: [recipientIds],
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
public getWithdrawData(
token: `0x${string}`,
amount: bigint,
): TransactionData {
this.checkStrategy();
const encodedData = encodeFunctionData({
abi: superfluidAbi,
functionName: "withdraw",
args: [token, amount],
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
public getCloseStream(): TransactionData {
this.checkStrategy();
const encodedData = encodeFunctionData({
abi: superfluidAbi,
functionName: "closeStream",
});
return {
to: this.strategy!,
data: encodedData,
value: "0",
};
}
}