Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
WALLET_PRIVATE_KEY=
RPC_URL=
CHAIN_ID=
TRIGGER_INTERVAL_HOURS=
TRIGGER_SLI_JOB_INTERVAL_CRON=
TRIGGER_CLAIMS_TRACKING_JOB_INTERVAL_CRON=
CDP_SERVICE_URL=
JOB_TRIGGER_AUTH_TOKEN=
APP_PORT=
60 changes: 60 additions & 0 deletions src/blockchain/abis/client-abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Abi } from "viem";

export const CLIENT_CONTRACT_ABI = [
{
type: "function",
name: "getSPClients",
inputs: [
{
name: "provider",
type: "uint64",
internalType: "CommonTypes.FilActorId",
},
],
outputs: [
{
name: "clients",
type: "address[]",
internalType: "address[]",
},
],
stateMutability: "view",
},
{
type: "function",
name: "getClientAllocationIdsPerProvider",
inputs: [
{
name: "provider",
type: "uint64",
internalType: "CommonTypes.FilActorId",
},
{
name: "client",
type: "address",
internalType: "address",
},
],
outputs: [
{
name: "",
type: "uint64[]",
internalType: "CommonTypes.FilActorId[]",
},
],
stateMutability: "view",
},
{
type: "function",
name: "claimsTerminatedEarly",
inputs: [
{
name: "claims",
type: "uint64[]",
internalType: "uint64[]",
},
],
outputs: [],
stateMutability: "nonpayable",
},
] as const satisfies Abi;
2 changes: 1 addition & 1 deletion src/blockchain/abis/sla-allocator-abi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Abi } from "viem";

export const SLA_ALLOCATOR_ABI = [
export const SLA_ALLOCATOR_CONTRACT_ABI = [
{
type: "function",
name: "providers",
Expand Down
2 changes: 1 addition & 1 deletion src/blockchain/abis/sli-oracle-abi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const SLI_ORACLE_ABI = [
export const SLI_ORACLE_CONTRACT_ABI = [
{
type: "function",
name: "setSLI",
Expand Down
10 changes: 10 additions & 0 deletions src/blockchain/blockchain-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { privateKeyToAccount } from "viem/accounts";
import { filecoin, filecoinCalibration } from "viem/chains";
import { SERVICE_CONFIG } from "../config/env.js";
import { baseLogger } from "../utils/logger.js";

export const getChain = (chainId: number) => {
switch (chainId) {
Expand All @@ -30,6 +31,12 @@ export const getChain = (chainId: number) => {
default: { http: ["http://fidlabs.servehttp.com:1234/rpc/v1"] },
},
testnet: true,
contracts: {
multicall3: {
address: "0xe1C001010343EAEfa2E80bf0F1072f93b867616A",
blockCreated: 1657068,
},
},
});
default:
throw new Error(`Unsupported chain ID: ${chainId}`);
Expand All @@ -50,6 +57,7 @@ export function getRpcClient() {
chain,
transport: http(SERVICE_CONFIG.RPC_URL),
});
baseLogger.info("RPC client created on chain ID " + chain.id);
}

return rpcClient;
Expand All @@ -62,6 +70,8 @@ export function getWalletClient() {
chain,
transport: http(SERVICE_CONFIG.RPC_URL),
});

baseLogger.info("Wallet client created on chain ID " + chain.id);
}

return walletClient;
Expand Down
17 changes: 10 additions & 7 deletions src/blockchain/sla-allocator-contract.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import { Address } from "viem";
import { SERVICE_CONFIG } from "../config/env.js";
import { logger } from "../utils/logger.js";
import { SLA_ALLOCATOR_ABI } from "./abis/sla-allocator-abi.js";
import { baseLogger } from "../utils/logger.js";
import { SLA_ALLOCATOR_CONTRACT_ABI } from "./abis/sla-allocator-abi.js";
import { getRpcClient } from "./blockchain-client.js";

const childLogger = baseLogger.child(
{ avengers: "assemble" },
{ msgPrefix: "[SLA Allocator Contract] " },
);

export async function getProvidersFromSlaAllocatorContract(): Promise<
number[]
> {
const rpcClient = getRpcClient();

logger.info("Fetching providers from SLA Allocator contract...");
childLogger.info("Fetching providers from contract...");

const providers = await rpcClient.readContract({
address: SERVICE_CONFIG.SLA_ALLOCATOR_CONTRACT_ADDRESS as Address,
abi: SLA_ALLOCATOR_ABI,
abi: SLA_ALLOCATOR_CONTRACT_ABI,
functionName: "getProviders",
});

logger.info(
`Fetched ${providers.length} providers from SLA Allocator contract`,
);
childLogger.info(`Fetched ${providers.length} providers from contract`);

return providers.map((p) => Number(p));
}
95 changes: 95 additions & 0 deletions src/blockchain/sla-client-contract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Address } from "viem";
import { SERVICE_CONFIG } from "../config/env.js";

import { baseLogger } from "../utils/logger.js";
import { CLIENT_CONTRACT_ABI } from "./abis/client-abi.js";
import { getRpcClient, getWalletClient } from "./blockchain-client.js";

const childLogger = baseLogger.child(
{ avengers: "assemble" },
{ msgPrefix: "[SLA Client Contract] " },
);

export async function getClientsForSPFromClientContract(
storageProviderId: number,
): Promise<Address[]> {
const rpcClient = getRpcClient();

childLogger.info("Fetching clients for storage provider...");

const spClients = await rpcClient.readContract({
address: SERVICE_CONFIG.CLIENT_CONTRACT_ADDRESS as Address,
abi: CLIENT_CONTRACT_ABI,
functionName: "getSPClients",
args: [BigInt(storageProviderId)],
});

childLogger.info(
`Fetched ${spClients.length} clients for SP ${storageProviderId}`,
);

return spClients as Address[];
}

export async function getClientAllocationIdsPerProvider(
storageProviderId: number,
clientAddresses: Address[],
): Promise<number[]> {
const rpcClient = getRpcClient();

childLogger.info(
`Fetching allocation ID for clients and storage providers ${storageProviderId}...`,
);

const multicallData = clientAddresses.map((clientId) => ({
address: SERVICE_CONFIG.CLIENT_CONTRACT_ADDRESS as Address,
abi: CLIENT_CONTRACT_ABI,
functionName: "getClientAllocationIdsPerProvider",
args: [BigInt(storageProviderId), clientId],
}));

const multicall = await rpcClient.multicall({
contracts: multicallData,
});

childLogger.info(
`Fetched ${multicall.length} allocations for storage provider ${storageProviderId}...`,
);

const ids = multicall
.filter((response) => !response.error)
.flatMap((response) => Number(response.result));

return ids;
}

export async function setClaimTerminatedEarly(allocationIds: bigint[]) {
const rpcClient = getRpcClient();
const walletClient = getWalletClient();

childLogger.info("claimsTerminatedEarly: Simulating request...");

const { request } = await rpcClient.simulateContract({
address: SERVICE_CONFIG.CLIENT_CONTRACT_ADDRESS as Address,
abi: CLIENT_CONTRACT_ABI,
functionName: "claimsTerminatedEarly",
args: [allocationIds],
account: walletClient.account,
});

childLogger.info("claimsTerminatedEarly: Sending transaction...");

const txHash = await walletClient.writeContract(request);

childLogger.info(
`claimsTerminatedEarly: Transaction sent: ${txHash}, waiting for confirmation...`,
);

const receipt = await rpcClient.waitForTransactionReceipt({
hash: txHash,
});

childLogger.info(
`claimsTerminatedEarly: Transaction executed in block ${receipt.blockNumber}`,
);
}
46 changes: 28 additions & 18 deletions src/blockchain/sli-oracle-contract.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Address, encodeFunctionData } from "viem";
import { SERVICE_CONFIG } from "../config/env.js";
import { logger } from "../utils/logger.js";
import { baseLogger } from "../utils/logger.js";
import {
CdpSliResponse,
SLIAttestation,
StorageProvidersSLIMetric,
} from "../utils/types.js";
import { SLI_ORACLE_ABI } from "./abis/sli-oracle-abi.js";
import { SLI_ORACLE_CONTRACT_ABI } from "./abis/sli-oracle-abi.js";
import { getRpcClient, getWalletClient } from "./blockchain-client.js";

const childLogger = baseLogger.child(
{ avengers: "assemble" },
{ msgPrefix: "[SLI Oracle Contract] " },
);

export async function setSliOnOracleContract(
sliDataForProviders: CdpSliResponse[],
) {
Expand All @@ -22,7 +27,7 @@ export async function setSliOnOracleContract(
provider: bigint;
sli: SLIAttestation;
}[] = sliDataForProviders.map((provider) => {
logger.info(
childLogger.info(
`Preparing SLI data for provider ${provider.storageProviderId}`,
);
const availabilityMetric =
Expand Down Expand Up @@ -82,68 +87,73 @@ export async function setSliOnOracleContract(

const encodedCalls = buildedSliData.map((req) =>
encodeFunctionData({
abi: SLI_ORACLE_ABI,
abi: SLI_ORACLE_CONTRACT_ABI,
functionName: "setSLI",
args: [req.provider, req.sli],
}),
);

logger.info("Simulating request to oracle contract...");
childLogger.info("setSLI: Simulating request...");

const { request } = await rpcClient.simulateContract({
address: oracleContractAddress,
abi: SLI_ORACLE_ABI,
abi: SLI_ORACLE_CONTRACT_ABI,
functionName: "multicall",
args: [encodedCalls],
account: walletClient.account,
});

logger.info("Simulation successful.");

logger.info("Sending transaction to oracle contract...");
childLogger.info("setSLI: Sending transaction...");

const txHash = await walletClient.writeContract(request);

logger.info(`Transaction sent: ${txHash}`);
logger.info(`Waiting for confirmation...`);
childLogger.info(
`setSLI: Transaction sent: ${txHash}, waiting for confirmation...`,
);

const receipt = await rpcClient.waitForTransactionReceipt({
hash: txHash,
});

logger.info(`Transaction executed in block ${receipt.blockNumber}`);
childLogger.info(
`setSLI: Transaction executed in block ${receipt.blockNumber}`,
);
}

export async function getSPEmptyAttestations(): Promise<void> {
const rpcClient = getRpcClient();

logger.info(
childLogger.info(
"Fetching Attestations from SLI Oracle contract for SP: f03315260",
);

const providers = await rpcClient.readContract({
address: SERVICE_CONFIG.ORACLE_CONTRACT_ADDRESS as Address,
abi: SLI_ORACLE_ABI,
abi: SLI_ORACLE_CONTRACT_ABI,
functionName: "attestations",
args: [90999],
});

logger.info(`Fetched Attestation from SLI Oracle contract: ` + providers);
childLogger.info(
`Fetched Attestation from SLI Oracle contract: ` + providers,
);
}

export async function getSPFillAttestations(): Promise<void> {
const rpcClient = getRpcClient();

logger.info(
childLogger.info(
"Fetching Attestations from SLI Oracle contract for SP: f03315260",
);

const providers = await rpcClient.readContract({
address: SERVICE_CONFIG.ORACLE_CONTRACT_ADDRESS as Address,
abi: SLI_ORACLE_ABI,
abi: SLI_ORACLE_CONTRACT_ABI,
functionName: "attestations",
args: [3315260],
});

logger.info(`Fetched Attestations from SLI Oracle contract: ` + providers);
childLogger.info(
`Fetched Attestations from SLI Oracle contract: ` + providers,
);
}
Loading