Mp 2836 implement pagination to the batched smart contract queries (#301)

* feat: batch and paginate oracle prices

* fixes and improvements

* feat: complete batching mechanism and its implementation

* fix: getVaultConfigs usage

* fix: linting

* feat: remove hardcoded mars decimals
This commit is contained in:
Yusuf Seyrek 2023-07-17 12:01:00 +03:00 committed by GitHub
parent 48d07173fb
commit 49e7778b1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 832 additions and 349 deletions

View File

@ -42,5 +42,5 @@ NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmos
# CHARTING_LIBRARY_USERNAME="username_with_access_to_charting_library"
# CHARTING_LIBRARY_ACCESS_TOKEN="access_token_with_access_to_charting_library"
# CHARTING_LIBRARY_REPOSITORY="username/charting_library"
# NEXT_PUBLIC_PYTH_ENDPOINT=https://xc-mainnet.pyth.network/api/
# NEXT_PUBLIC_PYTH_ENDPOINT=https://xc-mainnet.pyth.network/api
# NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/

View File

@ -4,7 +4,7 @@ import { ENV } from 'constants/env'
import { MarsAccountNftQueryClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
import { MarsCreditManagerQueryClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
import { MarsIncentivesQueryClient } from 'types/generated/mars-incentives/MarsIncentives.client'
import { MarsMockOracleQueryClient } from 'types/generated/mars-mock-oracle/MarsMockOracle.client'
import { MarsOracleOsmosisQueryClient } from 'types/generated/mars-oracle-osmosis/MarsOracleOsmosis.client'
import { MarsMockRedBankQueryClient } from 'types/generated/mars-mock-red-bank/MarsMockRedBank.client'
import { MarsMockVaultQueryClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
import { MarsParamsQueryClient } from 'types/generated/mars-params/MarsParams.client'
@ -12,7 +12,7 @@ import { MarsParamsQueryClient } from 'types/generated/mars-params/MarsParams.cl
let _cosmWasmClient: CosmWasmClient
let _accountNftQueryClient: MarsAccountNftQueryClient
let _creditManagerQueryClient: MarsCreditManagerQueryClient
let _oracleQueryClient: MarsMockOracleQueryClient
let _oracleQueryClient: MarsOracleOsmosisQueryClient
let _redBankQueryClient: MarsMockRedBankQueryClient
let _paramsQueryClient: MarsParamsQueryClient
let _incentivesQueryClient: MarsIncentivesQueryClient
@ -75,7 +75,7 @@ const getOracleQueryClient = async () => {
try {
if (!_oracleQueryClient) {
const client = await getClient()
_oracleQueryClient = new MarsMockOracleQueryClient(client, ENV.ADDRESS_ORACLE)
_oracleQueryClient = new MarsOracleOsmosisQueryClient(client, ENV.ADDRESS_ORACLE)
}
return _oracleQueryClient

View File

@ -6,7 +6,7 @@ import { SECONDS_IN_A_YEAR } from 'utils/constants'
import getPrice from 'api/prices/getPrice'
import getMarsPrice from 'api/prices/getMarsPrice'
import { ASSETS } from 'constants/assets'
import { byDenom } from 'utils/array'
import { byDenom, bySymbol } from 'utils/array'
export default async function calculateAssetIncentivesApy(
denom: string,
@ -16,17 +16,15 @@ export default async function calculateAssetIncentivesApy(
if (!assetIncentive) return null
const [marketLiquidityAmount, assetPriceResponse, marsPrice] = await Promise.all([
const [marketLiquidityAmount, assetPrice, marsPrice] = await Promise.all([
getUnderlyingLiquidityAmount(market),
getPrice(denom),
getMarsPrice(),
])
const assetDecimals = (ASSETS.find(byDenom(denom)) as Asset).decimals
const marsDecimals = 6,
priceFeedDecimals = 6
const marsDecimals = (ASSETS.find(bySymbol('MARS')) as Asset).decimals
const assetPrice = BN(assetPriceResponse).shiftedBy(assetDecimals - priceFeedDecimals)
const marketLiquidityValue = BN(marketLiquidityAmount)
.shiftedBy(-assetDecimals)
.multipliedBy(assetPrice)

View File

@ -1,6 +1,5 @@
import { ENV } from 'constants/env'
import { resolveMarketResponse } from 'utils/resolvers'
import { getClient, getRedBankQueryClient } from 'api/cosmwasm-client'
import { getRedBankQueryClient } from 'api/cosmwasm-client'
export default async function getMarket(denom: string): Promise<Market> {
try {

View File

@ -1,12 +1,20 @@
import { getEnabledMarketAssets } from 'utils/assets'
import getMarket from 'api/markets/getMarket'
import { getRedBankQueryClient } from 'api/cosmwasm-client'
import iterateContractQuery from 'utils/iterateContractQuery'
import { byDenom } from 'utils/array'
import { resolveMarketResponse } from 'utils/resolvers'
import { Market as RedBankMarket } from 'types/generated/mars-mock-red-bank/MarsMockRedBank.types'
export default async function getMarkets(): Promise<Market[]> {
try {
const client = await getRedBankQueryClient()
const enabledAssets = getEnabledMarketAssets()
const marketQueries = enabledAssets.map((asset) => getMarket(asset.denom))
return await Promise.all(marketQueries)
const markets = await iterateContractQuery(client.markets)
return enabledAssets.map((asset) =>
resolveMarketResponse(markets.find(byDenom(asset.denom)) as RedBankMarket),
)
} catch (ex) {
throw ex
}

View File

@ -1,22 +1,26 @@
import { getOracleQueryClient } from 'api/cosmwasm-client'
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
import { BNCoin } from 'types/classes/BNCoin'
import { PriceResponse } from 'types/generated/mars-oracle-osmosis/MarsOracleOsmosis.types'
import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers'
import iterateContractQuery from 'utils/iterateContractQuery'
export default async function getOraclePrices(...assets: Asset[]): Promise<BNCoin[]> {
try {
const baseDecimals = 6
if (!assets.length) return []
const oracleQueryClient = await getOracleQueryClient()
const priceResults = await iterateContractQuery(oracleQueryClient.prices)
const priceQueries = assets.map((asset) =>
oracleQueryClient.price({
denom: asset.denom,
}),
return assets.map((asset) => {
const priceResponse = priceResults.find(byDenom(asset.denom)) as PriceResponse
const decimalDiff = asset.decimals - PRICE_ORACLE_DECIMALS
return BNCoin.fromDenomAndBigNumber(
asset.denom,
BN(priceResponse.price).shiftedBy(decimalDiff),
)
const priceResults = await Promise.all(priceQueries)
return priceResults.map(({ denom, price }, index) => {
const decimalDiff = assets[index].decimals - baseDecimals
return BNCoin.fromDenomAndBigNumber(denom, BN(price).shiftedBy(decimalDiff))
})
} catch (ex) {
throw ex

View File

@ -4,6 +4,7 @@ import { byDenom } from 'utils/array'
import getPythPrice from 'api/prices/getPythPrices'
import getPoolPrice from 'api/prices/getPoolPrice'
import { BN } from 'utils/helpers'
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
export default async function getPrice(denom: string): Promise<BigNumber> {
try {
@ -16,8 +17,9 @@ export default async function getPrice(denom: string): Promise<BigNumber> {
if (asset.hasOraclePrice) {
const oracleQueryClient = await getOracleQueryClient()
const priceResponse = await oracleQueryClient.price({ denom: asset.denom })
const decimalDiff = asset.decimals - PRICE_ORACLE_DECIMALS
return BN(priceResponse.price)
return BN(priceResponse.price).shiftedBy(decimalDiff)
}
if (asset.poolId) {

View File

@ -1,27 +1,13 @@
import { getParamsQueryClient } from 'api/cosmwasm-client'
import { ENV } from 'constants/env'
import { VaultConfigBaseForString } from 'types/generated/mars-params/MarsParams.types'
import { VaultConfigBaseForAddr } from 'types/generated/mars-params/MarsParams.types'
import iterateContractQuery from 'utils/iterateContractQuery'
export const getVaultConfigs = async (
vaultConfigs: VaultConfigBaseForString[],
startAfter?: string,
): Promise<VaultConfigBaseForString[]> => {
if (!ENV.ADDRESS_PARAMS) return []
const paramsQueryClient = await getParamsQueryClient()
export const getVaultConfigs = async (): Promise<VaultConfigBaseForAddr[]> => {
try {
const batch = await paramsQueryClient.allVaultConfigs({
limit: 4,
startAfter,
})
vaultConfigs.push(...batch)
if (batch.length === 4) {
return await getVaultConfigs(vaultConfigs, batch[batch.length - 1].addr)
}
return vaultConfigs
} catch {
return vaultConfigs
const paramsQueryClient = await getParamsQueryClient()
return await iterateContractQuery(paramsQueryClient.allVaultConfigs, 'addr')
} catch (ex) {
console.error(ex)
throw ex
}
}

View File

@ -7,7 +7,7 @@ import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
import { BN } from 'utils/helpers'
export default async function getVaults(): Promise<Vault[]> {
const vaultConfigs = await getVaultConfigs([])
const vaultConfigs = await getVaultConfigs()
const $vaultUtilizations = getVaultUtilizations(vaultConfigs)
const $aprs = getAprs()
const vaultMetaDatas = ENV.NETWORK === 'testnet' ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA

View File

@ -37,13 +37,13 @@ function Benefits({ benefits }: BenefitsProps) {
export default function TermsOfService() {
const { connect } = useWalletManager()
const [hasAgreedToTerms, setHasAgreedToTerms] = useLocalStorage(TERMS_OF_SERVICE_KEY, false)
const [_, setHasAgreedToTerms] = useLocalStorage(TERMS_OF_SERVICE_KEY, false)
const handleAgreeTermsOfService = useCallback(() => {
useStore.setState({ showTermsOfService: false, isFocusMode: false })
setHasAgreedToTerms(true)
connect()
}, [connect, hasAgreedToTerms, setHasAgreedToTerms])
}, [connect, setHasAgreedToTerms])
return (
<div className='relative flex h-full w-full items-center justify-center'>

2
src/constants/query.ts Normal file
View File

@ -0,0 +1,2 @@
export const ITEM_LIMIT_PER_QUERY = 10
export const PRICE_ORACLE_DECIMALS = 6

View File

@ -1,99 +0,0 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.1.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { CosmWasmClient, ExecuteResult, SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { Coin, StdFee } from '@cosmjs/amino'
import {
CoinPrice,
Decimal,
ExecuteMsg,
InstantiateMsg,
PriceResponse,
QueryMsg,
} from './MarsMockOracle.types'
export interface MarsMockOracleReadOnlyInterface {
contractAddress: string
price: ({ denom }: { denom: string }) => Promise<PriceResponse>
}
export class MarsMockOracleQueryClient implements MarsMockOracleReadOnlyInterface {
client: CosmWasmClient
contractAddress: string
constructor(client: CosmWasmClient, contractAddress: string) {
this.client = client
this.contractAddress = contractAddress
this.price = this.price.bind(this)
}
price = async ({ denom }: { denom: string }): Promise<PriceResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
price: {
denom,
},
})
}
}
export interface MarsMockOracleInterface extends MarsMockOracleReadOnlyInterface {
contractAddress: string
sender: string
changePrice: (
{
denom,
price,
}: {
denom: string
price: Decimal
},
fee?: number | StdFee | 'auto',
memo?: string,
_funds?: Coin[],
) => Promise<ExecuteResult>
}
export class MarsMockOracleClient
extends MarsMockOracleQueryClient
implements MarsMockOracleInterface
{
client: SigningCosmWasmClient
sender: string
contractAddress: string
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress)
this.client = client
this.sender = sender
this.contractAddress = contractAddress
this.changePrice = this.changePrice.bind(this)
}
changePrice = async (
{
denom,
price,
}: {
denom: string
price: Decimal
},
fee: number | StdFee | 'auto' = 'auto',
memo?: string,
_funds?: Coin[],
): Promise<ExecuteResult> => {
return await this.client.execute(
this.sender,
this.contractAddress,
{
change_price: {
denom,
price,
},
},
fee,
memo,
_funds,
)
}
}

View File

@ -1,72 +0,0 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.1.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { Coin } from '@cosmjs/amino'
import { MsgExecuteContractEncodeObject } from '@cosmjs/cosmwasm-stargate'
import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx'
import { toUtf8 } from '@cosmjs/encoding'
import {
CoinPrice,
Decimal,
ExecuteMsg,
InstantiateMsg,
PriceResponse,
QueryMsg,
} from './MarsMockOracle.types'
export interface MarsMockOracleMessage {
contractAddress: string
sender: string
changePrice: (
{
denom,
price,
}: {
denom: string
price: Decimal
},
_funds?: Coin[],
) => MsgExecuteContractEncodeObject
}
export class MarsMockOracleMessageComposer implements MarsMockOracleMessage {
sender: string
contractAddress: string
constructor(sender: string, contractAddress: string) {
this.sender = sender
this.contractAddress = contractAddress
this.changePrice = this.changePrice.bind(this)
}
changePrice = (
{
denom,
price,
}: {
denom: string
price: Decimal
},
_funds?: Coin[],
): MsgExecuteContractEncodeObject => {
return {
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
value: MsgExecuteContract.fromPartial({
sender: this.sender,
contract: this.contractAddress,
msg: toUtf8(
JSON.stringify({
change_price: {
denom,
price,
},
}),
),
funds: _funds,
}),
}
}
}

View File

@ -1,85 +0,0 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.1.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { useMutation, UseMutationOptions, useQuery, UseQueryOptions } from '@tanstack/react-query'
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
import { Coin, StdFee } from '@cosmjs/amino'
import {
CoinPrice,
Decimal,
ExecuteMsg,
InstantiateMsg,
PriceResponse,
QueryMsg,
} from './MarsMockOracle.types'
import { MarsMockOracleClient, MarsMockOracleQueryClient } from './MarsMockOracle.client'
export const marsMockOracleQueryKeys = {
contract: [
{
contract: 'marsMockOracle',
},
] as const,
address: (contractAddress: string | undefined) =>
[{ ...marsMockOracleQueryKeys.contract[0], address: contractAddress }] as const,
price: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
[{ ...marsMockOracleQueryKeys.address(contractAddress)[0], method: 'price', args }] as const,
}
export interface MarsMockOracleReactQuery<TResponse, TData = TResponse> {
client: MarsMockOracleQueryClient | undefined
options?: Omit<
UseQueryOptions<TResponse, Error, TData>,
"'queryKey' | 'queryFn' | 'initialData'"
> & {
initialData?: undefined
}
}
export interface MarsMockOraclePriceQuery<TData>
extends MarsMockOracleReactQuery<PriceResponse, TData> {
args: {
denom: string
}
}
export function useMarsMockOraclePriceQuery<TData = PriceResponse>({
client,
args,
options,
}: MarsMockOraclePriceQuery<TData>) {
return useQuery<PriceResponse, Error, TData>(
marsMockOracleQueryKeys.price(client?.contractAddress, args),
() =>
client
? client.price({
denom: args.denom,
})
: Promise.reject(new Error('Invalid client')),
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
)
}
export interface MarsMockOracleChangePriceMutation {
client: MarsMockOracleClient
msg: {
denom: string
price: Decimal
}
args?: {
fee?: number | StdFee | 'auto'
memo?: string
funds?: Coin[]
}
}
export function useMarsMockOracleChangePriceMutation(
options?: Omit<
UseMutationOptions<ExecuteResult, Error, MarsMockOracleChangePriceMutation>,
'mutationFn'
>,
) {
return useMutation<ExecuteResult, Error, MarsMockOracleChangePriceMutation>(
({ client, msg, args: { fee, memo, funds } = {} }) => client.changePrice(msg, fee, memo, funds),
options,
)
}

View File

@ -1,27 +0,0 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.1.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
export type Decimal = string
export interface InstantiateMsg {
prices: CoinPrice[]
}
export interface CoinPrice {
denom: string
price: Decimal
}
export type ExecuteMsg = {
change_price: CoinPrice
}
export type QueryMsg = {
price: {
denom: string
}
}
export interface PriceResponse {
denom: string
price: Decimal
}

View File

@ -1,14 +0,0 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.1.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import * as _12 from './MarsMockOracle.types'
import * as _13 from './MarsMockOracle.client'
import * as _14 from './MarsMockOracle.message-composer'
import * as _15 from './MarsMockOracle.react-query'
export namespace contracts {
export const MarsMockOracle = { ..._12, ..._13, ..._14, ..._15 }
}

View File

@ -0,0 +1,260 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'
import { Coin, StdFee } from '@cosmjs/amino'
import {
InstantiateMsg,
ExecuteMsg,
OsmosisPriceSourceForString,
Decimal,
Downtime,
Identifier,
OwnerUpdate,
DowntimeDetector,
GeometricTwap,
RedemptionRateForString,
QueryMsg,
ConfigResponse,
PriceResponse,
PriceSourceResponseForString,
ArrayOfPriceSourceResponseForString,
ArrayOfPriceResponse,
} from './MarsOracleOsmosis.types'
export interface MarsOracleOsmosisReadOnlyInterface {
contractAddress: string
config: () => Promise<ConfigResponse>
priceSource: ({ denom }: { denom: string }) => Promise<PriceSourceResponseForString>
priceSources: ({
limit,
startAfter,
}: {
limit?: number
startAfter?: string
}) => Promise<ArrayOfPriceSourceResponseForString>
price: ({ denom }: { denom: string }) => Promise<PriceResponse>
prices: ({
limit,
startAfter,
}: {
limit?: number
startAfter?: string
}) => Promise<ArrayOfPriceResponse>
}
export class MarsOracleOsmosisQueryClient implements MarsOracleOsmosisReadOnlyInterface {
client: CosmWasmClient
contractAddress: string
constructor(client: CosmWasmClient, contractAddress: string) {
this.client = client
this.contractAddress = contractAddress
this.config = this.config.bind(this)
this.priceSource = this.priceSource.bind(this)
this.priceSources = this.priceSources.bind(this)
this.price = this.price.bind(this)
this.prices = this.prices.bind(this)
}
config = async (): Promise<ConfigResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
config: {},
})
}
priceSource = async ({ denom }: { denom: string }): Promise<PriceSourceResponseForString> => {
return this.client.queryContractSmart(this.contractAddress, {
price_source: {
denom,
},
})
}
priceSources = async ({
limit,
startAfter,
}: {
limit?: number
startAfter?: string
}): Promise<ArrayOfPriceSourceResponseForString> => {
return this.client.queryContractSmart(this.contractAddress, {
price_sources: {
limit,
start_after: startAfter,
},
})
}
price = async ({ denom }: { denom: string }): Promise<PriceResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
price: {
denom,
},
})
}
prices = async ({
limit,
startAfter,
}: {
limit?: number
startAfter?: string
}): Promise<ArrayOfPriceResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
prices: {
limit,
start_after: startAfter,
},
})
}
}
export interface MarsOracleOsmosisInterface extends MarsOracleOsmosisReadOnlyInterface {
contractAddress: string
sender: string
setPriceSource: (
{
denom,
priceSource,
}: {
denom: string
priceSource: OsmosisPriceSourceForString
},
fee?: number | StdFee | 'auto',
memo?: string,
_funds?: Coin[],
) => Promise<ExecuteResult>
removePriceSource: (
{
denom,
}: {
denom: string
},
fee?: number | StdFee | 'auto',
memo?: string,
_funds?: Coin[],
) => Promise<ExecuteResult>
updateOwner: (
ownerUpdate: OwnerUpdate,
fee?: number | StdFee | 'auto',
memo?: string,
_funds?: Coin[],
) => Promise<ExecuteResult>
updateConfig: (
{
baseDenom,
}: {
baseDenom?: string
},
fee?: number | StdFee | 'auto',
memo?: string,
_funds?: Coin[],
) => Promise<ExecuteResult>
}
export class MarsOracleOsmosisClient
extends MarsOracleOsmosisQueryClient
implements MarsOracleOsmosisInterface
{
client: SigningCosmWasmClient
sender: string
contractAddress: string
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress)
this.client = client
this.sender = sender
this.contractAddress = contractAddress
this.setPriceSource = this.setPriceSource.bind(this)
this.removePriceSource = this.removePriceSource.bind(this)
this.updateOwner = this.updateOwner.bind(this)
this.updateConfig = this.updateConfig.bind(this)
}
setPriceSource = async (
{
denom,
priceSource,
}: {
denom: string
priceSource: OsmosisPriceSourceForString
},
fee: number | StdFee | 'auto' = 'auto',
memo?: string,
_funds?: Coin[],
): Promise<ExecuteResult> => {
return await this.client.execute(
this.sender,
this.contractAddress,
{
set_price_source: {
denom,
price_source: priceSource,
},
},
fee,
memo,
_funds,
)
}
removePriceSource = async (
{
denom,
}: {
denom: string
},
fee: number | StdFee | 'auto' = 'auto',
memo?: string,
_funds?: Coin[],
): Promise<ExecuteResult> => {
return await this.client.execute(
this.sender,
this.contractAddress,
{
remove_price_source: {
denom,
},
},
fee,
memo,
_funds,
)
}
updateOwner = async (
ownerUpdate: OwnerUpdate,
fee: number | StdFee | 'auto' = 'auto',
memo?: string,
_funds?: Coin[],
): Promise<ExecuteResult> => {
return await this.client.execute(
this.sender,
this.contractAddress,
{
update_owner: ownerUpdate,
},
fee,
memo,
_funds,
)
}
updateConfig = async (
{
baseDenom,
}: {
baseDenom?: string
},
fee: number | StdFee | 'auto' = 'auto',
memo?: string,
_funds?: Coin[],
): Promise<ExecuteResult> => {
return await this.client.execute(
this.sender,
this.contractAddress,
{
update_config: {
base_denom: baseDenom,
},
},
fee,
memo,
_funds,
)
}
}

View File

@ -0,0 +1,259 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { UseQueryOptions, useQuery, useMutation, UseMutationOptions } from '@tanstack/react-query'
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
import { StdFee, Coin } from '@cosmjs/amino'
import {
InstantiateMsg,
ExecuteMsg,
OsmosisPriceSourceForString,
Decimal,
Downtime,
Identifier,
OwnerUpdate,
DowntimeDetector,
GeometricTwap,
RedemptionRateForString,
QueryMsg,
ConfigResponse,
PriceResponse,
PriceSourceResponseForString,
ArrayOfPriceSourceResponseForString,
ArrayOfPriceResponse,
} from './MarsOracleOsmosis.types'
import { MarsOracleOsmosisQueryClient, MarsOracleOsmosisClient } from './MarsOracleOsmosis.client'
export const marsOracleOsmosisQueryKeys = {
contract: [
{
contract: 'marsOracleOsmosis',
},
] as const,
address: (contractAddress: string | undefined) =>
[{ ...marsOracleOsmosisQueryKeys.contract[0], address: contractAddress }] as const,
config: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
[
{ ...marsOracleOsmosisQueryKeys.address(contractAddress)[0], method: 'config', args },
] as const,
priceSource: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
[
{ ...marsOracleOsmosisQueryKeys.address(contractAddress)[0], method: 'price_source', args },
] as const,
priceSources: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
[
{ ...marsOracleOsmosisQueryKeys.address(contractAddress)[0], method: 'price_sources', args },
] as const,
price: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
[{ ...marsOracleOsmosisQueryKeys.address(contractAddress)[0], method: 'price', args }] as const,
prices: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
[
{ ...marsOracleOsmosisQueryKeys.address(contractAddress)[0], method: 'prices', args },
] as const,
}
export interface MarsOracleOsmosisReactQuery<TResponse, TData = TResponse> {
client: MarsOracleOsmosisQueryClient | undefined
options?: Omit<
UseQueryOptions<TResponse, Error, TData>,
"'queryKey' | 'queryFn' | 'initialData'"
> & {
initialData?: undefined
}
}
export interface MarsOracleOsmosisPricesQuery<TData>
extends MarsOracleOsmosisReactQuery<ArrayOfPriceResponse, TData> {
args: {
limit?: number
startAfter?: string
}
}
export function useMarsOracleOsmosisPricesQuery<TData = ArrayOfPriceResponse>({
client,
args,
options,
}: MarsOracleOsmosisPricesQuery<TData>) {
return useQuery<ArrayOfPriceResponse, Error, TData>(
marsOracleOsmosisQueryKeys.prices(client?.contractAddress, args),
() =>
client
? client.prices({
limit: args.limit,
startAfter: args.startAfter,
})
: Promise.reject(new Error('Invalid client')),
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
)
}
export interface MarsOracleOsmosisPriceQuery<TData>
extends MarsOracleOsmosisReactQuery<PriceResponse, TData> {
args: {
denom: string
}
}
export function useMarsOracleOsmosisPriceQuery<TData = PriceResponse>({
client,
args,
options,
}: MarsOracleOsmosisPriceQuery<TData>) {
return useQuery<PriceResponse, Error, TData>(
marsOracleOsmosisQueryKeys.price(client?.contractAddress, args),
() =>
client
? client.price({
denom: args.denom,
})
: Promise.reject(new Error('Invalid client')),
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
)
}
export interface MarsOracleOsmosisPriceSourcesQuery<TData>
extends MarsOracleOsmosisReactQuery<ArrayOfPriceSourceResponseForString, TData> {
args: {
limit?: number
startAfter?: string
}
}
export function useMarsOracleOsmosisPriceSourcesQuery<TData = ArrayOfPriceSourceResponseForString>({
client,
args,
options,
}: MarsOracleOsmosisPriceSourcesQuery<TData>) {
return useQuery<ArrayOfPriceSourceResponseForString, Error, TData>(
marsOracleOsmosisQueryKeys.priceSources(client?.contractAddress, args),
() =>
client
? client.priceSources({
limit: args.limit,
startAfter: args.startAfter,
})
: Promise.reject(new Error('Invalid client')),
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
)
}
export interface MarsOracleOsmosisPriceSourceQuery<TData>
extends MarsOracleOsmosisReactQuery<PriceSourceResponseForString, TData> {
args: {
denom: string
}
}
export function useMarsOracleOsmosisPriceSourceQuery<TData = PriceSourceResponseForString>({
client,
args,
options,
}: MarsOracleOsmosisPriceSourceQuery<TData>) {
return useQuery<PriceSourceResponseForString, Error, TData>(
marsOracleOsmosisQueryKeys.priceSource(client?.contractAddress, args),
() =>
client
? client.priceSource({
denom: args.denom,
})
: Promise.reject(new Error('Invalid client')),
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
)
}
export interface MarsOracleOsmosisConfigQuery<TData>
extends MarsOracleOsmosisReactQuery<ConfigResponse, TData> {}
export function useMarsOracleOsmosisConfigQuery<TData = ConfigResponse>({
client,
options,
}: MarsOracleOsmosisConfigQuery<TData>) {
return useQuery<ConfigResponse, Error, TData>(
marsOracleOsmosisQueryKeys.config(client?.contractAddress),
() => (client ? client.config() : Promise.reject(new Error('Invalid client'))),
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
)
}
export interface MarsOracleOsmosisUpdateConfigMutation {
client: MarsOracleOsmosisClient
msg: {
baseDenom?: string
}
args?: {
fee?: number | StdFee | 'auto'
memo?: string
funds?: Coin[]
}
}
export function useMarsOracleOsmosisUpdateConfigMutation(
options?: Omit<
UseMutationOptions<ExecuteResult, Error, MarsOracleOsmosisUpdateConfigMutation>,
'mutationFn'
>,
) {
return useMutation<ExecuteResult, Error, MarsOracleOsmosisUpdateConfigMutation>(
({ client, msg, args: { fee, memo, funds } = {} }) =>
client.updateConfig(msg, fee, memo, funds),
options,
)
}
export interface MarsOracleOsmosisUpdateOwnerMutation {
client: MarsOracleOsmosisClient
msg: OwnerUpdate
args?: {
fee?: number | StdFee | 'auto'
memo?: string
funds?: Coin[]
}
}
export function useMarsOracleOsmosisUpdateOwnerMutation(
options?: Omit<
UseMutationOptions<ExecuteResult, Error, MarsOracleOsmosisUpdateOwnerMutation>,
'mutationFn'
>,
) {
return useMutation<ExecuteResult, Error, MarsOracleOsmosisUpdateOwnerMutation>(
({ client, msg, args: { fee, memo, funds } = {} }) => client.updateOwner(msg, fee, memo, funds),
options,
)
}
export interface MarsOracleOsmosisRemovePriceSourceMutation {
client: MarsOracleOsmosisClient
msg: {
denom: string
}
args?: {
fee?: number | StdFee | 'auto'
memo?: string
funds?: Coin[]
}
}
export function useMarsOracleOsmosisRemovePriceSourceMutation(
options?: Omit<
UseMutationOptions<ExecuteResult, Error, MarsOracleOsmosisRemovePriceSourceMutation>,
'mutationFn'
>,
) {
return useMutation<ExecuteResult, Error, MarsOracleOsmosisRemovePriceSourceMutation>(
({ client, msg, args: { fee, memo, funds } = {} }) =>
client.removePriceSource(msg, fee, memo, funds),
options,
)
}
export interface MarsOracleOsmosisSetPriceSourceMutation {
client: MarsOracleOsmosisClient
msg: {
denom: string
priceSource: OsmosisPriceSourceForString
}
args?: {
fee?: number | StdFee | 'auto'
memo?: string
funds?: Coin[]
}
}
export function useMarsOracleOsmosisSetPriceSourceMutation(
options?: Omit<
UseMutationOptions<ExecuteResult, Error, MarsOracleOsmosisSetPriceSourceMutation>,
'mutationFn'
>,
) {
return useMutation<ExecuteResult, Error, MarsOracleOsmosisSetPriceSourceMutation>(
({ client, msg, args: { fee, memo, funds } = {} }) =>
client.setPriceSource(msg, fee, memo, funds),
options,
)
}

View File

@ -0,0 +1,192 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
export interface InstantiateMsg {
base_denom: string
owner: string
}
export type ExecuteMsg =
| {
set_price_source: {
denom: string
price_source: OsmosisPriceSourceForString
}
}
| {
remove_price_source: {
denom: string
}
}
| {
update_owner: OwnerUpdate
}
| {
update_config: {
base_denom?: string | null
}
}
export type OsmosisPriceSourceForString =
| {
fixed: {
price: Decimal
[k: string]: unknown
}
}
| {
spot: {
pool_id: number
[k: string]: unknown
}
}
| {
arithmetic_twap: {
downtime_detector?: DowntimeDetector | null
pool_id: number
window_size: number
[k: string]: unknown
}
}
| {
geometric_twap: {
downtime_detector?: DowntimeDetector | null
pool_id: number
window_size: number
[k: string]: unknown
}
}
| {
xyk_liquidity_token: {
pool_id: number
[k: string]: unknown
}
}
| {
staked_geometric_twap: {
downtime_detector?: DowntimeDetector | null
pool_id: number
transitive_denom: string
window_size: number
[k: string]: unknown
}
}
| {
pyth: {
contract_addr: string
denom_decimals: number
max_staleness: number
price_feed_id: Identifier
[k: string]: unknown
}
}
| {
lsd: {
geometric_twap: GeometricTwap
redemption_rate: RedemptionRateForString
transitive_denom: string
[k: string]: unknown
}
}
export type Decimal = string
export type Downtime =
| 'duration30s'
| 'duration1m'
| 'duration2m'
| 'duration3m'
| 'duration4m'
| 'duration5m'
| 'duration10m'
| 'duration20m'
| 'duration30m'
| 'duration40m'
| 'duration50m'
| 'duration1h'
| 'duration15h'
| 'duration2h'
| 'duration25h'
| 'duration3h'
| 'duration4h'
| 'duration5h'
| 'duration6h'
| 'duration9h'
| 'duration12h'
| 'duration18h'
| 'duration24h'
| 'duration36h'
| 'duration48h'
export type Identifier = string
export type OwnerUpdate =
| {
propose_new_owner: {
proposed: string
}
}
| 'clear_proposed'
| 'accept_proposed'
| 'abolish_owner_role'
| {
set_emergency_owner: {
emergency_owner: string
}
}
| 'clear_emergency_owner'
export interface DowntimeDetector {
downtime: Downtime
recovery: number
[k: string]: unknown
}
export interface GeometricTwap {
downtime_detector?: DowntimeDetector | null
pool_id: number
window_size: number
[k: string]: unknown
}
export interface RedemptionRateForString {
contract_addr: string
max_staleness: number
[k: string]: unknown
}
export type QueryMsg =
| {
config: {}
}
| {
price_source: {
denom: string
}
}
| {
price_sources: {
limit?: number | null
start_after?: string | null
}
}
| {
price: {
denom: string
}
}
| {
prices: {
limit?: number | null
start_after?: string | null
}
}
export interface ConfigResponse {
base_denom: string
owner?: string | null
proposed_new_owner?: string | null
}
export interface PriceResponse {
denom: string
price: Decimal
}
export interface PriceSourceResponseForString {
denom: string
price_source: string
}
export type ArrayOfPriceSourceResponseForString = PriceSourceResponseForString[]
export type ArrayOfPriceResponse = PriceResponse[]

View File

@ -0,0 +1,13 @@
// @ts-nocheck
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import * as _6 from './MarsOracleOsmosis.types'
import * as _7 from './MarsOracleOsmosis.client'
import * as _8 from './MarsOracleOsmosis.react-query'
export namespace contracts {
export const MarsOracleOsmosis = { ..._6, ..._7, ..._8 }
}

View File

@ -0,0 +1,36 @@
import { ITEM_LIMIT_PER_QUERY } from 'constants/query'
interface KeyProperties {
denom?: string
addr?: string
}
type Query<T> = ({
limit,
startAfter,
}: {
limit?: number | undefined
startAfter?: string | undefined
}) => Promise<T[]>
export default async function iterateContractQuery<T extends KeyProperties>(
query: Query<T>,
keyProperty: keyof KeyProperties = 'denom',
previousResults?: T[],
): Promise<T[]> {
const lastItem = previousResults && previousResults.at(-1)
const lastItemKey = lastItem && lastItem[keyProperty]
const params = {
limit: ITEM_LIMIT_PER_QUERY,
startAfter: lastItemKey,
}
const results = await query(params)
const accumulated = (previousResults ?? []).concat(results)
if (results.length < ITEM_LIMIT_PER_QUERY) {
return accumulated
}
return await iterateContractQuery(query, keyProperty, accumulated)
}

View File

@ -33,8 +33,29 @@ if (!process.env.NEXT_PUBLIC_REST) {
if (!process.env.NEXT_PUBLIC_APOLLO_APR) {
throw 'NEXT_PUBLIC_APOLLO_APR is not defined'
}
if (!process.env.NEXT_PUBLIC_PARAMS) {
throw 'NEXT_PUBLIC_PARAMS is not defined'
}
if (!process.env.NEXT_PUBLIC_CANDLES_ENDPOINT) {
throw 'NEXT_PUBLIC_CANDLES_ENDPOINT is not defined'
}
if (!process.env.CHARTING_LIBRARY_USERNAME) {
throw 'CHARTING_LIBRARY_USERNAME is not defined'
}
if (!process.env.CHARTING_LIBRARY_ACCESS_TOKEN) {
throw 'CHARTING_LIBRARY_ACCESS_TOKEN is not defined'
}
if (!process.env.CHARTING_LIBRARY_REPOSITORY) {
throw 'CHARTING_LIBRARY_REPOSITORY is not defined'
}
if (!process.env.NEXT_PUBLIC_PYTH_ENDPOINT) {
throw 'NEXT_PUBLIC_PYTH_ENDPOINT is not defined'
}
if (!process.env.NEXT_PUBLIC_MAINNET_REST) {
throw 'NEXT_PUBLIC_MAINNET_REST is not defined'
}
if (!process.env.NEXT_PUBLIC_RPC) {
throw 'NEXT_PUBLIC_RPC is not defined'
} else {
console.log('✅ Required env variables set')
}
console.log('✅ Required env variables set')