Skip to content

Commit

Permalink
feat: neptune service
Browse files Browse the repository at this point in the history
  • Loading branch information
shane-moore committed Nov 8, 2024
1 parent c66e830 commit cceff72
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/sdk-ts/src/client/wasm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './swap'
export * from './types'
export * from './incentives'
export * from './nameservice'
export * from './neptune'
export * from './trading_strategies'
6 changes: 6 additions & 0 deletions packages/sdk-ts/src/client/wasm/neptune/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './queries'
export * from './transformer'
export * from './types'
export * from './service'

export const NEPTUNE_PRICE_CONTRACT = 'inj1u6cclz0qh5tep9m2qayry9k97dm46pnlqf8nre'
19 changes: 19 additions & 0 deletions packages/sdk-ts/src/client/wasm/neptune/queries/QueryGetPrices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { BaseWasmQuery } from '../../BaseWasmQuery'
import { toBase64 } from '../../../../utils'
import { AssetInfo } from '../types'

export declare namespace QueryGetPrices {
export interface Params {
assets: AssetInfo[]
}
}

export class QueryGetPrices extends BaseWasmQuery<QueryGetPrices.Params> {
toPayload() {
return toBase64({
get_prices: {
assets: this.params.assets,
},
})
}
}
1 change: 1 addition & 0 deletions packages/sdk-ts/src/client/wasm/neptune/queries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { QueryGetPrices } from './QueryGetPrices'
159 changes: 159 additions & 0 deletions packages/sdk-ts/src/client/wasm/neptune/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import {
Network,
isMainnet,
getNetworkEndpoints,
} from '@injectivelabs/networks'
import { AssetInfo, NEPTUNE_USDT_CW20_CONTRACT, AssetInfoWithPrice } from './types'
import { ChainGrpcWasmApi } from '../../chain'
import { QueryGetPrices } from './queries'
import { PriceQueryTransformer } from './transformer'
import ExecArgNeptuneDeposit from '../../../core/modules/wasm/exec-args/ExecArgNeptuneDeposit'
import ExecArgNeptuneWithdraw from '../../../core/modules/wasm/exec-args/ExecArgNeptuneWithdraw'

import MsgExecuteContractCompat from '../../../core/modules/wasm/msgs/MsgExecuteContractCompat'

import { GeneralException } from '@injectivelabs/exceptions'
import { NEPTUNE_PRICE_CONTRACT } from './index'

const NEPTUNE_USDT_MARKET_CONTRACT = 'inj1nc7gjkf2mhp34a6gquhurg8qahnw5kxs5u3s4u'

export class NeptuneService {
private client: ChainGrpcWasmApi
private priceOracleContract: string

/**
* Constructs a new NeptuneService instan ce.
* @param network The network to use (default: Mainnet).
* @param endpoints Optional custom network endpoints.
*/
constructor(
network: Network = Network.Mainnet,
endpoints?: any // Replace `any` with the appropriate type if available
) {
if (network !== Network.Mainnet) {
throw new GeneralException(new Error('Please switch to mainnet network'))
}

const networkEndpoints = endpoints || getNetworkEndpoints(network)
this.client = new ChainGrpcWasmApi(networkEndpoints.grpc)
this.priceOracleContract = isMainnet(network) ? NEPTUNE_PRICE_CONTRACT : ''
}

/**
* Fetch prices for given assets from the Neptune Price Oracle contract.
* @param assets Array of AssetInfo objects.
* @returns Array of Price objects.
*/
async fetchPrices(assets: AssetInfo[]): Promise<AssetInfoWithPrice[]> {
const queryGetPricesPayload = new QueryGetPrices({ assets }).toPayload()

try {
const response = await this.client.fetchSmartContractState(
this.priceOracleContract,
queryGetPricesPayload
)

const prices = PriceQueryTransformer.contractPricesResponseToPrices(response)

return prices
} catch (error) {
console.error('Error fetching prices:', error)
throw new GeneralException(new Error('Failed to fetch prices'))
}
}

/**
* Fetch the redemption ratio based on CW20 and native asset prices.
* @param cw20Asset AssetInfo for the CW20 token.
* @param nativeAsset AssetInfo for the native token.
* @returns Redemption ratio as a number.
*/
async fetchRedemptionRatio({ cw20Asset, nativeAsset }: {
cw20Asset: AssetInfo,
nativeAsset: AssetInfo
}): Promise<number> {
const prices = await this.fetchPrices([cw20Asset, nativeAsset])

const [cw20Price] = prices
const [nativePrice] = prices.reverse()

if (!cw20Price || !nativePrice) {
throw new GeneralException(new Error('Failed to compute redemption ratio'))
}

return Number(cw20Price.price) / Number(nativePrice.price)
}

/**
* Convert CW20 nUSDT to bank nUSDT using the redemption ratio.
* @param amountCW20 Amount in CW20 nUSDT.
* @param redemptionRatio Redemption ratio.
* @returns Amount in bank nUSDT.
*/
calculateBankAmount(amountCW20: number, redemptionRatio: number): number {
return amountCW20 * redemptionRatio
}

/**
* Convert bank nUSDT to CW20 nUSDT using the redemption ratio.
* @param amountBank Amount in bank nUSDT.
* @param redemptionRatio Redemption ratio.
* @returns Amount in CW20 nUSDT.
*/
calculateCw20Amount(amountBank: number, redemptionRatio: number): number {
return amountBank / redemptionRatio
}

/**
* Create a deposit message.
* @param sender Sender's Injective address.
* @param contractAddress USDT market contract address.
* @param denom Denomination of the asset.
* @param amount Amount to deposit as a string.
* @returns MsgExecuteContractCompat message.
*/
createDepositMsg(
denom: string,
amount: string,
sender: string,
contractAddress: string = NEPTUNE_USDT_MARKET_CONTRACT,
): MsgExecuteContractCompat {
return MsgExecuteContractCompat.fromJSON({
sender,
contractAddress,
execArgs: ExecArgNeptuneDeposit.fromJSON({}),
funds: {
denom,
amount,
},
})
}

/**
* Create a withdraw message.
* @param sender Sender's Injective address.
* @param contractAddress nUSDT contract address.
* @param amount Amount to withdraw as a string.
* @returns MsgExecuteContractCompat message.
*/
createWithdrawMsg({
amount,
sender,
cw20ContractAddress = NEPTUNE_USDT_CW20_CONTRACT,
marketContractAddress = NEPTUNE_USDT_MARKET_CONTRACT,
}: {
amount: string,
sender: string,
cw20ContractAddress?: string,
marketContractAddress?: string,
}): MsgExecuteContractCompat {
return MsgExecuteContractCompat.fromJSON({
sender,
contractAddress: cw20ContractAddress,
execArgs: ExecArgNeptuneWithdraw.fromJSON({
amount,
contract: marketContractAddress,
}),
})
}
}
16 changes: 16 additions & 0 deletions packages/sdk-ts/src/client/wasm/neptune/transformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { WasmContractQueryResponse } from '../types'
import { toUtf8 } from '../../../utils'
import { AssetInfo, PriceResponse } from './types'

export class PriceQueryTransformer {
static contractPricesResponseToPrices(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; price: string }> {
const data = JSON.parse(toUtf8(response.data)) as PriceResponse

return data.map(([assetInfo, priceInfo]) => ({
assetInfo,
price: priceInfo.price,
}))
}
}
18 changes: 18 additions & 0 deletions packages/sdk-ts/src/client/wasm/neptune/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export type AssetInfo =
| {
token: {
contract_addr: string
}
}
| {
native_token: {
denom: string
}
}

export type AssetInfoWithPrice = {assetInfo: AssetInfo, price: string }

export type PriceResponse = Array<[AssetInfo, { price: string }]>

export const NEPTUNE_USDT_CW20_CONTRACT =
'inj1cy9hes20vww2yr6crvs75gxy5hpycya2hmjg9s'
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
dataToExecData,
ExecArgBase,
ExecDataRepresentation,
} from '../ExecArgBase'

export declare namespace ExecArgNeptuneDeposit {
export interface Params {}

export interface Data {}
}

/**
* @category Contract Exec Arguments
*/
export default class ExecArgNeptuneDeposit extends ExecArgBase<
ExecArgNeptuneDeposit.Params,
ExecArgNeptuneDeposit.Data
> {
static fromJSON(
params: ExecArgNeptuneDeposit.Params,
): ExecArgNeptuneDeposit {
return new ExecArgNeptuneDeposit(params)
}

public toData(): ExecArgNeptuneDeposit.Data {
return {}
}

public toExecData(): ExecDataRepresentation<ExecArgNeptuneDeposit.Data> {
return dataToExecData('lend', this.toData())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
ExecArgBase,
dataToExecData,
ExecDataRepresentation,
} from '../ExecArgBase'
import { toBase64 } from '../../../../utils'


export declare namespace ExecArgNeptuneWithdraw {
export interface Params {
amount: string
contract: string
}

export interface Data {
amount: string
contract: string
msg: string
}
}

/**
* @category Contract Exec Arguments
*/
export default class ExecArgNeptuneWithdraw extends ExecArgBase<
ExecArgNeptuneWithdraw.Params,
ExecArgNeptuneWithdraw.Data
> {
static fromJSON(
params: ExecArgNeptuneWithdraw.Params,
): ExecArgNeptuneWithdraw {
return new ExecArgNeptuneWithdraw(params)
}

toData(): ExecArgNeptuneWithdraw.Data {
const { params } = this
const innerMsg = { redeem: {} }
const encodedMsg = toBase64(innerMsg)

return {
amount: params.amount,
contract: params.contract,
msg: encodedMsg,
}
}

toExecData(): ExecDataRepresentation<ExecArgNeptuneWithdraw.Data> {
return dataToExecData('send', this.toData())
}
}
4 changes: 4 additions & 0 deletions packages/sdk-ts/src/core/modules/wasm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import ExecArgCW20Transfer from './exec-args/ExecArgCW20Transfer'
import ExecArgSwapMinOutput from './exec-args/ExecArgSwapMinOutput'
import ExecArgDepositTokens from './exec-args/ExecArgDepositTokens'
import ExecArgCreateCampaign from './exec-args/ExecArgCreateCampaign'
import ExecArgNeptuneDeposit from './exec-args/ExecArgNeptuneDeposit'
import ExecArgSwapExactOutput from './exec-args/ExecArgSwapExactOutput'
import ExecArgNeptuneWithdraw from './exec-args/ExecArgNeptuneWithdraw'
import ExecArgInitiateTransfer from './exec-args/ExecArgInitiateTransfer'
import ExecArgUpdateGridConfig from './exec-args/ExecArgUpdateGridConfig'
import ExecArgIncreaseAllowance from './exec-args/ExecArgIncreaseAllowance'
Expand Down Expand Up @@ -40,7 +42,9 @@ export {
ExecArgSwapMinOutput,
ExecArgDepositTokens,
ExecArgCreateCampaign,
ExecArgNeptuneDeposit,
ExecArgSwapExactOutput,
ExecArgNeptuneWithdraw,
ExecArgInitiateTransfer,
ExecArgUpdateGridConfig,
ExecArgIncreaseAllowance,
Expand Down

0 comments on commit cceff72

Please sign in to comment.