Skip to content

Commit

Permalink
Merge pull request #129 from securesecrets/batch-query-block-height-i…
Browse files Browse the repository at this point in the history
…mplementation

feat: batch query block height implementation
  • Loading branch information
AustinWoetzel authored Apr 18, 2024
2 parents 5ac0d42 + e351fa5 commit 32d03ae
Show file tree
Hide file tree
Showing 20 changed files with 110 additions and 12 deletions.
2 changes: 1 addition & 1 deletion docs/contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This page contains a list of deployed contracts.
|-------------------- |----------------------------------------------- |------------------------------------------------------------------ |
| ShadeSwap Factory | secret1ja0hcwvy76grqkpgwznxukgd7t8a8anmmx05pp | 2ad4ed2a4a45fd6de3daca9541ba82c26bb66c76d1c3540de39b509abd26538e |
| ShadeSwap Router | secret1pjhdug87nxzv0esxasmeyfsucaj98pw4334wyc | 448e3f6d801e453e838b7a5fbaa4dd93b84d0f1011245f0d5745366dadaf3e85 |
| Batch Query Router | secret17gnlxnwux0szd7qhl90ym8lw22qvedjz4v09dm | 72a09535b77b76862f7b568baf1ddbe158a2e4bbd0f0879c69ada9b398e31c1f |
| Batch Query Router | secret15mkmad8ac036v4nrpcc7nk8wyr578egt077syt | 1c7e86ba4fdb6760e70bf08a7df7f44b53eb0b23290e3e69ca96140810d4f432 |
| Oracle | secret10n2xl5jmez6r9umtdrth78k0vwmce0l5m9f5dm | 32c4710842b97a526c243a68511b15f58d6e72a388af38a7221ff3244c754e91 |
| stkd-scrt | secret1k6u0cy4feepm6pehnz804zmwakuwdapm69tuc4 | f6be719b3c6feb498d3554ca0398eb6b7e7db262acb33f84a8f12106da6bbb09 |
| Shade Staking | secret1y6px5x7jzrk8hyvy67f06ytn8v0jwculypwxws | 2a1ae7fd2be82931cb11d0ce82b2e243507f2006074e2f316da661beb1abe3c3 |
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/services/batchQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ test('it can call the single batch query service and detect query retry limit ex
of(batchPairConfigResponse), // will never reach final case due to retry limit
);

await expect(() => batchQuery(input)).rejects.toThrowError('Reached maximum retry attempts for Stale node error.');
await expect(() => batchQuery(input)).rejects.toThrowError('Reached maximum retry attempts for stale node error.');
});

test('it can call the multi-batch query service on a single batch', async () => {
Expand Down
7 changes: 3 additions & 4 deletions src/contracts/services/batchQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const batchQuerySingleBatch$ = ({
nodeHealthValidationConfig?: NodeHealthValidationConfig,
}) => {
let retryCount = 0;
return of(1).pipe( // empty observable used here so that we can start a data stream
return of(1).pipe( // placeholder observable of(1) used here so that we can start a data stream
// and retry from this level when certain error conditions are reached
switchMap(() => sendSecretClientContractQuery$({
queryMsg: msgBatchQuery(queries),
Expand All @@ -90,8 +90,7 @@ const batchQuerySingleBatch$ = ({
switchMap((response) => {
// create an error if stale node is detected
if (nodeHealthValidationConfig
&& nodeHealthValidationConfig.minBlockHeight
&& response.batch.block_height < nodeHealthValidationConfig.minBlockHeight
&& response.batch.block_height < nodeHealthValidationConfig.minBlockHeight
) {
// callback for when stale node is detected. Useful for error logging.
if (typeof nodeHealthValidationConfig.onStaleNodeDetected === 'function') {
Expand All @@ -112,7 +111,7 @@ const batchQuerySingleBatch$ = ({
// retry the query
return caught;
}
return throwError(() => new Error('Reached maximum retry attempts for Stale node error.'));
return throwError(() => new Error('Reached maximum retry attempts for stale node error.'));
} if (error.message.includes('{wasm contract}')) {
return throwError(() => new Error('{wasm contract} error that typically occurs when batch size is too large and node gas query limits are exceeded. Consider reducing the batch size.'));
}
Expand Down
5 changes: 5 additions & 0 deletions src/contracts/services/derivativeScrt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ const batchQueryResponse = [
{
id: BatchRouterKeys.STAKING_INFO,
response: stakingInfoResponse,
blockHeight: 1,
},
{
id: BatchRouterKeys.FEE_INFO,
response: feeInfoResponse,
blockHeight: 1,
},
];

Expand Down Expand Up @@ -55,6 +57,7 @@ test('it can parse the batch query resonse', () => {
)).toStrictEqual({
...feeInfoResponseParsed,
...stakingInfoResponseParsed,
blockHeight: 1,
});
});

Expand All @@ -78,6 +81,7 @@ test('it can call the query all info service', async () => {
expect(output).toStrictEqual({
...feeInfoResponseParsed,
...stakingInfoResponseParsed,
blockHeight: 1,
});

// async/await function
Expand All @@ -87,5 +91,6 @@ test('it can call the query all info service', async () => {
expect(output2).toStrictEqual({
...feeInfoResponseParsed,
...stakingInfoResponseParsed,
blockHeight: 1,
});
});
11 changes: 10 additions & 1 deletion src/contracts/services/derivativeScrt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
BatchQueryParsedResponse,
BatchQueryParsedResponseItem,
} from '~/types/contracts/batchQuery/model';
import { NodeHealthValidationConfig } from '~/types';
import { batchQuery$ } from './batchQuery';

// Contract returns price as a rate of stkd-SCRT/SCRT with 6 decimals
Expand Down Expand Up @@ -89,6 +90,9 @@ const parseDerivativeScrtInfo = (
return {
...parseDerivativeScrtStakingInfo(stakingInfoResponse.response),
...parseDerivativeScrtFeeInfo(feeInfoResponse.response),
// we are assuming that both responses will come from the same block
// because they are queried in the same batch.
blockHeight: stakingInfoResponse.blockHeight,
};
};

Expand All @@ -107,6 +111,7 @@ const queryDerivativeScrtInfo$ = ({
lcdEndpoint,
chainId,
queryTimeSeconds,
nodeHealthValidationConfig,
}: {
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
Expand All @@ -115,6 +120,7 @@ const queryDerivativeScrtInfo$ = ({
lcdEndpoint?: string,
chainId?: string,
queryTimeSeconds?: number,
nodeHealthValidationConfig?: NodeHealthValidationConfig,
}) => batchQuery$({
queries: [
{
Expand All @@ -134,13 +140,13 @@ const queryDerivativeScrtInfo$ = ({
codeHash,
},
queryMsg: msgQueryScrtDerivativeFees(),

},
],
lcdEndpoint,
contractAddress: queryRouterContractAddress,
codeHash: queryRouterCodeHash,
chainId,
nodeHealthValidationConfig,
}).pipe(
map((response: any) => parseDerivativeScrtInfo(response as BatchQueryParsedResponse)),
first(),
Expand All @@ -161,6 +167,7 @@ async function queryDerivativeScrtInfo({
lcdEndpoint,
chainId,
queryTimeSeconds,
nodeHealthValidationConfig,
}: {
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
Expand All @@ -169,6 +176,7 @@ async function queryDerivativeScrtInfo({
lcdEndpoint?: string,
chainId?: string,
queryTimeSeconds?: number,
nodeHealthValidationConfig?: NodeHealthValidationConfig,
}) {
return lastValueFrom(queryDerivativeScrtInfo$({
queryRouterContractAddress,
Expand All @@ -178,6 +186,7 @@ async function queryDerivativeScrtInfo({
lcdEndpoint,
chainId,
queryTimeSeconds,
nodeHealthValidationConfig,
}));
}

Expand Down
13 changes: 11 additions & 2 deletions src/contracts/services/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,22 @@ import {
BatchItemResponseStatus,
BatchQueryParams,
BatchQueryParsedResponse,
NodeHealthValidationConfig,
} from '~/types';
import { batchQuery$ } from './batchQuery';

/**
* Parses the contract price query into the app data model
*/
const parsePriceFromContract = (response: OraclePriceResponse): ParsedOraclePriceResponse => ({
const parsePriceFromContract = (
response: OraclePriceResponse,
blockHeight?: number,
): ParsedOraclePriceResponse => ({
oracleKey: response.key,
rate: response.data.rate,
lastUpdatedBase: response.data.last_updated_base,
lastUpdatedQuote: response.data.last_updated_quote,
blockHeight,
});

/**
Expand Down Expand Up @@ -74,12 +79,13 @@ const parseBatchQueryIndividualPrices = (
type: errorType,
msg: item.response,
},
blockHeight: item.blockHeight,
},
};
}
return {
...prev,
[item.id as string]: parsePriceFromContract(item.response),
[item.id as string]: parsePriceFromContract(item.response, item.blockHeight),
};
}, {});

Expand Down Expand Up @@ -202,6 +208,7 @@ function batchQueryIndividualPrices$({
oracleContractAddress,
oracleCodeHash,
oracleKeys,
nodeHealthValidationConfig,
}:{
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
Expand All @@ -210,6 +217,7 @@ function batchQueryIndividualPrices$({
oracleContractAddress: string
oracleCodeHash: string
oracleKeys: string[],
nodeHealthValidationConfig?: NodeHealthValidationConfig,
}) {
const queries:BatchQueryParams[] = oracleKeys.map((key) => ({
id: key,
Expand All @@ -225,6 +233,7 @@ function batchQueryIndividualPrices$({
lcdEndpoint,
chainId,
queries,
nodeHealthValidationConfig,
}).pipe(
map(parseBatchQueryIndividualPrices),
first(),
Expand Down
8 changes: 8 additions & 0 deletions src/contracts/services/snip20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
Contract,
BatchQueryParams,
BatchQueryParsedResponse,
NodeHealthValidationConfig,
} from '~/types';
import { batchQuery$ } from './batchQuery';

Expand All @@ -35,6 +36,7 @@ const parseBatchQueryTokensInfo = (
): BatchTokensInfo => response.map((item) => ({
tokenContractAddress: item.id as string,
tokenInfo: parseTokenInfo(item.response),
blockHeight: item.blockHeight,
}));

const parseBalance = (response: BalanceResponse): string => response.balance.amount;
Expand Down Expand Up @@ -94,12 +96,14 @@ function batchQuerySnip20TokensInfo$({
lcdEndpoint,
chainId,
tokenContracts,
nodeHealthValidationConfig,
}:{
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
lcdEndpoint?: string,
chainId?: string,
tokenContracts: Contract[]
nodeHealthValidationConfig?: NodeHealthValidationConfig,
}) {
const queries:BatchQueryParams[] = tokenContracts.map((contract) => ({
id: contract.address,
Expand All @@ -115,6 +119,7 @@ function batchQuerySnip20TokensInfo$({
lcdEndpoint,
chainId,
queries,
nodeHealthValidationConfig,
}).pipe(
map(parseBatchQueryTokensInfo),
first(),
Expand All @@ -130,19 +135,22 @@ function batchQuerySnip20TokensInfo({
lcdEndpoint,
chainId,
tokenContracts,
nodeHealthValidationConfig,
}:{
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
lcdEndpoint?: string,
chainId?: string,
tokenContracts: Contract[]
nodeHealthValidationConfig?: NodeHealthValidationConfig,
}) {
return lastValueFrom(batchQuerySnip20TokensInfo$({
queryRouterContractAddress,
queryRouterCodeHash,
lcdEndpoint,
chainId,
tokenContracts,
nodeHealthValidationConfig,
}));
}

Expand Down
Loading

0 comments on commit 32d03ae

Please sign in to comment.