mirror of
https://github.com/lux-tel/websites.git
synced 2026-10-30 20:31:36 +00:00
294 lines
8.4 KiB
TypeScript
294 lines
8.4 KiB
TypeScript
'use client';
|
|
|
|
import type { ReadContractData } from 'wagmi/query';
|
|
import { ServiceNodeRewardsAbi } from '../abis';
|
|
import { type ContractReadQueryProps, useContractReadQuery } from './useContractReadQuery';
|
|
import { useMemo } from 'react';
|
|
import { type ContractWriteQueryProps, useContractWriteQuery } from './useContractWriteQuery';
|
|
import { useChain } from './useChain';
|
|
import type { Address } from 'viem';
|
|
|
|
export type ClaimRewardsQuery = ContractWriteQueryProps & {
|
|
/** Claim rewards */
|
|
claimRewards: () => void;
|
|
};
|
|
|
|
export function useClaimRewardsQuery(): ClaimRewardsQuery {
|
|
const chain = useChain();
|
|
const { simulateAndWriteContract, ...rest } = useContractWriteQuery({
|
|
contract: 'ServiceNodeRewards',
|
|
functionName: 'claimRewards',
|
|
chain,
|
|
});
|
|
|
|
return {
|
|
claimRewards: simulateAndWriteContract,
|
|
...rest,
|
|
};
|
|
}
|
|
|
|
export type UpdateRewardsBalanceQuery = ContractWriteQueryProps & {
|
|
/** Update rewards balance */
|
|
updateRewardsBalance: () => void;
|
|
};
|
|
|
|
export type UseUpdateRewardsBalanceQueryParams = {
|
|
address?: Address;
|
|
rewards?: bigint;
|
|
blsSignature?: string;
|
|
excludedSigners?: Array<bigint>;
|
|
};
|
|
|
|
export function useUpdateRewardsBalanceQuery({
|
|
address,
|
|
rewards,
|
|
blsSignature,
|
|
excludedSigners,
|
|
}: UseUpdateRewardsBalanceQueryParams): UpdateRewardsBalanceQuery {
|
|
const chain = useChain();
|
|
|
|
const defaultArgs = useMemo(() => {
|
|
const encodedBlsSignature = blsSignature ? encodeBlsSignature(blsSignature) : null;
|
|
|
|
return [address, rewards, encodedBlsSignature, excludedSigners] as const;
|
|
}, [address, rewards, blsSignature, excludedSigners]);
|
|
|
|
const { simulateAndWriteContract, ...rest } = useContractWriteQuery({
|
|
contract: 'ServiceNodeRewards',
|
|
functionName: 'updateRewardsBalance',
|
|
chain,
|
|
// TODO: update the types to better reflect optional args as default
|
|
// @ts-expect-error -- This is fine as the args change once the query is ready to execute.
|
|
defaultArgs,
|
|
});
|
|
|
|
return {
|
|
updateRewardsBalance: simulateAndWriteContract,
|
|
...rest,
|
|
};
|
|
}
|
|
|
|
export type TotalNodesQuery = ContractReadQueryProps & {
|
|
/** The total number of nodes */
|
|
totalNodes: ReadContractData<typeof ServiceNodeRewardsAbi, 'totalNodes', []>;
|
|
};
|
|
|
|
export function useTotalNodesQuery(): TotalNodesQuery {
|
|
const chain = useChain();
|
|
const { data: totalNodes, ...rest } = useContractReadQuery({
|
|
contract: 'ServiceNodeRewards',
|
|
functionName: 'totalNodes',
|
|
chain,
|
|
});
|
|
|
|
return {
|
|
totalNodes,
|
|
...rest,
|
|
};
|
|
}
|
|
|
|
const HEX_BYTES = {
|
|
BLS_KEY_BYTES: 128,
|
|
BLS_SIG_BYTES: 256,
|
|
ED_25519_KEY_BYTES: 64,
|
|
ED_25519_SIG_BYTES: 128,
|
|
};
|
|
|
|
function encodeHexToBigIntChunks(hex: string, hexBytes: number): Array<bigint> {
|
|
if (hexBytes < 64 || hexBytes % 64 !== 0) {
|
|
throw new Error(`hexBytes must be divisible by 2. hexBits: ${hexBytes}`);
|
|
}
|
|
|
|
if (hex.length !== hexBytes) {
|
|
throw new Error(`Hex length is invalid, it must be a ${hexBytes} byte string`);
|
|
}
|
|
|
|
const numberOfChunks = hexBytes / 64;
|
|
|
|
const chunks = [];
|
|
|
|
for (let i = 0; i < numberOfChunks; i++) {
|
|
chunks.push(hex.slice(i * 64, (i + 1) * 64));
|
|
}
|
|
|
|
return chunks.map((hexChunk) => BigInt(`0x${hexChunk}`));
|
|
}
|
|
|
|
const encodeBlsPubKey = (hex: string) => {
|
|
const chunks = encodeHexToBigIntChunks(hex, HEX_BYTES.BLS_KEY_BYTES);
|
|
const [X, Y] = chunks;
|
|
if (chunks.length !== 2) {
|
|
throw new Error(`BLS Pubkey improperly chunked. Expected 2 chunks, got ${chunks.length}`);
|
|
}
|
|
if (typeof X === 'undefined') {
|
|
throw new Error(`BLS Pubkey improperly chunked. X is undefined, got ${X}`);
|
|
}
|
|
if (typeof Y === 'undefined') {
|
|
throw new Error(`BLS Pubkey improperly chunked. Y is undefined, got ${Y}`);
|
|
}
|
|
return { X, Y };
|
|
};
|
|
|
|
const encodeBlsSignature = (hex: string) => {
|
|
const chunks = encodeHexToBigIntChunks(hex, HEX_BYTES.BLS_SIG_BYTES);
|
|
const [sigs0, sigs1, sigs2, sigs3] = chunks;
|
|
if (chunks.length !== 4) {
|
|
throw new Error(`BLS Signature improperly chunked. Expected 4 chunks, got ${chunks.length}`);
|
|
}
|
|
if (typeof sigs0 === 'undefined') {
|
|
throw new Error(`BLS Signature improperly chunked. sigs0 is undefined, got ${sigs0}`);
|
|
}
|
|
if (typeof sigs1 === 'undefined') {
|
|
throw new Error(`BLS Signature improperly chunked. sigs0 is undefined, got ${sigs1}`);
|
|
}
|
|
if (typeof sigs2 === 'undefined') {
|
|
throw new Error(`BLS Signature improperly chunked. sigs0 is undefined, got ${sigs2}`);
|
|
}
|
|
if (typeof sigs3 === 'undefined') {
|
|
throw new Error(`BLS Signature improperly chunked. sigs0 is undefined, got ${sigs3}`);
|
|
}
|
|
|
|
return { sigs0, sigs1, sigs2, sigs3 };
|
|
};
|
|
|
|
const encodeED25519PubKey = (hex: string) => {
|
|
const chunks = encodeHexToBigIntChunks(hex, HEX_BYTES.ED_25519_KEY_BYTES);
|
|
const [pubKey] = chunks;
|
|
if (chunks.length !== 1) {
|
|
throw new Error(
|
|
`ED 25519 Public Key improperly chunked. Expected 1 chunk, got ${chunks.length}`
|
|
);
|
|
}
|
|
if (typeof pubKey === 'undefined') {
|
|
throw new Error(`ED 25519 Public Key improperly chunked. pubKey is undefined, got ${pubKey}`);
|
|
}
|
|
return { pubKey };
|
|
};
|
|
|
|
const encodeED25519Signature = (hex: string) => {
|
|
const chunks = encodeHexToBigIntChunks(hex, HEX_BYTES.ED_25519_SIG_BYTES);
|
|
const [sigs0, sigs1] = chunks;
|
|
if (chunks.length !== 2) {
|
|
throw new Error(
|
|
`ED 25519 Signature improperly chunked. Expected 2 chunks, got ${chunks.length}`
|
|
);
|
|
}
|
|
if (typeof sigs0 === 'undefined') {
|
|
throw new Error(`ED 25519 Signature improperly chunked. sigs0 is undefined, got ${sigs0}`);
|
|
}
|
|
if (typeof sigs1 === 'undefined') {
|
|
throw new Error(`ED 25519 Signature improperly chunked. sigs0 is undefined, got ${sigs1}`);
|
|
}
|
|
return { sigs0, sigs1 };
|
|
};
|
|
|
|
export type UseAddBLSPubKeyReturn = ContractWriteQueryProps & {
|
|
addBLSPubKey: () => void;
|
|
};
|
|
|
|
export function useAddBLSPubKey({
|
|
blsPubKey,
|
|
blsSignature,
|
|
nodePubKey,
|
|
userSignature,
|
|
fee = 0,
|
|
}: {
|
|
blsPubKey: string;
|
|
blsSignature: string;
|
|
nodePubKey: string;
|
|
userSignature: string;
|
|
fee?: number;
|
|
}): UseAddBLSPubKeyReturn {
|
|
const chain = useChain();
|
|
const defaultArgs = useMemo(() => {
|
|
const encodedBlsPubKey = encodeBlsPubKey(blsPubKey);
|
|
const encodedBlsSignature = encodeBlsSignature(blsSignature);
|
|
const { pubKey } = encodeED25519PubKey(nodePubKey);
|
|
const { sigs0, sigs1 } = encodeED25519Signature(userSignature);
|
|
|
|
const encodedNodeParams = {
|
|
serviceNodePubkey: pubKey,
|
|
serviceNodeSignature1: sigs0,
|
|
serviceNodeSignature2: sigs1,
|
|
fee,
|
|
};
|
|
|
|
return [encodedBlsPubKey, encodedBlsSignature, encodedNodeParams, []] as const;
|
|
}, [blsPubKey, blsSignature, nodePubKey, userSignature]);
|
|
|
|
const { simulateAndWriteContract, ...rest } = useContractWriteQuery({
|
|
contract: 'ServiceNodeRewards',
|
|
functionName: 'addBLSPublicKey',
|
|
chain,
|
|
defaultArgs,
|
|
});
|
|
|
|
return {
|
|
addBLSPubKey: simulateAndWriteContract,
|
|
...rest,
|
|
};
|
|
}
|
|
|
|
export type UseInitiateRemoveBLSPublicKeyReturn = ContractWriteQueryProps & {
|
|
initiateRemoveBLSPublicKey: () => void;
|
|
};
|
|
|
|
export function useInitiateRemoveBLSPublicKey({
|
|
contractId,
|
|
}: {
|
|
contractId: number;
|
|
}): UseInitiateRemoveBLSPublicKeyReturn {
|
|
const chain = useChain();
|
|
|
|
const defaultArgs = useMemo(() => [BigInt(contractId ?? 0)] as [bigint], [contractId]);
|
|
|
|
const { simulateAndWriteContract, ...rest } = useContractWriteQuery({
|
|
contract: 'ServiceNodeRewards',
|
|
functionName: 'initiateRemoveBLSPublicKey',
|
|
chain,
|
|
defaultArgs,
|
|
});
|
|
|
|
return {
|
|
initiateRemoveBLSPublicKey: simulateAndWriteContract,
|
|
...rest,
|
|
};
|
|
}
|
|
|
|
export type UseRemoveBLSPublicKeyWithSignatureReturn = ContractWriteQueryProps & {
|
|
removeBLSPublicKeyWithSignature: () => void;
|
|
};
|
|
|
|
export function useRemoveBLSPublicKeyWithSignature({
|
|
blsPubKey,
|
|
timestamp,
|
|
blsSignature,
|
|
excludedSigners = [],
|
|
}: {
|
|
blsPubKey: string;
|
|
timestamp: number;
|
|
blsSignature: string;
|
|
excludedSigners?: Array<bigint>;
|
|
}): UseRemoveBLSPublicKeyWithSignatureReturn {
|
|
const chain = useChain();
|
|
const defaultArgs = useMemo(() => {
|
|
const encodedBlsPubKey = encodeBlsPubKey(blsPubKey);
|
|
const encodedBlsSignature = encodeBlsSignature(blsSignature);
|
|
const encodedTimestamp = BigInt(timestamp);
|
|
|
|
return [encodedBlsPubKey, encodedTimestamp, encodedBlsSignature, excludedSigners] as const;
|
|
}, [blsPubKey, timestamp, blsSignature, excludedSigners]);
|
|
|
|
const { simulateAndWriteContract, ...rest } = useContractWriteQuery({
|
|
contract: 'ServiceNodeRewards',
|
|
functionName: 'removeBLSPublicKeyWithSignature',
|
|
chain,
|
|
defaultArgs,
|
|
});
|
|
|
|
return {
|
|
removeBLSPublicKeyWithSignature: simulateAndWriteContract,
|
|
...rest,
|
|
};
|
|
}
|