Skip to content

Commit

Permalink
feat: added a batch query and changed some type names
Browse files Browse the repository at this point in the history
  • Loading branch information
SissonJ committed Mar 12, 2024
1 parent e500c6f commit 3b9a0a7
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 45 deletions.
73 changes: 68 additions & 5 deletions src/contracts/services/derivativeScrt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,37 @@ import {
beforeAll,
} from 'vitest';
import { of } from 'rxjs';
import { StakingDerivativesFeesResponse, StakingDerivativesInfoResponse } from '~/types/contracts/derivativeScrt/response';
import {
DerivativeScrtFeeInfoResponse,
DerivativeScrtStakingInfoResponse,
} from '~/types/contracts/derivativeScrt/response';
import {
parseDerivativeScrtFeeInfo,
parseDerivativeScrtStakingInfo,
parseDerivativeScrtAllInfo,
queryDerivativeScrtFeeInfo,
queryDerivativeScrtFeeInfo$,
queryDerivativeScrtStakingInfo,
queryDerivativeScrtStakingInfo$,
queryDerivativeScrtAllInfo,
queryDerivativeScrtAllInfo$,
} from '~/contracts/services/derivativeScrt';
import stakingInfoResponse from '~/test/mocks/derivativeScrt/stakingInfoResponse.json';
import stakingInfoResponseParsed from '~/test/mocks/derivativeScrt/stakingInfoResponseParsed.json';
import feeInfoResponse from '~/test/mocks/derivativeScrt/feeInfoResponse.json';
import feeInfoResponseParsed from '~/test/mocks/derivativeScrt/feeInfoResponseParsed.json';
import { BatchQueryParsedResponse } from '~/types/contracts/batchQuery/model';

const batchQueryResponse = [
{
id: 'staking_info',
response: stakingInfoResponse,
},
{
id: 'fee_info',
response: feeInfoResponse,
},
];

const sendSecretClientContractQuery$ = vi.hoisted(() => vi.fn());

Expand All @@ -34,11 +52,15 @@ beforeAll(() => {
vi.mock('~/client/services/clientServices', () => ({
sendSecretClientContractQuery$,
}));

vi.mock('~/contracts/services/batchQuery', () => ({
batchQuery$: vi.fn(() => of(batchQueryResponse)),
}));
});

test('it can parse the staking info', () => {
expect(parseDerivativeScrtStakingInfo(
stakingInfoResponse as StakingDerivativesInfoResponse,
stakingInfoResponse as DerivativeScrtStakingInfoResponse,
)).toStrictEqual(stakingInfoResponseParsed);
});

Expand All @@ -55,7 +77,7 @@ test('it can call the query staking info service', async () => {

let output;
queryDerivativeScrtStakingInfo$(input).subscribe({
next: (response) => {
next: (response: any) => {
output = response;
},
});
Expand Down Expand Up @@ -85,7 +107,7 @@ test('it can call the query staking info service', async () => {

test('it can parse the fee info', () => {
expect(parseDerivativeScrtFeeInfo(
feeInfoResponse as StakingDerivativesFeesResponse,
feeInfoResponse as DerivativeScrtFeeInfoResponse,
)).toStrictEqual(feeInfoResponseParsed);
});

Expand All @@ -102,7 +124,7 @@ test('it can call the query fees info service', async () => {

let output;
queryDerivativeScrtFeeInfo$(input).subscribe({
next: (response) => {
next: (response: any) => {
output = response;
},
});
Expand All @@ -129,3 +151,44 @@ test('it can call the query fees info service', async () => {

expect(output2).toStrictEqual(feeInfoResponseParsed);
});

test('it can parse the batch query resonse', () => {
expect(parseDerivativeScrtAllInfo(
batchQueryResponse as BatchQueryParsedResponse,
)).toStrictEqual({
...feeInfoResponseParsed,
...stakingInfoResponseParsed,
});
});

test('it can call the query all info service', async () => {
const input = {
queryRouterContractAddress: 'QUERY_ROUTER_CODE_HASH',
queryRouterCodeHash: 'QUERY_ROUTER_CODE_HASH',
contractAddress: 'DERIVATIVE_CONTRACT_ADDRESS',
codeHash: 'DERIVATIVE_CODE_HASH',
lcdEndpoint: 'LCD_ENDPOINT',
chainId: 'CHAIN_ID',
};

let output;
queryDerivativeScrtAllInfo$(input).subscribe({
next: (response: any) => {
output = response;
},
});

expect(output).toStrictEqual({
...feeInfoResponseParsed,
...stakingInfoResponseParsed,
});

// async/await function
sendSecretClientContractQuery$.mockReturnValueOnce(of(feeInfoResponse));
const output2 = await queryDerivativeScrtAllInfo(input);

expect(output2).toStrictEqual({
...feeInfoResponseParsed,
...stakingInfoResponseParsed,
});
});
145 changes: 128 additions & 17 deletions src/contracts/services/derivativeScrt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ import {
msgQueryScrtDerivativeStakingInfo,
} from '~/contracts/definitions/derivativeScrt';
import {
StakingDerivativesFeesResponse,
StakingDerivativesInfoResponse,
DerivativeScrtFeeInfoResponse,
DerivativeScrtStakingInfoResponse,
} from '~/types/contracts/derivativeScrt/response';
import {
StakingDerivativesFee,
StakingDerivativesInfo,
DerivativeScrtFeeInfo,
DerivativeScrtStakingInfo,
DerivativeScrtInfo,
} from '~/types/contracts/derivativeScrt/model';
import {
BatchQueryParsedResponse,
BatchQueryParsedResponseItem,
} from '~/types/contracts/batchQuery/model';
import { batchQuery$ } from './batchQuery';

// Contract returns price as a rate of stkd-SCRT/SCRT with 6 decimals
const DERIVATE_PRICE_DECIMALS = 6;
Expand All @@ -27,24 +33,29 @@ const DERIVATE_PRICE_DECIMALS = 6;
* parses the response for the stkd-scrt contract info
*/
function parseDerivativeScrtStakingInfo(
data: StakingDerivativesInfoResponse,
): StakingDerivativesInfo {
data: DerivativeScrtStakingInfoResponse,
): DerivativeScrtStakingInfo {
const { staking_info: stakingInfo } = data;
const {
price: exchangeRate,
rewards: communityRewards,
total_derivative_token_supply: supply,
unbond_amount_of_next_batch: nextUnboundAmount,
next_unbonding_batch_time: nextUnbondingBatchEstimatedTime,
validators,
validators: validatorsResp,
} = stakingInfo;

const validators = validatorsResp.map((nextValidator) => ({
validatorAddress: nextValidator.validator,
weight: nextValidator.weight,
}));

return {
validators,
supply: convertCoinFromUDenom(supply, DERIVATE_PRICE_DECIMALS).toNumber(),
supply: convertCoinFromUDenom(supply, DERIVATE_PRICE_DECIMALS).toString(),
exchangeRate: convertCoinFromUDenom(exchangeRate, DERIVATE_PRICE_DECIMALS).toNumber(),
communityRewards: convertCoinFromUDenom(communityRewards, DERIVATE_PRICE_DECIMALS).toNumber(),
nextUnboundAmount: convertCoinFromUDenom(nextUnboundAmount, DERIVATE_PRICE_DECIMALS).toNumber(),
communityRewards: convertCoinFromUDenom(communityRewards, DERIVATE_PRICE_DECIMALS).toString(),
nextUnboundAmount: convertCoinFromUDenom(nextUnboundAmount, DERIVATE_PRICE_DECIMALS).toString(),
// Seconds to Miliseconds
nextUnbondingBatchEstimatedTime: nextUnbondingBatchEstimatedTime * 1000,
};
Expand All @@ -64,13 +75,15 @@ const queryDerivativeScrtStakingInfo$ = ({
lcdEndpoint?: string,
chainId?: string,
}) => getActiveQueryClient$(lcdEndpoint, chainId).pipe(
switchMap(({ client }) => sendSecretClientContractQuery$({
switchMap(({ client }: {client:any}) => sendSecretClientContractQuery$({
queryMsg: msgQueryScrtDerivativeStakingInfo(Math.round(new Date().getTime() / 1000)),
client,
contractAddress,
codeHash,
})),
map((response) => parseDerivativeScrtStakingInfo(response as StakingDerivativesInfoResponse)),
map((response: any) => parseDerivativeScrtStakingInfo(
response as DerivativeScrtStakingInfoResponse,
)),
first(),
);

Expand All @@ -97,15 +110,36 @@ async function queryDerivativeScrtStakingInfo({
}

/**
*
* parse the response for fee info
*/
const parseDerivativeScrtFeeInfo = (
response: StakingDerivativesFeesResponse,
): StakingDerivativesFee => ({
response: DerivativeScrtFeeInfoResponse,
): DerivativeScrtFeeInfo => ({
withdrawFee: Number(response.fee_info.withdraw) / 100000,
depositFee: Number(response.fee_info.deposit) / 100000,
});

/**
* parse the response from the batch query contract
*/
const parseDerivativeScrtAllInfo = (
response: BatchQueryParsedResponse,
): DerivativeScrtInfo => {
const stakingInfoResponse = response.find(
(nextBatchItem: BatchQueryParsedResponseItem) => nextBatchItem.id === 'staking_info',
);
const feeInfoResponse = response.find(
(nextBatchItem: BatchQueryParsedResponseItem) => nextBatchItem.id === 'fee_info',
);
if (!stakingInfoResponse || !feeInfoResponse) {
throw new Error(`Unable to parse batch query response: ${response}`);
}
return {
...parseDerivativeScrtStakingInfo(stakingInfoResponse.response),
...parseDerivativeScrtFeeInfo(feeInfoResponse.response),
};
};

/**
* query the fee info
*/
Expand All @@ -120,13 +154,13 @@ const queryDerivativeScrtFeeInfo$ = ({
lcdEndpoint?: string,
chainId?: string,
}) => getActiveQueryClient$(lcdEndpoint, chainId).pipe(
switchMap(({ client }) => sendSecretClientContractQuery$({
switchMap(({ client }: { client: any }) => sendSecretClientContractQuery$({
queryMsg: msgQueryScrtDerivativeFees(),
client,
contractAddress,
codeHash,
})),
map((response) => parseDerivativeScrtFeeInfo(response as StakingDerivativesFeesResponse)),
map((response: any) => parseDerivativeScrtFeeInfo(response as DerivativeScrtFeeInfoResponse)),
first(),
);

Expand All @@ -152,11 +186,88 @@ async function queryDerivativeScrtFeeInfo({
}));
}

/**
* query both the staking info and the fee info
*/
const queryDerivativeScrtAllInfo$ = ({
queryRouterContractAddress,
queryRouterCodeHash,
contractAddress,
codeHash,
lcdEndpoint,
chainId,
}: {
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
contractAddress: string,
codeHash: string,
lcdEndpoint?: string,
chainId?: string,
}) => batchQuery$({
queries: [
{
id: 'staking_info',
contract: {
address: contractAddress,
codeHash,
},
queryMsg: msgQueryScrtDerivativeStakingInfo(Math.round(new Date().getTime() / 1000)),
},
{
id: 'fee_info',
contract: {
address: contractAddress,
codeHash,
},
queryMsg: msgQueryScrtDerivativeFees(),

},
],
lcdEndpoint,
contractAddress: queryRouterContractAddress,
codeHash: queryRouterCodeHash,
chainId,
}).pipe(
map((response: any) => parseDerivativeScrtAllInfo(response as BatchQueryParsedResponse)),
first(),
);

/**
* query the fee info and the staking info
*/
async function queryDerivativeScrtAllInfo({
queryRouterContractAddress,
queryRouterCodeHash,
contractAddress,
codeHash,
lcdEndpoint,
chainId,
}: {
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
contractAddress: string,
codeHash: string,
lcdEndpoint?: string,
chainId?: string,
}) {
return lastValueFrom(queryDerivativeScrtAllInfo$({
queryRouterContractAddress,
queryRouterCodeHash,
contractAddress,
codeHash,
lcdEndpoint,
chainId,
}));
}

export {
parseDerivativeScrtStakingInfo,
queryDerivativeScrtStakingInfo$,
queryDerivativeScrtStakingInfo,
parseDerivativeScrtFeeInfo,
queryDerivativeScrtFeeInfo$,
queryDerivativeScrtFeeInfo,
parseDerivativeScrtAllInfo,
queryDerivativeScrtAllInfo$,
queryDerivativeScrtAllInfo,
};
1 change: 1 addition & 0 deletions src/contracts/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './batchQuery';
export * from './oracle';
export * from './snip20';
export * from './swap';
export * from './derivativeScrt';
export * from './derivativeShd';
14 changes: 7 additions & 7 deletions src/test/mocks/derivativeScrt/stakingInfoResponseParsed.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"communityRewards": 22.865023,
"communityRewards": "22.865023",
"exchangeRate": 3.932046,
"nextUnbondingBatchEstimatedTime": 1695844838000,
"nextUnboundAmount": 0,
"supply": 7.8,
"nextUnboundAmount": "0",
"supply": "7.8",
"validators": [
{
"validator": "secretvaloper14y56hayzwrf8c24g8hzk7h9ge0ax7g80tqaf32",
"validatorAddress": "secretvaloper14y56hayzwrf8c24g8hzk7h9ge0ax7g80tqaf32",
"weight": 16
},
{
"validator": "secretvaloper1gutgtpw0caqfsp8ja0r5yecv8jxz2y8vxxa9mw",
"validatorAddress": "secretvaloper1gutgtpw0caqfsp8ja0r5yecv8jxz2y8vxxa9mw",
"weight": 17
},
{
"validator": "secretvaloper1lgqd22pd0p7uezjrhukkslml4d5czqszvz8gkc",
"validatorAddress": "secretvaloper1lgqd22pd0p7uezjrhukkslml4d5czqszvz8gkc",
"weight": 16
},
{
"validator": "secretvaloper1wmc9e4552x4haktppy4nrknkdv8hhtm9talhqu",
"validatorAddress": "secretvaloper1wmc9e4552x4haktppy4nrknkdv8hhtm9talhqu",
"weight": 17
}
]
Expand Down
2 changes: 2 additions & 0 deletions src/types/contracts/derivativeScrt/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './model';
export * from './response';
Loading

0 comments on commit 3b9a0a7

Please sign in to comment.