From 3b9a0a74ec621d094afee3c9843ea8a984be06ce Mon Sep 17 00:00:00 2001 From: SissonJ Date: Tue, 12 Mar 2024 11:38:20 -0500 Subject: [PATCH] feat: added a batch query and changed some type names --- src/contracts/services/derivativeScrt.test.ts | 73 ++++++++- src/contracts/services/derivativeScrt.ts | 145 ++++++++++++++++-- src/contracts/services/index.ts | 1 + .../stakingInfoResponseParsed.json | 14 +- src/types/contracts/derivativeScrt/index.ts | 2 + src/types/contracts/derivativeScrt/model.ts | 34 ++-- .../contracts/derivativeScrt/response.ts | 14 +- src/types/contracts/index.ts | 1 + 8 files changed, 239 insertions(+), 45 deletions(-) create mode 100644 src/types/contracts/derivativeScrt/index.ts diff --git a/src/contracts/services/derivativeScrt.test.ts b/src/contracts/services/derivativeScrt.test.ts index 6efd142..5d4c86a 100644 --- a/src/contracts/services/derivativeScrt.test.ts +++ b/src/contracts/services/derivativeScrt.test.ts @@ -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()); @@ -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); }); @@ -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; }, }); @@ -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); }); @@ -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; }, }); @@ -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, + }); +}); diff --git a/src/contracts/services/derivativeScrt.ts b/src/contracts/services/derivativeScrt.ts index 0646c09..411c4b3 100644 --- a/src/contracts/services/derivativeScrt.ts +++ b/src/contracts/services/derivativeScrt.ts @@ -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; @@ -27,8 +33,8 @@ 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, @@ -36,15 +42,20 @@ function parseDerivativeScrtStakingInfo( 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, }; @@ -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(), ); @@ -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 */ @@ -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(), ); @@ -152,6 +186,80 @@ 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$, @@ -159,4 +267,7 @@ export { parseDerivativeScrtFeeInfo, queryDerivativeScrtFeeInfo$, queryDerivativeScrtFeeInfo, + parseDerivativeScrtAllInfo, + queryDerivativeScrtAllInfo$, + queryDerivativeScrtAllInfo, }; diff --git a/src/contracts/services/index.ts b/src/contracts/services/index.ts index b2607c4..b74164d 100644 --- a/src/contracts/services/index.ts +++ b/src/contracts/services/index.ts @@ -2,4 +2,5 @@ export * from './batchQuery'; export * from './oracle'; export * from './snip20'; export * from './swap'; +export * from './derivativeScrt'; export * from './derivativeShd'; diff --git a/src/test/mocks/derivativeScrt/stakingInfoResponseParsed.json b/src/test/mocks/derivativeScrt/stakingInfoResponseParsed.json index 4e72d35..ad7ee0f 100644 --- a/src/test/mocks/derivativeScrt/stakingInfoResponseParsed.json +++ b/src/test/mocks/derivativeScrt/stakingInfoResponseParsed.json @@ -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 } ] diff --git a/src/types/contracts/derivativeScrt/index.ts b/src/types/contracts/derivativeScrt/index.ts new file mode 100644 index 0000000..ed9aa71 --- /dev/null +++ b/src/types/contracts/derivativeScrt/index.ts @@ -0,0 +1,2 @@ +export * from './model'; +export * from './response'; diff --git a/src/types/contracts/derivativeScrt/model.ts b/src/types/contracts/derivativeScrt/model.ts index 7cbc06d..a8785fd 100644 --- a/src/types/contracts/derivativeScrt/model.ts +++ b/src/types/contracts/derivativeScrt/model.ts @@ -1,20 +1,36 @@ -import { StakingDerivativesValidator } from './response'; +type DerivativeScrtValidator = { + validatorAddress: string, + weight: number; +} -type StakingDerivativesInfo = { - validators: StakingDerivativesValidator[], - supply: number, +type DerivativeScrtStakingInfo = { + validators: DerivativeScrtValidator[], + supply: string, exchangeRate: number, - communityRewards: number, - nextUnboundAmount: number, + communityRewards: string, + nextUnboundAmount: string, nextUnbondingBatchEstimatedTime: number, } -type StakingDerivativesFee = { +type DerivativeScrtFeeInfo = { + depositFee: number, + withdrawFee: number, +} + +type DerivativeScrtInfo = { + validators: DerivativeScrtValidator[], + supply: string, + exchangeRate: number, + communityRewards: string, + nextUnboundAmount: string, + nextUnbondingBatchEstimatedTime: number, depositFee: number, withdrawFee: number, } export type { - StakingDerivativesInfo, - StakingDerivativesFee, + DerivativeScrtValidator, + DerivativeScrtStakingInfo, + DerivativeScrtFeeInfo, + DerivativeScrtInfo, }; diff --git a/src/types/contracts/derivativeScrt/response.ts b/src/types/contracts/derivativeScrt/response.ts index 176d224..2e420c8 100644 --- a/src/types/contracts/derivativeScrt/response.ts +++ b/src/types/contracts/derivativeScrt/response.ts @@ -1,9 +1,9 @@ -type StakingDerivativesValidator = { +type DerivativeScrtValidatorResponse = { validator: string, weight: number, } -type StakingDerivativesInfoResponse = { +type DerivativeScrtStakingInfoResponse = { staking_info: { available_scrt: string, batch_unbond_in_progress: boolean, @@ -16,11 +16,11 @@ type StakingDerivativesInfoResponse = { unbond_amount_of_next_batch: string, unbonding_batch_interval: number, unbonding_time: number, - validators: StakingDerivativesValidator[], + validators: DerivativeScrtValidatorResponse[], }, }; -type StakingDerivativesFeesResponse = { +type DerivativeScrtFeeInfoResponse = { fee_info: { fee_collector: string, deposit: number, @@ -29,7 +29,7 @@ type StakingDerivativesFeesResponse = { } export type { - StakingDerivativesValidator, - StakingDerivativesInfoResponse, - StakingDerivativesFeesResponse, + DerivativeScrtValidatorResponse, + DerivativeScrtStakingInfoResponse, + DerivativeScrtFeeInfoResponse, }; diff --git a/src/types/contracts/index.ts b/src/types/contracts/index.ts index dc286ca..5af7c35 100644 --- a/src/types/contracts/index.ts +++ b/src/types/contracts/index.ts @@ -3,4 +3,5 @@ export * from './oracle'; export * from './shared'; export * from './snip20'; export * from './swap'; +export * from './derivativeScrt'; export * from './derivativeShd';