Conversation
📝 WalkthroughWalkthroughAdds EVM ConvertEvmToCoin RPC, message, and event; extends Params with canonicalWnibi and MsgCreateFunToken with allowZeroDecimals; adds QueryExchangeRateResponse.isVintage; introduces GraphQL Marketing query and schema changes; adds heart-monitor evm/marketing batch APIs and tests; updates nibiru submodule pointer. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor App as SDK User
participant Ext as EthMsgExtension
participant Client as MsgClientImpl
participant RPC as RPC
participant Chain as EVM Module
App->>Ext: convertEvmToCoin({sender, erc20Addr, amount, toAddr})
Ext->>Client: ConvertEvmToCoin(MsgConvertEvmToCoin.fromPartial(...))
Client->>RPC: unary("/eth.evm.v1.Msg/ConvertEvmToCoin", bytes)
RPC->>Chain: Deliver ConvertEvmToCoin request
alt success
Chain-->>RPC: MsgConvertEvmToCoinResponse
RPC-->>Client: response bytes
Client-->>Ext: decoded response
Ext-->>App: resolved Promise
else error
RPC-->>Client: error
Client-->>Ext: reject
Ext-->>App: rejected Promise
end
note over Chain: Emits EventConvertEvmToCoin on success
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/protojs/eth/evm/v1/tx.ts (1)
1409-1416: Blocker: MsgConvertCoinToEvm encode/decode mismatch for toEthAddrEncode writes raw bytes, but decode reads a string. This breaks round‑trip compatibility and likely the on‑wire format. Also the hex-to-bytes conversion will mis-handle "0x" prefixes/odd lengths.
Fix: encode as string (to match interface and decode).
Apply this diff:
encode(message: MsgConvertCoinToEvm, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.toEthAddr !== "") { - // Converting string to raw bytes - const bytes = new Uint8Array( - message.toEthAddr.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)) - ) - writer.uint32(10).bytes(bytes) - } + if (message.toEthAddr !== "") { + writer.uint32(10).string(message.toEthAddr); + }Also applies to: 1437-1452
🧹 Nitpick comments (3)
src/protojs/eth/evm/v1/events.ts (1)
80-90: New EventConvertEvmToCoin interface: LGTM; consider clarifying address formats.Optional: add brief comments noting expected formats, e.g., toAddress (bech32) vs senderEthAddr (0x… EVM), to avoid misuse.
src/protojs/eth/evm/v1/tx.ts (1)
272-273: Biome lint: empty interfaceMsgConvertEvmToCoinResponse is an empty interface. Either:
- keep it as-is but silence lints for generated code (preferable), e.g., ignore src/protojs/** in Biome; or
- change to a type alias:
export type MsgConvertEvmToCoinResponse = {};Based on static analysis hints
src/sdk/msg/eth.ts (1)
13-15: Wiring for ConvertEvmToCoin is consistent and completeImports, type URL, registry entry, interface, and client call all align. LGTM.
Minor nit: method names mix
convertCoinToEVMvsconvertEvmToCoin. Consider standardizing casing for consistency (e.g., both...Evm...).Also applies to: 23-24, 31-32, 43-46, 60-61
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
nibiru(1 hunks)src/protojs/eth/evm/v1/events.ts(4 hunks)src/protojs/eth/evm/v1/evm.ts(7 hunks)src/protojs/eth/evm/v1/tx.ts(12 hunks)src/protojs/nibiru/oracle/v1/query.ts(7 hunks)src/sdk/msg/eth.test.ts(4 hunks)src/sdk/msg/eth.ts(4 hunks)src/sdk/query/oracle.test.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/protojs/eth/evm/v1/events.ts (2)
src/protojs/cosmos/base/v1beta1/coin.ts (2)
Coin(11-14)Coin(41-106)src/gql/utils/generated.ts (1)
Exact(3-3)
src/sdk/msg/eth.ts (1)
src/protojs/eth/evm/v1/tx.ts (5)
MsgServiceName(1707-1707)MsgConvertEvmToCoin(248-270)MsgConvertEvmToCoin(1541-1632)MsgConvertEvmToCoinResponse(272-273)MsgConvertEvmToCoinResponse(1638-1676)
src/protojs/eth/evm/v1/tx.ts (2)
src/gql/utils/generated.ts (1)
Exact(3-3)src/gql/utils/consts.ts (1)
DeepPartial(29-49)
src/sdk/msg/eth.test.ts (2)
src/protojs/eth/evm/v1/tx.ts (2)
MsgConvertEvmToCoin(248-270)MsgConvertEvmToCoin(1541-1632)src/sdk/msg/eth.ts (1)
setupEthMsgExtension(48-63)
🪛 Biome (2.1.2)
src/protojs/eth/evm/v1/tx.ts
[error] 272-273: An empty interface is equivalent to {}.
Safe fix: Use a type alias instead.
(lint/suspicious/noEmptyInterface)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checkout_cache_install_build_test
🔇 Additional comments (13)
src/protojs/eth/evm/v1/events.ts (3)
33-36: Doc change: LGTM.
50-53: Doc change for ConvertCoinToEvm: LGTM.
766-876: EventConvertEvmToCoin codec symmetry is correct; please manually confirm the .proto field numbers (1, 2, 3, 4, 6) match the encode/decode tags.src/protojs/eth/evm/v1/evm.ts (1)
37-38: Confirm upstream .proto field number for canonical_wnibi
- TS wiring (writer.uint32(82)/field 10) is correct; verify the upstream .proto declares
canonical_wnibi = 10to avoid tag mismatches.nibiru (1)
1-1: Approve submodule pointer bump; verify config and CI
.gitmodulespath/url entries are correct.- No branch is pinned—consider pinning to a stable release tag.
- Ensure CI invokes
git submodule sync --recursiveandgit submodule update --init --recursive.src/protojs/nibiru/oracle/v1/query.ts (1)
30-31: isVintage addition looks correct; tag and defaults are consistentField 4 uses bool (wire type 0), encoded only when true, defaulted to false across base/fromJSON/fromPartial. Decode path matches tag 32. LGTM. Please confirm upstream nodes may omit this field without issues (default stays false).
Also applies to: 268-269, 282-284, 316-323, 337-338, 347-348, 364-365
src/sdk/query/oracle.test.ts (1)
43-44: Fixture updated for isVintage — goodMocks now reflect the new field; keeps type-checking happy. LGTM.
src/sdk/msg/eth.test.ts (4)
20-23: Mocking ConvertEvmToCoin added — good coverageWires the new RPC into the test harness. LGTM.
69-70: Params.canonicalWnibi expectation added — OKTests assert new field in params; aligns with proto changes.
Also applies to: 75-76
96-97: createFunToken: allowZeroDecimals exercised — OKCovers the new flag; assertion looks correct.
Also applies to: 102-103
129-150: New convertEVMToCoin test — OKVerifies fromPartial args and mocked response. LGTM.
src/protojs/eth/evm/v1/tx.ts (2)
218-227: allowZeroDecimals field is correctly integratedBoolean field on tag 4 with sensible default/encoding. All (de)serialization paths align. LGTM.
Also applies to: 1248-1249, 1262-1264, 1297-1302, 1317-1318, 1326-1327, 1339-1340
247-270: New MsgConvertEvmToCoin flow is wired correctlyTypes, encode/decode, client interface, and MsgClientImpl method look consistent. LGTM.
Also applies to: 1537-1632, 1634-1676, 1700-1705, 1718-1719, 1744-1748
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/gql/heart-monitor/heart-monitor.test.ts (1)
308-328: Marketing tests cover happy path; consider adding a negative-caseOnce input validation is added in marketingQueryString (see comment in src/gql/query/marketing.ts), add a test asserting a clear error when required args are omitted.
src/gql/heart-monitor/heart-monitor.ts (1)
107-111: Avoid double DeepPartial on MarketingFieldsMarketingFields is already DeepPartial. Remove the extra DeepPartial for clarity and accurate typings.
- readonly marketing: ( - args: QueryMarketingArgs, - fields: DeepPartial<MarketingFields> - ) => Promise<GqlOutMarketing> + readonly marketing: ( + args: QueryMarketingArgs, + fields: MarketingFields + ) => Promise<GqlOutMarketing>- marketing = async ( - args: QueryMarketingArgs, - fields: DeepPartial<MarketingFields> - ) => marketing(args, this.gqlEndpt, fields) + marketing = async ( + args: QueryMarketingArgs, + fields: MarketingFields + ) => marketing(args, this.gqlEndpt, fields)Also applies to: 210-214
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/gql/heart-monitor/heart-monitor.test.ts(3 hunks)src/gql/heart-monitor/heart-monitor.ts(7 hunks)src/gql/query/index.ts(1 hunks)src/gql/query/marketing.ts(1 hunks)src/gql/utils/generated.ts(6 hunks)src/gql/utils/schema.graphql(7 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/gql/query/marketing.ts (2)
src/gql/utils/generated.ts (3)
GQLMarketingGqlIsTaskCompletedArgs(433-436)GQLQuery(536-564)GQLMarketing(427-430)src/gql/utils/consts.ts (3)
DeepPartial(29-49)arg(66-76)doGqlQuery(179-190)
src/gql/heart-monitor/heart-monitor.test.ts (5)
src/gql/utils/generated.ts (2)
GQLEvm(135-138)GQLMarketing(427-430)src/gql/utils/consts.ts (1)
checkFields(53-59)src/gql/query/evm.ts (1)
evm(25-28)src/gql/utils/defaultObjects.ts (1)
defaultEvm(281-310)src/gql/query/marketing.ts (2)
QueryMarketingArgs(10-12)marketing(43-53)
src/gql/heart-monitor/heart-monitor.ts (4)
src/gql/utils/consts.ts (2)
DeepPartial(29-49)queryBatchHandler(61-64)src/gql/utils/generated.ts (1)
GQLEvm(135-138)src/gql/query/evm.ts (2)
GqlOutEvm(10-12)evm(25-28)src/gql/query/marketing.ts (4)
QueryMarketingArgs(10-12)MarketingFields(18-18)GqlOutMarketing(14-16)marketing(43-53)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: checkout_cache_install_build_test
🔇 Additional comments (19)
src/gql/query/index.ts (1)
12-12: Expose marketing query via barrel – LGTMExporting the new marketing module here is correct and matches the new surface.
src/gql/heart-monitor/heart-monitor.test.ts (2)
58-60: Imports for marketing types – LGTMTypes align with generated GQLMarketing and QueryMarketingArgs.
140-154: EVM test helper – LGTMCovers presence and funTokens field; consistent with defaultEvm.
src/gql/utils/schema.graphql (5)
1-11: Add @defer directive – LGTMSchema-level addition looks standard and non-breaking to existing queries.
108-116: Event.txHash added – LGTMEnhances traceability without breaking changes.
343-346: New Marketing type and root field – LGTM; ensure clients pass required argsMatches generated types. Clients should provide both taskId and userAddress when querying isTaskCompleted.
Also applies to: 426-426
531-534: Introduce StringEqualsFilter – LGTMConsistent with new equality-only semantics used in ContractEventsFilter.
49-53: Contract events filter is a breaking change; verify client queries updated
contractEventsnow requires a non-nullwhere: ContractEventsFilter!andblockis mandatory in the filter.- Ensure all GraphQL queries or builders include the new
whereargument and handle the updated filters.src/gql/heart-monitor/heart-monitor.ts (5)
48-52: Marketing imports – LGTMTypes and function are correctly wired into HeartMonitor.
72-75: Public batch handler exposure – LGTMInterface addition mirrors implementation; naming consistent with tests.
86-87: EVM accessor in interface – LGTMSignature matches underlying evm(endpt, fields).
177-179: Batch handler implementation – LGTMPass-through to queryBatchHandler with instance endpoint is sound.
192-193: EVM method implementation – LGTMConsistent with other endpoint wrappers.
src/gql/utils/generated.ts (6)
124-124: LGTM!Adding the optional
txHashfield toGQLEventis backward compatible. Consumers can access transaction hashes when available.
427-436: LGTM!The new
GQLMarketingtype and associated args provide marketing task completion queries. This is a non-breaking addition to the schema.
548-548: LGTM!Adding the
marketingfield to the root Query type enables the new marketing functionality. This is a non-breaking addition.
785-787: LGTM!The new
GQLStringEqualsFilterprovides exact-match-only filtering, distinguishing it fromGQLStringFilterwhich supports pattern matching. This appears intentional for contract event queries (lines 58-59).
992-992: Require where clause on contractEvents queries.
Thewhereparameter is now mandatory forcontractEventscalls; verify every invocation supplies a validwhereclause to avoid runtime failures.
56-60: Breaking changes in GQLContractEventsFilter
blockis now required (was optional) — all queries must include a block filter.contractAddressandtypechanged fromGQLStringFilter(withlike) toGQLStringEqualsFilter(exact matches only).Verify all client queries and code using
contractEventshave been updated to supply the requiredwhere/blockfilter and accommodate exact‐match filtering.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/gql/heart-monitor/heart-monitor.test.ts(3 hunks)src/gql/heart-monitor/heart-monitor.ts(7 hunks)src/gql/query/index.ts(1 hunks)src/gql/query/marketing.ts(1 hunks)src/gql/utils/generated.ts(6 hunks)src/gql/utils/schema.graphql(7 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/gql/query/marketing.ts (2)
src/gql/utils/generated.ts (3)
GQLMarketingGqlIsTaskCompletedArgs(433-436)GQLQuery(536-564)GQLMarketing(427-430)src/gql/utils/consts.ts (3)
DeepPartial(29-49)arg(66-76)doGqlQuery(179-190)
src/gql/heart-monitor/heart-monitor.test.ts (5)
src/gql/utils/generated.ts (2)
GQLEvm(135-138)GQLMarketing(427-430)src/gql/utils/consts.ts (1)
checkFields(53-59)src/gql/query/evm.ts (1)
evm(25-28)src/gql/utils/defaultObjects.ts (1)
defaultEvm(281-310)src/gql/query/marketing.ts (2)
QueryMarketingArgs(10-12)marketing(43-53)
src/gql/heart-monitor/heart-monitor.ts (3)
src/gql/utils/consts.ts (2)
DeepPartial(29-49)queryBatchHandler(61-64)src/gql/query/evm.ts (2)
GqlOutEvm(10-12)evm(25-28)src/gql/query/marketing.ts (4)
QueryMarketingArgs(10-12)MarketingFields(18-18)GqlOutMarketing(14-16)marketing(43-53)
🔇 Additional comments (12)
src/gql/query/index.ts (1)
12-12: LGTM!The marketing module export follows the existing barrel file pattern and aligns with the new marketing query functionality introduced in this PR.
src/gql/heart-monitor/heart-monitor.test.ts (2)
140-153: LGTM!The EVM test implementation follows the established testing patterns in this file and correctly validates the EVM query functionality.
308-327: Verify that the hardcoded test values exist in the test environment.The test uses hardcoded values (
taskId: "task-123"anduserAddress: "nibi1xyz"). Ensure these values exist in the testnet-2 environment, otherwise the test may fail.src/gql/utils/generated.ts (1)
57-59: LGTM!The generated types correctly reflect the GraphQL schema changes, including:
- New
GQLMarketingtype withisTaskCompletedfield- New
GQLStringEqualsFilterfor exact string matching- Added
txHashfield toGQLEvent- Updated
GQLContractEventsFilterwith requiredblockand new filter types- Required
whereparameter inGQLWasmGqlContractEventsArgsAlso applies to: 124-124, 427-436, 548-548, 785-787, 992-992
src/gql/heart-monitor/heart-monitor.ts (3)
86-86: LGTM!The
evmmethod follows the established pattern for query methods and correctly delegates to the corresponding query function.Also applies to: 192-192
107-110: LGTM!The
marketingmethod follows the established pattern for query methods and correctly delegates to the corresponding query function with proper argument ordering.Also applies to: 210-213
72-74: No internal references toGQLQueryGqlBatchHandler; verify external usage
Ripgrep found zero internal calls or interface-typed invocations of this method—ensure no external consumers rely on it.src/gql/query/marketing.ts (1)
43-53: LGTM!The
marketingfunction correctly follows the established pattern for query execution, properly wrapping the query string and delegating todoGqlQuery.src/gql/utils/schema.graphql (4)
1-10: LGTM!The
@deferdirective is a standard GraphQL feature for deferred fragment execution, properly defined with its standard arguments.
50-52: LGTM!The schema changes improve the contract events filtering:
- Required
blockfilter enforces proper query scopingStringEqualsFilterprovides exact-match semantics forcontractAddressandtypetxHashfield addition toEventtype enhances event traceabilityAlso applies to: 113-113
343-345: LGTM!The
Marketingtype and query field are properly defined, withisTaskCompletedrequiring bothtaskIdanduserAddressas non-null arguments, aligning with the implementation in the query module.Also applies to: 426-426
531-533: LGTM!The
StringEqualsFilterinput type provides exact-match filtering semantics, and makingwhererequired inWasm.contractEventsensures proper query scoping, consistent with the requiredblockfilter inContractEventsFilter.Also applies to: 713-713
* chore: unstoppable domain proxy (#404) * fix: move curly braces * refactor: adding custom amino messages (#407) * refactor: adding custom amino converter for convert to evm msg * chore: comment and linting * chore: new file instead of index * chore: linting * chore: pull latest protos * chore: update protos and gql (#412) * chore: update protos * chore: add gql updates * fix: small issue --------- Co-authored-by: Calico Nino <54007257+CalicoNino@users.noreply.github.com>
No description provided.