Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch pair config #67

Merged
merged 6 commits into from
Nov 30, 2023
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
5 changes: 5 additions & 0 deletions .changeset/many-worms-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@shadeprotocol/shadejs": patch
---

Batch Pair Config Queries
134 changes: 131 additions & 3 deletions docs/queries/swap.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ console.log(output)
```

## Pair Config
query the configuration of the pair
query the configuration of a single pair

**input**

Expand Down Expand Up @@ -281,14 +281,142 @@ console.log(output)
};
```

## Pairs Info
Query the info for multiple pairs
## Pairs Config
Query the pair config for multiple pairs
::: info
This query uses a smart contract batch query router to allow you to query many pairs in a single http request. This is a highly efficient method of interacting with the chain an minimizes the load on the LCD endpoint.
:::

**input**

```ts
async function batchQueryPairsConfig({
queryRouterContractAddress,
queryRouterCodeHash,
lcdEndpoint,
chainId,
pairsContracts,
}:{
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
lcdEndpoint?: string,
chainId?: string,
pairsContracts: Contract[]
}): Promise<BatchPairsConfig>
```

**output**

```ts
type BatchPairsConfig = BatchPairConfig[]

type BatchPairConfig = {
pairContractAddress: string,
pairConfig: PairConfig,
}

type CustomFee = {
daoFee: number,
lpFee: number,
}

type PairConfig = {
factoryContract: Contract | null,
lpTokenContract: Contract | null,
stakingContract: Contract | null,
token0Contract: Contract,
token1Contract: Contract,
isStable: boolean,
fee: CustomFee | null,
}

```

**example use**

```ts
const output = await batchQueryPairsConfig({
queryRouterContractAddress: '[QUERY_ROUTER_CONTRACT_ADDRESS]',
queryRouterCodeHash: '[QUERY_ROUTER_CODE_HASH]',
pairsContracts: [{
address: '[PAIR_1_ADDRESS]',
codeHash: '[PAIR_1_CODE_HASH]',
},
{
address: '[PAIR_2_ADDRESS]',
codeHash: '[PAIR_2_CODE_HASH]',
}]
})
console.log(output)
```
***console***
```md
[
{
"pairContractAddress": "secret1qyt4l47yq3x43ezle4nwlh5q0sn6f9sesat7ap",
"pairConfig": {
"factoryContract": {
"address": "secret1ja0hcwvy76grqkpgwznxukgd7t8a8anmmx05pp",
"codeHash": "2ad4ed2a4a45fd6de3daca9541ba82c26bb66c76d1c3540de39b509abd26538e"
},
"lpTokenContract": {
"address": "secret10egcg03euavu336fzed87m4zdx8jkgzzz7zgmh",
"codeHash": "b0c2048d28a0ca0b92274549b336703622ecb24a8c21f417e70c03aa620fcd7b"
},
"stakingContract": {
"address": "secret1vgtmfvzdn7ztn7kcrqd7p6f2z97wvauavp3udh",
"codeHash": "a83f0fdc6e5bcdb1f59e39200a084401309fc5338dbb2e54a2bcdc08fa3eaf49"
},
"token0Contract": {
"address": "secret153wu605vvp934xhd4k9dtd640zsep5jkesstdm",
"codeHash": "638a3e1d50175fbcb8373cf801565283e3eb23d88a9b7b7f99fcc5eb1e6b561e"
},
"token1Contract": {
"address": "secret1k6u0cy4feepm6pehnz804zmwakuwdapm69tuc4",
"codeHash": "f6be719b3c6feb498d3554ca0398eb6b7e7db262acb33f84a8f12106da6bbb09"
},
"isStable": false,
"fee": null
}
},
{
"pairContractAddress": "secret1l34fyc9g23fnlk896693nw57phevnyha7pt6gj",
"pairConfig": {
"factoryContract": {
"address": "secret1ja0hcwvy76grqkpgwznxukgd7t8a8anmmx05pp",
"codeHash": "2ad4ed2a4a45fd6de3daca9541ba82c26bb66c76d1c3540de39b509abd26538e"
},
"lpTokenContract": {
"address": "secret1zw9gwj6kx7vd3xax7wf45y6dmawkj3pd3dk7wt",
"codeHash": "b0c2048d28a0ca0b92274549b336703622ecb24a8c21f417e70c03aa620fcd7b"
},
"stakingContract": {
"address": "secret13j4n5gj8857h2j4cnempdkfygrw9snasx4yzw2",
"codeHash": "a83f0fdc6e5bcdb1f59e39200a084401309fc5338dbb2e54a2bcdc08fa3eaf49"
},
"token0Contract": {
"address": "secret1fl449muk5yq8dlad7a22nje4p5d2pnsgymhjfd",
"codeHash": "638a3e1d50175fbcb8373cf801565283e3eb23d88a9b7b7f99fcc5eb1e6b561e"
},
"token1Contract": {
"address": "secret153wu605vvp934xhd4k9dtd640zsep5jkesstdm",
"codeHash": "638a3e1d50175fbcb8373cf801565283e3eb23d88a9b7b7f99fcc5eb1e6b561e"
},
"isStable": false,
"fee": {
"lpFee": 0,
"daoFee": 0.003
}
}
}
]
```

## Pairs Info
Query the info for multiple pairs

**input**

```ts
async function batchQueryPairsInfo({
queryRouterContractAddress,
Expand Down
69 changes: 69 additions & 0 deletions src/contracts/services/swap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ import {
parseSwapResponse,
parseBatchQueryPairInfoResponse,
parseBatchQueryStakingInfoResponse,
parseBatchQueryPairConfigResponse,
batchQueryPairsInfo,
batchQueryPairsInfo$,
batchQueryStakingInfo,
batchQueryStakingInfo$,
batchQueryPairsConfig,
batchQueryPairsConfig$,
} from '~/contracts/services/swap';
import factoryConfigResponse from '~/test/mocks/swap/factoryConfig.json';
import factoryPairsResponse from '~/test/mocks/swap/factoryPairs.json';
Expand All @@ -49,6 +52,8 @@ import { pairsInfoResponseUnparsed } from '~/test/mocks/swap/batchPairsInfoRespo
import { pairsInfoParsed } from '~/test/mocks/swap/batchPairsInfoParsed';
import { batchStakingConfigUnparsed } from '~/test/mocks/swap/batchStakingConfigUnparsed';
import { batchStakingConfigParsed } from '~/test/mocks/swap/batchStakingConfigParsed';
import { batchPairsConfigResponseUnparsed } from '~/test/mocks/swap/batchPairsConfigResponseUnparsed';
import { batchPairsConfigParsed } from '~/test/mocks/swap/batchPairsConfigParsed';

const sendSecretClientContractQuery$ = vi.hoisted(() => vi.fn());
const batchQuery$ = vi.hoisted(() => vi.fn());
Expand Down Expand Up @@ -121,6 +126,12 @@ test('it can parse the batch staking response', () => {
)).toStrictEqual(batchStakingConfigParsed);
});

test('it can parse the batch pair config response', () => {
expect(parseBatchQueryPairConfigResponse(
batchPairsConfigResponseUnparsed,
)).toStrictEqual(batchPairsConfigParsed);
});

test('it can call the query factory config service', async () => {
// observables function
sendSecretClientContractQuery$.mockReturnValueOnce(of(factoryConfigResponse));
Expand Down Expand Up @@ -354,3 +365,61 @@ test('it can call the batch staking info query service', async () => {
});
expect(response).toStrictEqual(batchStakingConfigParsed);
});

test('it can call the batch pair config query service', async () => {
const input = {
queryRouterContractAddress: 'CONTRACT_ADDRESS',
queryRouterCodeHash: 'CODE_HASH',
lcdEndpoint: 'LCD_ENDPOINT',
chainId: 'CHAIN_ID',
pairsContracts: [{
address: 'PAIR_ADDRESS',
codeHash: 'PAIR_CODE_HASH',
}],
};

// observables function
batchQuery$.mockReturnValueOnce(of(batchPairsConfigResponseUnparsed));
let output;
batchQueryPairsConfig$(input).subscribe({
next: (response) => {
output = response;
},
});

expect(batchQuery$).toHaveBeenCalledWith({
contractAddress: input.queryRouterContractAddress,
codeHash: input.queryRouterCodeHash,
lcdEndpoint: input.lcdEndpoint,
chainId: input.chainId,
queries: [{
id: input.pairsContracts[0].address,
contract: {
address: input.pairsContracts[0].address,
codeHash: input.pairsContracts[0].codeHash,
},
queryMsg: 'PAIR_CONFIG_MSG',
}],
});

expect(output).toStrictEqual(batchPairsConfigParsed);

// async/await function
batchQuery$.mockReturnValueOnce(of(batchPairsConfigResponseUnparsed));
const response = await batchQueryPairsConfig(input);
expect(batchQuery$).toHaveBeenCalledWith({
contractAddress: input.queryRouterContractAddress,
codeHash: input.queryRouterCodeHash,
lcdEndpoint: input.lcdEndpoint,
chainId: input.chainId,
queries: [{
id: input.pairsContracts[0].address,
contract: {
address: input.pairsContracts[0].address,
codeHash: input.pairsContracts[0].codeHash,
},
queryMsg: 'PAIR_CONFIG_MSG',
}],
});
expect(response).toStrictEqual(batchPairsConfigParsed);
});
81 changes: 78 additions & 3 deletions src/contracts/services/swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '~/types/contracts/swap/response';
import {
BatchPairsInfo,
BatchPairsConfig,
BatchStakingInfo,
FactoryConfig,
FactoryPairs,
Expand Down Expand Up @@ -148,7 +149,7 @@ function parsePairConfig(response: PairConfigResponse): PairConfig {
isStable: pair[2],
fee: customFee ? {
lpFee: customFee.lp_fee.nom / customFee.lp_fee.denom,
daoFee: customFee.lp_fee.nom / customFee.lp_fee.denom,
daoFee: customFee.shade_dao_fee.nom / customFee.shade_dao_fee.denom,
} : null,
};
}
Expand Down Expand Up @@ -233,6 +234,16 @@ const parseBatchQueryPairInfoResponse = (
pairInfo: parsePairInfo(item.response),
}));

/**
* parses the pair config response from a batch query of
* multiple pair contracts
*/
const parseBatchQueryPairConfigResponse = (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment above the function explaining what it does

response: BatchQueryParsedResponse,
): BatchPairsConfig => response.map((item) => ({
pairContractAddress: item.id as string,
pairConfig: parsePairConfig(item.response),
}));
/**
* parses the single staking info response
*/
Expand Down Expand Up @@ -487,7 +498,7 @@ async function queryPairConfig({
}

/**
* query the pair info for multiple pools at one time
* query the info for multiple pairs at one time
*/
function batchQueryPairsInfo$({
queryRouterContractAddress,
Expand Down Expand Up @@ -523,7 +534,7 @@ function batchQueryPairsInfo$({
}

/**
* query the pair info for multiple pools at one time
* query the info for multiple pairs at one time
*/
async function batchQueryPairsInfo({
queryRouterContractAddress,
Expand All @@ -547,6 +558,67 @@ async function batchQueryPairsInfo({
}));
}

/**
* query the config for multiple pairs at one time
*/
function batchQueryPairsConfig$({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment

queryRouterContractAddress,
queryRouterCodeHash,
lcdEndpoint,
chainId,
pairsContracts,
}:{
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
lcdEndpoint?: string,
chainId?: string,
pairsContracts: Contract[]
}) {
const queries:BatchQuery[] = pairsContracts.map((contract) => ({
id: contract.address,
contract: {
address: contract.address,
codeHash: contract.codeHash,
},
queryMsg: msgQueryPairConfig(),
}));
return batchQuery$({
contractAddress: queryRouterContractAddress,
codeHash: queryRouterCodeHash,
lcdEndpoint,
chainId,
queries,
}).pipe(
map(parseBatchQueryPairConfigResponse),
first(),
);
}

/**
* query the config for multiple pairs at one time
*/
async function batchQueryPairsConfig({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment

queryRouterContractAddress,
queryRouterCodeHash,
lcdEndpoint,
chainId,
pairsContracts,
}:{
queryRouterContractAddress: string,
queryRouterCodeHash?: string,
lcdEndpoint?: string,
chainId?: string,
pairsContracts: Contract[]
}) {
return lastValueFrom(batchQueryPairsConfig$({
queryRouterContractAddress,
queryRouterCodeHash,
lcdEndpoint,
chainId,
pairsContracts,
}));
}

/**
* query the staking info for multiple staking contracts at one time
*/
Expand Down Expand Up @@ -622,9 +694,12 @@ export {
queryPairConfig,
batchQueryPairsInfo$,
batchQueryPairsInfo,
batchQueryPairsConfig$,
batchQueryPairsConfig,
batchQueryStakingInfo$,
batchQueryStakingInfo,
parseSwapResponse,
parseBatchQueryPairInfoResponse,
parseBatchQueryStakingInfoResponse,
parseBatchQueryPairConfigResponse,
};
Loading