mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.4 KiB
191 lines
4.4 KiB
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
|
|
|
|
import {
|
|
afterEach,
|
|
beforeEach,
|
|
describe,
|
|
expect,
|
|
it,
|
|
jest
|
|
} from '@jest/globals';
|
|
|
|
import { HyperliquidImportService } from './hyperliquid-import.service';
|
|
|
|
describe('HyperliquidImportService', () => {
|
|
let configurationService: ConfigurationService;
|
|
let hyperliquidImportService: HyperliquidImportService;
|
|
|
|
beforeEach(() => {
|
|
const getMock = jest.fn().mockImplementation((key: string) => {
|
|
if (key === 'REQUEST_TIMEOUT') {
|
|
return 2000;
|
|
}
|
|
|
|
return undefined;
|
|
});
|
|
|
|
configurationService = {
|
|
get: getMock
|
|
} as unknown as ConfigurationService;
|
|
|
|
hyperliquidImportService = new HyperliquidImportService(
|
|
configurationService
|
|
);
|
|
|
|
jest.spyOn(global, 'fetch').mockImplementation(async (_url, init) => {
|
|
const payload = JSON.parse(init.body as string);
|
|
|
|
if (payload.type === 'spotMeta') {
|
|
return createResponse({
|
|
tokens: [
|
|
{ fullName: 'Hyperliquid', index: 0, name: 'HYPE' },
|
|
{ fullName: 'USD Coin', index: 1, name: 'USDC' }
|
|
],
|
|
universe: [{ name: '@2', tokens: [0, 1] }]
|
|
});
|
|
}
|
|
|
|
if (payload.type === 'userFills') {
|
|
return createResponse([
|
|
{
|
|
builderFee: '0.05',
|
|
coin: '@2',
|
|
fee: '0.1',
|
|
px: '10',
|
|
side: 'B',
|
|
sz: '2',
|
|
time: Date.UTC(2024, 0, 1)
|
|
}
|
|
]);
|
|
}
|
|
|
|
if (payload.type === 'userFunding') {
|
|
return createResponse([
|
|
{
|
|
delta: {
|
|
coin: 'BTC',
|
|
usdc: '-1.5'
|
|
},
|
|
time: Date.UTC(2024, 0, 2)
|
|
},
|
|
{
|
|
delta: {
|
|
coin: 'ETH',
|
|
usdc: '2.5'
|
|
},
|
|
time: Date.UTC(2024, 0, 3)
|
|
}
|
|
]);
|
|
}
|
|
|
|
if (payload.type === 'userNonFundingLedgerUpdates') {
|
|
return createResponse([
|
|
{
|
|
delta: {
|
|
amount: '3.25',
|
|
token: 'HYPE',
|
|
type: 'rewardsClaim'
|
|
},
|
|
time: Date.UTC(2024, 0, 4)
|
|
},
|
|
{
|
|
delta: {
|
|
fee: '0.2',
|
|
feeToken: 'USDC',
|
|
type: 'send'
|
|
},
|
|
time: Date.UTC(2024, 0, 5)
|
|
},
|
|
{
|
|
delta: {
|
|
type: 'deposit',
|
|
usdc: '100'
|
|
},
|
|
time: Date.UTC(2024, 0, 6)
|
|
}
|
|
]);
|
|
}
|
|
|
|
return createResponse([]);
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
});
|
|
|
|
it('maps fills, funding and selected ledger items', async () => {
|
|
const activities = await hyperliquidImportService.getActivities({
|
|
walletAddress: '0x0000000000000000000000000000000000000001'
|
|
});
|
|
|
|
expect(activities).toHaveLength(5);
|
|
|
|
expect(activities[0]).toMatchObject({
|
|
dataSource: 'HYPERLIQUID',
|
|
quantity: 2,
|
|
symbol: 'HYPE/USDC',
|
|
type: 'BUY',
|
|
unitPrice: 10
|
|
});
|
|
expect(activities[0].fee).toBeCloseTo(0.15);
|
|
|
|
expect(
|
|
activities.some((activity) => {
|
|
return (
|
|
activity.type === 'FEE' &&
|
|
activity.symbol === 'BTC' &&
|
|
activity.unitPrice === 1.5
|
|
);
|
|
})
|
|
).toBe(true);
|
|
|
|
expect(
|
|
activities.some((activity) => {
|
|
return (
|
|
activity.type === 'INTEREST' &&
|
|
activity.symbol === 'ETH' &&
|
|
activity.unitPrice === 2.5
|
|
);
|
|
})
|
|
).toBe(true);
|
|
|
|
expect(
|
|
activities.some((activity) => {
|
|
return (
|
|
activity.type === 'INTEREST' &&
|
|
activity.symbol === 'HYPE' &&
|
|
activity.unitPrice === 3.25
|
|
);
|
|
})
|
|
).toBe(true);
|
|
|
|
expect(
|
|
activities.some((activity) => {
|
|
return (
|
|
activity.type === 'FEE' &&
|
|
activity.symbol === 'USDC' &&
|
|
activity.unitPrice === 0.2
|
|
);
|
|
})
|
|
).toBe(true);
|
|
});
|
|
|
|
it('skips ledger updates when disabled', async () => {
|
|
const activities = await hyperliquidImportService.getActivities({
|
|
includeLedger: false,
|
|
walletAddress: '0x0000000000000000000000000000000000000001'
|
|
});
|
|
|
|
expect(activities).toHaveLength(3);
|
|
});
|
|
});
|
|
|
|
function createResponse(data: unknown) {
|
|
return Promise.resolve({
|
|
json: async () => data,
|
|
ok: true,
|
|
status: 200,
|
|
statusText: 'OK'
|
|
} as Response);
|
|
}
|
|
|