diff --git a/README.md b/README.md index 5a514080..4fdd8a09 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,9 @@ The `nibijs` source code can be found in the `src` directory. - [Example: Creating a wallet](#example-creating-a-wallet) - [Example: Querying](#example-querying) - [Example: Sending funds](#example-sending-funds) - - [Example: Transaction with arbitrary messages](#example-transaction-with-arbitrary-messages) - [Codebase structure](#codebase-structure) - [Development Quick Start](#development-quick-start) -- [🔓 License](#%F0%9F%94%93-license) +- [🔓 License](#-license) To learn more about Nibiru, see [nibiru.fi/docs](https://nibiru.fi/docs) @@ -100,14 +99,6 @@ console.log("balances: %o", balances) const blockHeight = 200000 const block = await querier.getBlock(blockHeight) console.log("block: %o", block) - -// Query PERP markets -const perpMarkets = await querier.nibiruExtensions.perp.markets() -console.log("perpMarkets: %o", perpMarkets) - -// Query SPOT pools -const spotPools = await querier.nibiruExtensions.spot.pools() -console.log("spotPools: %o", spotPools) ``` ### Example: Sending funds @@ -151,63 +142,6 @@ balances = await querier.getAllBalances(exampleAddress) console.log("balances: %o", balances) ``` -### Example: Transaction with arbitrary messages - -```js -import { - NibiruTxClient, - newSignerFromMnemonic, - Msg, - Testnet, - NibiruQuerier, -} from "@nibiruchain/nibijs" -import { coin } from "@cosmjs/proto-signing" - -const mnemonic = "Your mnemonic here" -export const CHAIN = Testnet(2) -const signer = await newSignerFromMnemonic(mnemonic) -const querier = await NibiruQuerier.connect(CHAIN.endptTm) -const txClient = await NibiruTxClient.connectWithSigner(CHAIN.endptTm, signer) -const [{ address: fromAddr }] = await signer.getAccounts() -const pair = "ubtc:unusd" - -// Construct tx msgs -const msgs = [ - Msg.perp.openPosition({ - sender: fromAddr, - pair: pair, - quoteAssetAmount: 10, - leverage: 1, - goLong: true, - baseAssetAmountLimit: 0, - }), - Msg.perp.addMargin({ - sender: fromAddr, - pair: pair, - margin: coin("20", "unusd"), - }), - Msg.perp.removeMargin({ - sender: fromAddr, - pair: pair, - margin: coin("5", "unusd"), - }), - // final margin value of 10 (open) + 20 (add) - 5 (remove) = 25 -] - -// Broadcast tx -const txResp = await txClient.signAndBroadcast(fromAddr, msgs, "auto") -console.log(txResp) - -// Check your open PERP positions -const delay = (ms) => new Promise((res) => setTimeout(res, ms)) -await delay(5000) - -const perpPositions = await querier.nibiruExtensions.perp.positions({ - trader: fromAddr, -}) -console.log("perpPositions: %o", perpPositions) -``` - ## Codebase structure | Directories of `@nibiruchain/nibijs` | Purpose/Utility | diff --git a/nibiru b/nibiru index d71d67dc..3199ae53 160000 --- a/nibiru +++ b/nibiru @@ -1 +1 @@ -Subproject commit d71d67dcf4cd269c7d8d3be5b13a5cd8c4ee27b6 +Subproject commit 3199ae538bc2e1f4bb8d06727d0d10b96c6822a8 diff --git a/src/gql/heart-monitor/heart-monitor.test.ts b/src/gql/heart-monitor/heart-monitor.test.ts index b2c87c4e..30a5c1d8 100644 --- a/src/gql/heart-monitor/heart-monitor.test.ts +++ b/src/gql/heart-monitor/heart-monitor.test.ts @@ -139,10 +139,7 @@ const testFeatureFlags = async (fields: GQLFeatureFlags) => { if (resp.featureFlags) { const { featureFlags } = resp - checkFields( - [featureFlags], - ["gov", "oracle", "perp", "spot", "staking", "wasm"] - ) + checkFields([featureFlags], ["gov", "oracle", "staking", "wasm"]) } } @@ -398,10 +395,7 @@ test("queryBatchHandler", async () => { if (resp.featureFlags) { const { featureFlags } = resp - checkFields( - [featureFlags], - ["gov", "oracle", "perp", "spot", "staking", "wasm"] - ) + checkFields([featureFlags], ["gov", "oracle", "staking", "wasm"]) } }) diff --git a/src/gql/utils/consts.test.ts b/src/gql/utils/consts.test.ts index b62dfa85..a6ad8f81 100644 --- a/src/gql/utils/consts.test.ts +++ b/src/gql/utils/consts.test.ts @@ -37,10 +37,7 @@ describe("queryBatchHandler tests", () => { if (resp.featureFlags) { const { featureFlags } = resp - checkFields( - [featureFlags], - ["gov", "oracle", "perp", "spot", "staking", "wasm"] - ) + checkFields([featureFlags], ["gov", "oracle", "staking", "wasm"]) } }) diff --git a/src/gql/utils/defaultObjects.ts b/src/gql/utils/defaultObjects.ts index 09ec535d..e419516a 100644 --- a/src/gql/utils/defaultObjects.ts +++ b/src/gql/utils/defaultObjects.ts @@ -14,18 +14,10 @@ import { GQLInflationDistribution, GQLInflationInfo, GQLInflationRewards, - GQLMarkPriceCandle, GQLOracleEntry, GQLOraclePrice, - GQLPerpLeaderboard, - GQLPerpMarket, - GQLPerpPosition, - GQLPerpPositionChange, GQLProxies, GQLRedelegation, - GQLSpotLpPosition, - GQLSpotPool, - GQLSpotPoolSwap, GQLStakingActionType, GQLStakingHistoryItem, GQLToken, @@ -82,68 +74,6 @@ export const defaultActor: GQLUser = { export const defaultUser = defaultActor -export const defaultPerpMarket: GQLPerpMarket = { - base_reserve: 0, - ecosystem_fund_fee_ratio: 0, - max_funding_rate: 0, - enabled: true, - exchange_fee_ratio: 0, - funding_rate_epoch_id: "", - index_price_twap: 0, - is_deleted: false, - latest_cumulative_premium_fraction: 0, - liquidation_fee_ratio: 0, - maintenance_margin_ratio: 0, - mark_price: 0, - mark_price_twap: 0, - max_leverage: 0, - pair: "", - partial_liquidation_ratio: 0, - prepaid_bad_debt: defaultToken, - price_multiplier: 0, - quote_reserve: 0, - sqrt_depth: 0, - total_long: 0, - total_short: 0, - twap_lookback_window: "", -} - -export const defaultPerpPosition: GQLPerpPosition = { - bad_debt: 0, - last_updated_block: defaultBlock, - latest_cumulative_premium_fraction: 0, - margin: 0, - margin_ratio: 0, - open_notional: 0, - pair: "", - liquidation_price: 0, - position_notional: 0, - size: 0, - trader_address: "", - unrealized_funding_payment: 0, - unrealized_pnl: 0, -} - -export const defaultPool: GQLSpotPool = { - amplification: 0, - created_block: defaultBlock, - exit_fee: 0, - swap_fee: 0, - pool_id: 0, - tokens: [defaultToken], - pool_type: "", - total_shares: defaultToken, - total_weight: 0, - weights: [defaultToken], -} - -export const defaultSpotPool = { - block: defaultBlock, - pool: defaultPool, - pool_shares: defaultToken, - user: defaultUser, -} - export const defaultGovProposal: GQLGovProposal = { depositEndTime: "", finalTallyResultAbstain: 0, @@ -176,50 +106,6 @@ export const defaultGovVote: GQLGovVote = { sender: defaultUser, } -export const defaultMarkPriceCandles: GQLMarkPriceCandle = { - close: 0, - high: 0, - low: 0, - open: 0, - volume: 0, - volumeNotional: 0, - pair: "", - period: 0, - periodInterval: "", - periodStartTs: "", - indexPriceTwapClose: 0, -} - -export const defaultPerpPositionChanges: GQLPerpPositionChange = { - badDebt: defaultToken, - block: defaultBlock, - changeReason: "", - eventSeqNo: 0, - exchangedNotional: 0, - exchangedSize: 0, - fundingPayment: 0, - latestCumulativePremiumFraction: 0, - margin: 0, - marginToUser: 0, - openNotional: 0, - pair: "", - positionNotional: 0, - realizedPnl: 0, - size: 0, - traderAddress: "", - transactionFee: defaultToken, - txSeqNo: 0, -} - -export const defaultPerpLeaderboard: GQLPerpLeaderboard = { - avg_pct_pnl_rank: 0, - avg_pct_pnl: 0, - input_margin: 0, - raw_pnl: 0, - raw_pnl_with_unrealized: 0, - trader_address: "", -} - export const defaultGovernance: GQLGovernance = { govDeposits: [defaultGovDeposit], govProposals: [defaultGovProposal], @@ -227,7 +113,7 @@ export const defaultGovernance: GQLGovernance = { } export const defaultDistributionCommission: GQLDistributionCommission = { - commission: [defaultToken], + commission: defaultToken, validator: defaultValidator, } @@ -246,21 +132,6 @@ export const defaultRedelegations: GQLRedelegation = { creation_block: defaultBlock, } -export const defaultSpotLpPosition: GQLSpotLpPosition = { - created_block: defaultBlock, - pool: defaultPool, - pool_shares: defaultToken, - user: defaultUser, -} - -export const defaultSpotPoolSwap: GQLSpotPoolSwap = { - block: defaultBlock, - pool: defaultPool, - token_in: defaultToken, - token_out: defaultToken, - user: defaultUser, -} - export const defaultUnbondings: GQLUnbonding = { amount: 0, completion_time: "", @@ -342,8 +213,6 @@ export const defaultInflationInfo: GQLInflationInfo = { export const defaultFeatureFlags: GQLFeatureFlags = { gov: true, oracle: true, - perp: false, - spot: false, staking: true, wasm: true, } diff --git a/src/sdk/msg/eth.test.ts b/src/sdk/msg/eth.test.ts index 50271945..ae548c26 100644 --- a/src/sdk/msg/eth.test.ts +++ b/src/sdk/msg/eth.test.ts @@ -11,6 +11,12 @@ describe("setupEthMsgExtension", () => { UpdateParams: jest.fn().mockResolvedValue({ test: "Test", }), + CreateFunToken: jest.fn().mockResolvedValue({ + test: "Test", + }), + ConvertCoinToEvm: jest.fn().mockResolvedValue({ + test: "Test", + }), } as unknown as query.MsgClientImpl) test("should setup extension correctly", () => { @@ -54,30 +60,62 @@ describe("setupEthMsgExtension", () => { const result = await extension.updateParams({ authority: "", params: { - evmDenom: "", createFuntokenFee: "", - enableCreate: true, - enableCall: true, extraEips: [new Long(0)], - allowUnprotectedTxs: true, - activePrecompiles: [""], evmChannels: [""], }, }) expect(msgUpdateParams).toHaveBeenCalledWith({ authority: "", params: { - evmDenom: "", createFuntokenFee: "", - enableCreate: true, - enableCall: true, extraEips: [new Long(0)], - allowUnprotectedTxs: true, - activePrecompiles: [""], evmChannels: [""], }, }) expect(result).toEqual({ test: "Test" }) }) }) + + describe("createFunToken", () => { + test("should call MsgCreateFunToken and return the response", async () => { + const msgCreateFunToken = jest + .spyOn(query.MsgCreateFunToken, "fromPartial") + .mockReturnValue({} as query.MsgCreateFunToken) + + const extension = setupEthMsgExtension(mockBaseQueryClient) + const result = await extension.createFunToken({ + fromBankDenom: "", + fromErc20: "", + sender: "", + }) + expect(msgCreateFunToken).toHaveBeenCalledWith({ + fromBankDenom: "", + fromErc20: "", + sender: "", + }) + expect(result).toEqual({ test: "Test" }) + }) + }) + + describe("convertCoinToEVM", () => { + test("should call MsgConvertCoinToEvm and return the response", async () => { + const msgConvertCoinToEvm = jest + .spyOn(query.MsgConvertCoinToEvm, "fromPartial") + .mockReturnValue({} as query.MsgConvertCoinToEvm) + + const extension = setupEthMsgExtension(mockBaseQueryClient) + const result = await extension.convertCoinToEVM({ + toEthAddr: "", + bankCoin: { denom: "", amount: "" }, + sender: "", + }) + expect(msgConvertCoinToEvm).toHaveBeenCalledWith({ + toEthAddr: "", + bankCoin: { denom: "", amount: "" }, + sender: "", + }) + expect(result).toEqual({ test: "Test" }) + }) + }) }) diff --git a/src/sdk/msg/eth.ts b/src/sdk/msg/eth.ts index dce30c0c..8f9af639 100644 --- a/src/sdk/msg/eth.ts +++ b/src/sdk/msg/eth.ts @@ -1,6 +1,10 @@ import { createProtobufRpcClient, QueryClient } from "@cosmjs/stargate" import { MsgClientImpl, + MsgConvertCoinToEvm, + MsgConvertCoinToEvmResponse, + MsgCreateFunToken, + MsgCreateFunTokenResponse, MsgEthereumTx, MsgEthereumTxResponse, MsgUpdateParams, @@ -10,6 +14,12 @@ import { export interface EthMsgExtension { ethereumTx: (body: MsgEthereumTx) => Promise updateParams: (body: MsgUpdateParams) => Promise + createFunToken: ( + body: MsgCreateFunToken + ) => Promise + convertCoinToEVM: ( + body: MsgConvertCoinToEvm + ) => Promise } export const setupEthMsgExtension = (base: QueryClient): EthMsgExtension => { @@ -20,5 +30,9 @@ export const setupEthMsgExtension = (base: QueryClient): EthMsgExtension => { queryService.EthereumTx(MsgEthereumTx.fromPartial(body)), updateParams: async (body: MsgUpdateParams) => queryService.UpdateParams(MsgUpdateParams.fromPartial(body)), + createFunToken: async (body: MsgCreateFunToken) => + queryService.CreateFunToken(MsgCreateFunToken.fromPartial(body)), + convertCoinToEVM: async (body: MsgConvertCoinToEvm) => + queryService.ConvertCoinToEvm(MsgConvertCoinToEvm.fromPartial(body)), } } diff --git a/src/sdk/query/eth.test.ts b/src/sdk/query/eth.test.ts index d7d40dd7..59faddb7 100644 --- a/src/sdk/query/eth.test.ts +++ b/src/sdk/query/eth.test.ts @@ -36,6 +36,9 @@ describe("setupEpochsExtension", () => { TraceBlock: jest.fn().mockResolvedValue({ traceBlock: "Test", }), + TraceCall: jest.fn().mockResolvedValue({ + traceCall: "Test", + }), BaseFee: jest.fn().mockResolvedValue({ baseFee: "Test", }), @@ -58,6 +61,7 @@ describe("setupEpochsExtension", () => { expect(extension.estimateGas).toBeInstanceOf(Function) expect(extension.traceTx).toBeInstanceOf(Function) expect(extension.traceBlock).toBeInstanceOf(Function) + expect(extension.traceCall).toBeInstanceOf(Function) expect(extension.baseFee).toBeInstanceOf(Function) expect(extension.funTokenMapping).toBeInstanceOf(Function) }) @@ -244,7 +248,6 @@ describe("setupEpochsExtension", () => { limit: 0, enableMemory: true, enableReturnData: true, - tracerJsonConfig: "", }, predecessors: [MsgEthereumTx.fromPartial({})], blockNumber: new Long(0), @@ -267,7 +270,6 @@ describe("setupEpochsExtension", () => { limit: 0, enableMemory: true, enableReturnData: true, - tracerJsonConfig: "", }, predecessors: [MsgEthereumTx.fromPartial({})], blockNumber: new Long(0), @@ -300,7 +302,6 @@ describe("setupEpochsExtension", () => { limit: 0, enableMemory: true, enableReturnData: true, - tracerJsonConfig: "", }, blockNumber: new Long(0), blockHash: "", @@ -321,7 +322,6 @@ describe("setupEpochsExtension", () => { limit: 0, enableMemory: true, enableReturnData: true, - tracerJsonConfig: "", }, blockNumber: new Long(0), blockHash: "", @@ -334,6 +334,59 @@ describe("setupEpochsExtension", () => { }) }) + describe("traceCall", () => { + test("should call QueryTraceTxRequest and return the response", async () => { + const queryTraceTxRequest = jest + .spyOn(query.QueryTraceTxRequest, "fromPartial") + .mockReturnValue({} as query.QueryTraceTxRequest) + + const extension = setupEthExtension(mockBaseQueryClient) + const result = await extension.traceCall({ + msg: { + data: { typeUrl: "", value: new Uint8Array() }, + size: 0, + hash: "", + from: "", + }, + predecessors: [ + { + data: { typeUrl: "", value: new Uint8Array() }, + size: 0, + hash: "", + from: "", + }, + ], + blockHash: "", + blockMaxGas: new Long(0), + proposerAddress: new Uint8Array(), + blockNumber: new Long(0), + chainId: new Long(0), + }) + expect(queryTraceTxRequest).toHaveBeenCalledWith({ + msg: { + data: { typeUrl: "", value: new Uint8Array() }, + size: 0, + hash: "", + from: "", + }, + predecessors: [ + { + data: { typeUrl: "", value: new Uint8Array() }, + size: 0, + hash: "", + from: "", + }, + ], + blockHash: "", + blockMaxGas: new Long(0), + proposerAddress: new Uint8Array(), + blockNumber: new Long(0), + chainId: new Long(0), + }) + expect(result).toEqual({ traceCall: "Test" }) + }) + }) + describe("baseFee", () => { test("should call QueryBaseFeeRequest and return the response", async () => { const queryBaseFeeRequest = jest diff --git a/src/sdk/query/eth.ts b/src/sdk/query/eth.ts index 262b8a8c..934560b0 100644 --- a/src/sdk/query/eth.ts +++ b/src/sdk/query/eth.ts @@ -39,6 +39,7 @@ export interface EthExtension { estimateGas: (args: EthCallRequest) => Promise traceTx: (args: QueryTraceTxRequest) => Promise traceBlock: (args: QueryTraceBlockRequest) => Promise + traceCall: (args: QueryTraceTxRequest) => Promise baseFee: (args: QueryBaseFeeRequest) => Promise funTokenMapping: ( request: QueryFunTokenMappingRequest @@ -81,6 +82,9 @@ export const setupEthExtension = (base: QueryClient): EthExtension => { traceBlock: async (args: QueryTraceBlockRequest) => queryService.TraceBlock(QueryTraceBlockRequest.fromPartial(args)), + traceCall: async (args: QueryTraceTxRequest) => + queryService.TraceCall(QueryTraceTxRequest.fromPartial(args)), + baseFee: async (args: QueryBaseFeeRequest) => queryService.BaseFee(QueryBaseFeeRequest.fromPartial(args)),