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
167 changes: 70 additions & 97 deletions apps/tangle-cloud/src/data/services/useServiceApproveTx.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ vi.mock('@tangle-network/tangle-shared-ui/hooks/useContractWrite', () => ({

describe('useServiceApproveTx', () => {
const activeAddress = '0xabc0000000000000000000000000000000000000';
const ZERO_BLS_PUBKEY = [0n, 0n, 0n, 0n] as const;
const ZERO_BLS_POP = [0n, 0n] as const;

beforeEach(() => {
vi.clearAllMocks();
Expand All @@ -40,17 +42,13 @@ describe('useServiceApproveTx', () => {
});
});

it('uses approveService and clamps staking percent bounds for simple approvals', async () => {
let capturedFactory:
| ((params: any, activeAddress: any) => Promise<any>)
| undefined;

const captureFactory = (): {
factory: () => (params: any, addr: any) => Promise<any>;
} => {
let captured: ((params: any, addr: any) => Promise<any>) | undefined;
mockUseContractWrite.mockImplementation(
(
_abi: unknown,
factory: (params: any, activeAddress: any) => Promise<any>,
) => {
capturedFactory = factory;
(_abi: unknown, factory: (params: any, addr: any) => Promise<any>) => {
captured = factory;
return {
execute: vi.fn(),
status: 'NOT_YET_INITIATED',
Expand All @@ -62,58 +60,34 @@ describe('useServiceApproveTx', () => {
};
},
);

renderHook(() => useServiceApproveTx());

const clampedLow = await capturedFactory?.(
{
requestId: 1n,
stakingPercent: -5,
return {
factory: () => {
if (!captured) throw new Error('factory not captured');
return captured;
},
activeAddress,
);
};
};

expect(clampedLow.functionName).toBe('approveService');
expect(clampedLow.args).toEqual([1n, 0]);
it('builds the unified ApprovalParams with empty optional fields when only requestId is given', async () => {
const factory = captureFactory().factory();
const config = await factory({ requestId: 1n }, activeAddress);

const clampedHigh = await capturedFactory?.(
expect(config.functionName).toBe('approveService');
expect(config.args).toEqual([
{
requestId: 2n,
stakingPercent: 150,
requestId: 1n,
securityCommitments: [],
blsPubkey: ZERO_BLS_PUBKEY,
blsPopSignature: ZERO_BLS_POP,
teeCommitments: [],
},
activeAddress,
);

expect(clampedHigh.functionName).toBe('approveService');
expect(clampedHigh.args).toEqual([2n, 100]);
]);
});

it('uses approveServiceWithCommitments when security commitments are provided', async () => {
let capturedFactory:
| ((params: any, activeAddress: any) => Promise<any>)
| undefined;

mockUseContractWrite.mockImplementation(
(
_abi: unknown,
factory: (params: any, activeAddress: any) => Promise<any>,
) => {
capturedFactory = factory;
return {
execute: vi.fn(),
status: 'NOT_YET_INITIATED',
error: null,
reset: vi.fn(),
txHash: null,
isSuccess: false,
isLoading: false,
};
},
);

renderHook(() => useServiceApproveTx());

const config = await capturedFactory?.(
it('passes per-asset security commitments through unchanged', async () => {
const factory = captureFactory().factory();
const config = await factory(
{
requestId: 9n,
securityCommitments: [
Expand All @@ -129,58 +103,57 @@ describe('useServiceApproveTx', () => {
activeAddress,
);

expect(config.functionName).toBe('approveServiceWithCommitments');
expect(config.args).toEqual([
9n,
[
{
asset: {
kind: 1,
token: '0x9999999999999999999999999999999999999999',
},
exposureBps: 7500,
expect(config.functionName).toBe('approveService');
expect(config.args[0].securityCommitments).toEqual([
{
asset: {
kind: 1,
token: '0x9999999999999999999999999999999999999999',
},
],
exposureBps: 7500,
},
]);
});

it('returns null tx config when contracts are unavailable for the active chain', async () => {
mockGetContractsByChainId.mockImplementation(() => {
throw new Error('unsupported chain');
});

let capturedFactory:
| ((params: any, activeAddress: any) => Promise<any>)
| undefined;

mockUseContractWrite.mockImplementation(
(
_abi: unknown,
factory: (params: any, activeAddress: any) => Promise<any>,
) => {
capturedFactory = factory;
return {
execute: vi.fn(),
status: 'NOT_YET_INITIATED',
error: null,
reset: vi.fn(),
txHash: null,
isSuccess: false,
isLoading: false,
};
},
);

renderHook(() => useServiceApproveTx());

const config = await capturedFactory?.(
it('threads BLS and TEE fields when supplied (opt-in capabilities)', async () => {
const factory = captureFactory().factory();
const blsPubkey = [1n, 2n, 3n, 4n] as const;
const blsPopSignature = [5n, 6n] as const;
const tee = {
backend: 2,
expectedMeasurement:
'0x1111111111111111111111111111111111111111111111111111111111111111' as const,
nonceBinding:
'0x2222222222222222222222222222222222222222222222222222222222222222' as const,
expiresAt: 0n,
};

const config = await factory(
{
requestId: 1n,
stakingPercent: 50,
requestId: 3n,
blsPubkey,
blsPopSignature,
teeCommitments: [tee],
},
activeAddress,
);

expect(config.args[0]).toEqual({
requestId: 3n,
securityCommitments: [],
blsPubkey,
blsPopSignature,
teeCommitments: [tee],
});
});

it('returns null tx config when contracts are unavailable for the active chain', async () => {
mockGetContractsByChainId.mockImplementation(() => {
throw new Error('unsupported chain');
});

const factory = captureFactory().factory();
const config = await factory({ requestId: 1n }, activeAddress);
expect(config).toBeNull();
});
});
Loading
Loading