Skip to content

release/update master for v1.61#359

Merged
aarmoa merged 11 commits intomasterfrom
release/update_master_for_v1_61
Apr 27, 2026
Merged

release/update master for v1.61#359
aarmoa merged 11 commits intomasterfrom
release/update_master_for_v1_61

Conversation

@aarmoa
Copy link
Copy Markdown
Collaborator

@aarmoa aarmoa commented Apr 27, 2026

PR to submit changes in dev for v1.19.0 chain upgrade into master, to release the v1.61.0 version

Summary by CodeRabbit

  • New Features

    • Added auction & insurance voucher queries and new oracle streaming endpoints.
    • Introduced white‑knight liquidator parameters and related defaults.
  • Bug Fixes

    • Tightened validation for market denoms, oracle symbols/providers, and price thresholds.
    • Improved derivative fee/margin/refund and VWAP computations.
  • Chores

    • Switched examples to environment-based credential loading; added an env example and ignore rule for env files.
    • Updated build tooling and workflows.

aarmoa added 10 commits April 14, 2026 11:17
…-beta and indexer v1.18.59. Added examples also for new vouchers functionality
Replace hardcoded hex keys in InitCosmosKeyring call sites with
os.Getenv("INJECTIVE_PRIVATE_KEY"), call godotenv.Load() at startup, and
document variables in .env.example. Ignore .env in git.
…19_0_beta

[IC-986] sync_with_version_v1_19_0_beta
…_v1_60_0

[CHORE] Solved merge issues between master and dev branches
…t_for_release

[CHORE] final v1.19 alignment for release
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

Adds environment-driven example configuration (.env.example + .gitignore), broad example updates to load INJECTIVE_PRIVATE_KEY via godotenv, registers MsgClaimVoucher, introduces voucher query APIs, streaming oracle RPCs, and multiple exchange/oracle/peggy/type/param/logic changes across the chain modules.

Changes

Cohort / File(s) Summary
Env & CI
./.env.example, ./.gitignore, .github/workflows/golangci-lint.yml
Adds .env.example (INJECTIVE_PRIVATE_KEY), ignores .env, and updates golangci-lint action version.
Makefile / Build
Makefile
Updates cloned chain repos to v1.19.x, adjusts copy of chain types (adds vouchers/common types, removes some ocr types).
Examples — env-driven keys
examples/.../*.go (many files, 150+), examples/exchange/oracle/*
All examples now call godotenv.Load() and source private key from os.Getenv("INJECTIVE_PRIVATE_KEY"); several new example entrypoints added for vouchers and streaming.
Examples — removed data
examples/.../injective_data/ofac.json (two files)
Deletes OFAC address allowlist JSON files.
Client APIs
client/chain/chain_v2.go, client/chain/chain_test_support.go, client/exchange/exchange.go
Adds ChainClientV2 methods and mock methods to fetch auction/insurance vouchers; adds ExchangeClient streaming methods (StreamOracleList, StreamPricesByMarkets) and implementations.
Auction & Insurance codec
chain/auction/types/codec.go, chain/insurance/types/codec.go
Registers MsgClaimVoucher in legacy Amino and interface registry.
New examples for vouchers & streaming
examples/chain/auction/..., examples/chain/insurance/..., examples/exchange/oracle/...
Adds example programs to claim/query vouchers and to stream oracle lists/prices by market.
Exchange auth & params refactor
chain/exchange/types/authz_common.go, chain/exchange/types/v2/authz.go, chain/exchange/types/params.go
Refactors BatchUpdateOrders auth to table-driven checks; adds generic authorization helpers; introduces new params (white-knight liquidators, length caps) and validators; many signature type updates from interface{}any.
Exchange keys, msgs, errors, utils
chain/exchange/types/key.go, chain/exchange/types/msgs.go, chain/exchange/types/errors.go, chain/exchange/types/common_utils.go
Adds object-store and transient VWAP keys, new transient key helper; tightens market/oracle/denom validations; renames AuctionFeesAddress→ExchangeAuctionFeesAddress; comments out ErrOrderbookFillInvalid.
Exchange v2 logic changes
chain/exchange/types/v2/derivative.go, .../derivative_orders.go, .../fee_discounts.go, .../position.go
Centralizes margin-hold logic, adds MergePerpetualVwap, changes ComputeSyntheticVwapUnitDelta signature, removes some setters, adjusts cancel fee-rate logic, and adds bankrupt-close handling.
Peggy keys & claim hash
chain/peggy/types/key.go, chain/peggy/types/msgs.go
Renames rate-limit/mint key constants; adds inflow/outflow and per-block key builders; changes MsgValsetUpdatedClaim.ClaimHash preimage to include RewardToken/RewardAmount.
Oracle — Chainlink & Pyth utilities
chain/oracle/types/chainlink_data_streams.go, chain/oracle/types/pyth.go, chain/oracle/types/codec.go, chain/oracle/types/oracle.go, chain/oracle/types/params.go
Adds constructors/updaters for Chainlink/Pyth price states, Pyth attestation helpers/validation, exponentiation util; registers MsgRelayChainlinkPrices; adds positive-price guard in threshold check; removes AcceptUnverifiedChainlinkDataStreamsReports default.
Downtime & config/util helpers
chain/downtime-detector/types/keys.go, chain/types/config.go, chain/types/util.go
Replaces fmt.Sprintf with string concatenation for keys; adds InitSDKConfig() with sync.Once; adds safe iterator helpers (IterateSafe/IterateKeysSafe) and callback types.
EVM errors
chain/evm/types/errors.go
Adds ErrBlockedAddress error registration.
WasmX params
chain/wasmx/types/params.go
Adds ExecutionGasFeeMultiplier and MaxSafeExecutionGasLimit; enforces upper bound for MaxContractGasLimit.
Client test support & mocks
client/chain/chain_test_support.go
Adds mock methods returning empty voucher query responses for auction and insurance.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • [IC-986] sync_with_version_v1_19_0_beta #355: Overlapping changes including .env.example & .env ignore, migrating examples to godotenv/INJECTIVE_PRIVATE_KEY, Makefile chain-type updates, and MsgClaimVoucher codec registrations.

Poem

🐰 I hopped from hardcode to dotenv bright,

Keys in the air, no secrets in sight.
Vouchers claimed and oracle streams flow,
Examples now fetch keys from the meadow.
A tiny rabbit cheers — code ready to go! 🥕✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/update_master_for_v1_61

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 27, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
examples/chain/13_BroadcastMsgWithoutSimulation/example.go (1)

21-37: ⚠️ Potential issue | 🟡 Minor

Handle godotenv.Load() error silently

The pattern _ = godotenv.Load() silently ignores errors from loading the .env file. If the file doesn't exist or has parse errors, the application will proceed without warning. Consider logging or handling the error explicitly:

if err := godotenv.Load(); err != nil {
    // Handle error: log warning, fail gracefully, or continue based on requirements
}

The subsequent call to os.Getenv("INJECTIVE_PRIVATE_KEY") is intentionally designed with a fallback: if the environment variable is not set, InitCosmosKeyring will use the keyring backend (specified by the "inj-user" key name in cosmosKeyFrom), as documented in the function's behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/13_BroadcastMsgWithoutSimulation/example.go` around lines 21 -
37, Replace the silent discard of godotenv.Load() in main with explicit error
handling: call godotenv.Load() and if it returns an error log a non-fatal
warning (or decide to exit) so missing or malformed .env files are visible;
update the call site in main where godotenv.Load() is currently assigned to _
and ensure the behavior still lets InitCosmosKeyring use
os.Getenv("INJECTIVE_PRIVATE_KEY") as its documented fallback when the env var
is absent.
🧹 Nitpick comments (12)
chain/peggy/types/key.go (1)

314-367: Use common.Address for ERC20 parameters to align with the file's established pattern.

The new helpers at lines 314–367 all accept raw []byte for ERC20 addresses, inconsistent with existing key builders in this file (GetOutgoingTxBatchKey, GetBatchConfirmKey, GetFeeSecondIndexKey, GetERC20ToCosmosDenomKey) which all use common.Address. The typed parameter enforces a 20-byte invariant and prevents accidental malformed key construction. Changing these seven functions to accept common.Address instead of []byte would keep the API consistent and safer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/peggy/types/key.go` around lines 314 - 367, These helpers accept raw
[]byte for ERC20 but should use common.Address for consistency and to enforce
20-byte addresses; change the parameter type of GetRateLimitKey,
GetMintAmountERC20Key, GetTokenInflowPrefix, GetTokenInflowByBlockKey,
GetTokenOutflowPrefix, GetTokenOutflowByBlockKey, and GetTokenNetOutflowKey to
common.Address, replace uses of erc20 and len(erc20) with addr.Bytes() and
common.AddressLength (or len(addr.Bytes())), and update the append calls to
append(addr.Bytes()...) and capacity calculations accordingly; also add the
github.com/ethereum/go-ethereum/common import and update any callers to pass a
common.Address.
chain/wasmx/types/params.go (1)

17-19: Contribution of overflow-safe gas constants is solid.

The derived constants clearly express the relationships:

  • MinExecutionGasLimit correctly sums all required gas components
  • MaxSafeExecutionGasLimit bounds contract gas to prevent overflow when multiplied by ExecutionGasFeeMultiplier

Minor suggestion for clarity: Consider using math.MaxUint64 instead of ^uint64(0) for explicit readability, though both are equivalent.

 const (
 	GasForFeeDeduction        uint64 = 13419
 	GasForFeeRefund           uint64 = 13419
 	DefaultGasContractCall    uint64 = 63558
 	ExecutionGasFeeMultiplier uint64 = 3
 	MinExecutionGasLimit      uint64 = GasForFeeDeduction + GasForFeeRefund + DefaultGasContractCall
-	MaxSafeExecutionGasLimit  uint64 = ^uint64(0) / ExecutionGasFeeMultiplier
+	MaxSafeExecutionGasLimit  uint64 = math.MaxUint64 / ExecutionGasFeeMultiplier
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/wasmx/types/params.go` around lines 17 - 19, Replace the bit-twiddling
max value with the explicit constant: change the computation of
MaxSafeExecutionGasLimit to use math.MaxUint64 divided by
ExecutionGasFeeMultiplier, and add the necessary import for the math package;
this touches the constants ExecutionGasFeeMultiplier and
MaxSafeExecutionGasLimit in params.go.
examples/chain/ibc/channel/query/13_NextSequenceReceive/example.go (1)

4-16: Minor import ordering inconsistency.

The os import at line 15 is separated from other standard library imports. Standard Go convention groups all stdlib imports together. This is a minor formatting issue that doesn't affect functionality.

The godotenv import is correctly placed among third-party imports.

♻️ Optional: Consolidate standard library imports
 import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"os"
 
 	"github.com/InjectiveLabs/sdk-go/client"
 	"github.com/joho/godotenv"
 
 	chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
 	"github.com/InjectiveLabs/sdk-go/client/common"
 	rpchttp "github.com/cometbft/cometbft/rpc/client/http"
-
-	"os"
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/ibc/channel/query/13_NextSequenceReceive/example.go` around
lines 4 - 16, The import ordering in example.go is inconsistent: the standard
library import "os" is separated from the other stdlib imports ("context",
"encoding/json", "fmt"); move "os" into the first import group so all standard
library packages are grouped together, keeping third-party imports
(github.com/..., rpchttp) and local aliases (chainclient, common) in their
respective groups; update the import block around the file-level imports to
reflect the standard Go grouping convention.
examples/chain/exchange/query/18_SubaccountOrders/example.go (1)

17-17: Consider logging when .env file is not found.

The error from godotenv.Load() is silently discarded. While this allows the .env file to be optional (env vars can be set directly in the shell), logging a warning when the file doesn't exist would improve debugging experience for developers using these examples.

♻️ Optional improvement
-func main() {
-	_ = godotenv.Load()
+func main() {
+	if err := godotenv.Load(); err != nil {
+		fmt.Printf("Warning: .env file not found, using environment variables: %v\n", err)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/exchange/query/18_SubaccountOrders/example.go` at line 17, The
call to godotenv.Load() currently discards errors; change it to check the
returned error and log a warning when the .env file is missing or any load error
occurs so developers know why defaults/env vars might be absent. Specifically,
replace the standalone godotenv.Load() invocation with an error check around
godotenv.Load() (in example.go, where godotenv.Load() is called), and use the
log package to emit a warning like " .env not found: %v" when os.IsNotExist(err)
(or a generic "failed to load .env: %v" for other errors) so missing or
problematic .env files are visible during debugging.
examples/chain/exchange/query/51_OptedOutOfRewardsAccounts/example.go (2)

17-18: Consider handling .env load errors explicitly.

The error from godotenv.Load() is silently discarded. If the .env file is missing or malformed, the application continues without any indication, and INJECTIVE_PRIVATE_KEY may be unset, causing confusing downstream errors in keyring initialization.

♻️ Optional improvement for error handling
 func main() {
-	_ = godotenv.Load()
+	if err := godotenv.Load(); err != nil && !os.IsNotExist(err) {
+		fmt.Printf("Warning: failed to load .env file: %v\n", err)
+	}

Alternatively, if silent failure is intentional (e.g., .env is optional), consider adding a comment clarifying this.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/exchange/query/51_OptedOutOfRewardsAccounts/example.go` around
lines 17 - 18, The call to godotenv.Load() in main currently ignores errors;
change this so the error is handled or documented: check the returned error from
godotenv.Load() in main and either log/warn/fatal the error (so
missing/malformed .env is visible before keyring initialization that uses
INJECTIVE_PRIVATE_KEY) or add a comment explaining that .env is intentionally
optional; ensure the fix references the godotenv.Load() invocation and the
subsequent keyring/private key usage so users won’t get silent failures.

25-32: Validate INJECTIVE_PRIVATE_KEY before use.

If INJECTIVE_PRIVATE_KEY is not set, os.Getenv returns an empty string, which gets passed to InitCosmosKeyring. This could cause unclear errors downstream. Consider adding a validation check with a clear error message.

🛡️ Optional validation
 	senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
 		os.Getenv("HOME")+"/.injectived",
 		"injectived",
 		"file",
 		"inj-user",
 		"12345678",
-		os.Getenv("INJECTIVE_PRIVATE_KEY"), // keyring will be used if pk not provided
+		func() string {
+			pk := os.Getenv("INJECTIVE_PRIVATE_KEY")
+			if pk == "" {
+				fmt.Println("Warning: INJECTIVE_PRIVATE_KEY not set, falling back to keyring")
+			}
+			return pk
+		}(),
 		false,
 	)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/exchange/query/51_OptedOutOfRewardsAccounts/example.go` around
lines 25 - 32, The code calls InitCosmosKeyring with
os.Getenv("INJECTIVE_PRIVATE_KEY") without validating it, which can lead to
unclear downstream errors; before calling InitCosmosKeyring, check that the
INJECTIVE_PRIVATE_KEY env var is non-empty and return or log a clear error if
missing (e.g., set a descriptive error and exit or propagate it), so update the
logic around the call that assigns senderAddress, cosmosKeyring, err to validate
the env var and handle the missing-key case explicitly.
examples/chain/distribution/query/9_CommunityPool/example.go (1)

18-18: Consider handling godotenv.Load() errors explicitly.

Silently discarding the error with _ = godotenv.Load() means the program will silently proceed even if the .env file doesn't exist or has syntax errors. For example code, this may be acceptable since INJECTIVE_PRIVATE_KEY can come from the shell environment. If this pattern is intended as a reference for production integrations, consider adding at least a warning log when the file fails to load.

If the key is intended to be optional (falling back to keyring), the comment on line 31 already documents that behavior. However, for security-sensitive credentials, you may want to validate that either the key is provided or keyring is available before proceeding.

💡 Optional: Add validation for private key presence
 func main() {
-	_ = godotenv.Load()
+	if err := godotenv.Load(); err != nil {
+		// .env is optional; env vars may come from shell environment
+		fmt.Printf("Note: .env file not loaded: %v\n", err)
+	}
+	
+	privateKey := os.Getenv("INJECTIVE_PRIVATE_KEY")
+	if privateKey == "" {
+		fmt.Println("Warning: INJECTIVE_PRIVATE_KEY not set, will use keyring")
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/distribution/query/9_CommunityPool/example.go` at line 18,
Replace the silent ignore of godotenv.Load() with explicit error handling: call
godotenv.Load() and if it returns an error, log a warning (via your logger or
fmt.Printf) that the .env file failed to load and include the error text;
additionally validate presence of the INJECTIVE_PRIVATE_KEY environment variable
(or detect keyring fallback) before proceeding and log/fatal if neither is
available. Locate the call to godotenv.Load() and the code that reads
INJECTIVE_PRIVATE_KEY to add these checks and messages.
examples/chain/13_BroadcastMsgWithoutSimulation/example.go (1)

21-22: Consider logging a warning when .env file fails to load.

The current implementation silently discards errors from godotenv.Load(). While this allows the program to continue using system environment variables, it may mask configuration issues during development.

🔧 Optional: Log warning on .env load failure
-func main() {
-	_ = godotenv.Load()
+func main() {
+	if err := godotenv.Load(); err != nil {
+		// Non-fatal: .env is optional, environment variables may still be set
+		fmt.Printf("Warning: .env file not loaded: %v\n", err)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/13_BroadcastMsgWithoutSimulation/example.go` around lines 21 -
22, In main(), currently the return value from godotenv.Load() is ignored;
change this to check the error from godotenv.Load() and call your logger (or
log.Printf/log.Warn) to emit a warning when loading .env fails (e.g., "warning:
failed to load .env: %v"), while still allowing the program to continue; update
the code around the godotenv.Load() call in main() to capture err and log the
warning when err != nil.
examples/chain/insurance/1_MsgClaimVoucher/example.go (1)

20-20: Consider checking godotenv.Load error.

While _ discard is acceptable for optional .env loading, it would be helpful to log a warning when the file exists but fails to parse. However, this is acceptable for example code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/insurance/1_MsgClaimVoucher/example.go` at line 20, The call
to godotenv.Load() currently discards any error; change it to capture the
returned error from godotenv.Load() in example.go (the call site referencing
godotenv.Load) and if err != nil, log a brief warning (e.g., using log.Printf or
fmt.Println) indicating the .env file failed to load and include the error
message so failures to parse are visible in examples; keep behavior non-fatal so
the example continues running.
examples/chain/insurance/query/2_Voucher/example.go (1)

65-68: Same error handling issue as auction query example.

Consider matching error handling patterns across similar examples (panic vs print-and-continue).

♻️ Consistent error handling
 	res, err := chainClient.FetchInsuranceVoucher(ctx, denom, address)
 	if err != nil {
-		fmt.Println(err)
+		panic(err)
 	}

 	str, _ := json.MarshalIndent(res, "", "\t")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/insurance/query/2_Voucher/example.go` around lines 65 - 68,
The error handling for the FetchInsuranceVoucher call is inconsistent with other
examples: locate the FetchInsuranceVoucher call (res, err :=
chainClient.FetchInsuranceVoucher(ctx, denom, address)) and replace the
fmt.Println(err) branch with the project's standard error pattern used in
similar examples (e.g., panic(err) or log.Fatalf with a contextual message) so
failures abort/exit consistently; ensure you preserve the existing variable
names (res, err) and context (ctx, denom, address) when updating the handler.
examples/chain/auction/query/2_Voucher/example.go (1)

65-68: Error handling pattern inconsistent with other examples.

On error, this example prints the error but continues to process and print the result (which will be nil). Consider returning early on error or using the same panic pattern as other examples for consistency.

♻️ Consistent error handling
 	res, err := chainClient.FetchAuctionVoucher(ctx, denom, address)
 	if err != nil {
-		fmt.Println(err)
+		panic(err)
 	}

 	str, _ := json.MarshalIndent(res, "", "\t")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/auction/query/2_Voucher/example.go` around lines 65 - 68, The
example calls chainClient.FetchAuctionVoucher and prints the error but continues
to use res; update the error handling in the FetchAuctionVoucher call (res, err
:= chainClient.FetchAuctionVoucher(ctx, denom, address)) to return early or
panic on err (matching other examples) instead of just fmt.Println(err), so the
function exits when err != nil and does not attempt to print or use a nil res.
examples/exchange/oracle/5_StreamOracleList/example.go (1)

30-43: Stream loop lacks graceful error handling and context cancellation pattern.

The select with ctx.Done() is unreachable inside the default branch since stream.Recv() is blocking. Consider using a goroutine or restructure to properly check context cancellation. Also, for examples intended for demonstration, consider adding timeout handling for stream.Recv().

♻️ Refactor stream loop for proper cancellation
 	for {
-		select {
-		case <-ctx.Done():
-			return
-		default:
-			res, err := stream.Recv()
-			if err != nil {
-				fmt.Println(err)
-				return
-			}
-			str, _ := json.MarshalIndent(res, "", "\t")
-			fmt.Print(string(str))
-		}
+		res, err := stream.Recv()
+		if err != nil {
+			fmt.Println(err)
+			return
+		}
+		str, _ := json.MarshalIndent(res, "", "\t")
+		fmt.Print(string(str))
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/exchange/oracle/5_StreamOracleList/example.go` around lines 30 - 43,
The current loop blocks on stream.Recv() so the ctx.Done() case is never
reached; refactor to perform Recv in a dedicated goroutine that sends either the
received message or its error on channels, then select between ctx.Done(), the
recv channel, and an optional timeout (time.After) to handle cancellation and
timeouts gracefully. Specifically, create a recv goroutine that calls
stream.Recv() and sends results to a msgChan/errChan, then in the main loop
select on ctx.Done() to return, on msgChan to marshal/print the message, on
errChan to log/handle the error and break, and optionally a timeout case to
cancel long waits; reference the existing ctx and stream.Recv() to locate where
to change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@chain/exchange/types/v2/position.go`:
- Around line 351-385: In ApplyBankruptCloseWithoutPayouts, guard against a
negative closingQuantity by returning early (e.g., return math.LegacyZeroDec(),
nil) when closingQuantity.IsNegative(); then compute the closed slice's margin
and remove it from the remaining position instead of keeping the whole pre-close
margin: capture origMargin := p.Margin and origQty := p.Quantity, compute
closedMargin := origMargin.Mul(closingQuantity.Quo(origQty)) (use LegacyDec
Mul/Quo), compute pnl := p.GetPayoutFromPnl(closingPrice, closingQuantity) as
you already do, and set remainingMargin :=
origMargin.Sub(closedMargin).Add(pnl); set remainingQuantity :=
origQty.Sub(closingQuantity); if remainingQuantity.IsZero() call
p.ClosePositionWithoutPayouts() else assign p.Quantity = remainingQuantity and
p.Margin = remainingMargin; keep constructing PositionDelta as you already do
(ExecutionQuantity = closingQuantity, ExecutionPrice = closingPrice, IsLong =
!p.IsLong).

In `@chain/oracle/types/pyth.go`:
- Around line 8-23: NewPythPriceState currently converts publishTime int64 to
uint64 directly which silently wraps negative times; update NewPythPriceState to
validate publishTime is >= 0 and return an error for negative values (change
signature to NewPythPriceState(...) (*PythPriceState, error)), or alternatively
accept a uint64 publishTime so callers must provide a non-negative value; ensure
you adjust the creation of PythPriceState.PriceState to use NewPriceState(price,
blockTime) as before and update all callers to handle the new error/return
signature.
- Around line 42-49: The current check in PriceAttestation.Validate is
ineffective because GetPriceIDHash uses common.HexToHash which always returns a
32-byte value; instead, validate the raw p.PriceId string itself: strip an
optional "0x" prefix, verify the hex string length equals 64 characters (32
bytes), attempt to hex-decode it (e.g., with hex.DecodeString) and return
ErrInvalidPythPriceID if decoding fails or length is wrong; after this
validation you can still use GetPriceIDHash() safely. Ensure you update
PriceAttestation.Validate (and keep ErrInvalidPythPriceID) and do not rely on
common.HexToHash for input validation.

In `@chain/peggy/types/key.go`:
- Around line 120-121: Add deprecated aliases for the renamed exported keys so
downstream consumers don’t break: keep the new exported constants RateLimitKey
and MintAmountERC20Key as-is and add variables with the old names RateLimitsKey
and MintAmountsERC20Key that point to those same byte slices (marked/decorated
as deprecated in comments). Update key.go to define RateLimitsKey = RateLimitKey
and MintAmountsERC20Key = MintAmountERC20Key so the underlying prefix bytes
remain unchanged while preserving the old symbol names for this release.

In `@chain/peggy/types/msgs.go`:
- Around line 556-563: The Members field (b.Members, type []*BridgeValidator) is
being printed with "%s", producing non-canonical "%!s(...)" output and breaking
deterministic hashing in ClaimHash(); replace that with a deterministic
serialization: iterate over b.Members in order and build a canonical string
(e.g., join(fmt.Sprintf("%s/%d", member.GetAddress(), member.Power) for each
member) or marshal each member with a deterministic codec) and use that
canonical string in the tmhash.Sum input so ClaimHash() hashes the explicit,
ordered validator contents rather than Go's default "%s" representation.

In `@examples/chain/auction/query/1_Vouchers/example.go`:
- Around line 65-71: If FetchAuctionVouchers (call to
chainClient.FetchAuctionVouchers) returns an error, stop the example instead of
continuing: check err and return/exit non‑zero with a helpful message; do the
same for json.MarshalIndent — check its error and abort on failure. Concretely,
after calling FetchAuctionVouchers, if err != nil log/print the error and
os.Exit(1) (or return), and when calling json.MarshalIndent(res, "", "\t")
capture the marshal error, handle it the same way instead of ignoring it; this
ensures you don't print a zero-value res on failures and the example returns a
non‑zero status on errors.

In `@examples/chain/ibc/channel/query/10_PacketAcknowledgements/example.go`:
- Line 21: The call to godotenv.Load() in example.go is cwd-dependent and won't
find the repo-level .env when running the example from its folder; update the
example to load the .env via an explicit path instead of relying on the working
directory (e.g., resolve the example file's directory with runtime.Caller or
compute the repo-root relative path and call godotenv.Load(resolvedPath)) so the
.env is loaded predictably when running the example; change the godotenv.Load()
invocation in this file to load the resolved path.

In `@examples/chain/insurance/query/1_Vouchers/example.go`:
- Around line 65-71: The example currently ignores errors from
chainClient.FetchInsuranceVouchers and json.MarshalIndent and proceeds to print
potentially invalid output; modify the handler around
chainClient.FetchInsuranceVouchers(ctx, denom) so that if err != nil you fail
fast (return or log.Fatal/exit) instead of continuing, and check the error
returned by json.MarshalIndent(res, "", "\t") storing to str and err (or
marshalErr) and fail fast on marshal errors as well; update references to res,
err, and str so errors are handled immediately after each call to
FetchInsuranceVouchers and json.MarshalIndent.

In `@examples/exchange/oracle/6_StreamPricesByMarkets/example.go`:
- Line 13: The network name string passed to common.LoadNetwork is misspelled;
update the call in the example where network := common.LoadNetwork("tstnet",
"lb") to use the correct network name "testnet" (i.e.,
common.LoadNetwork("testnet", "lb")) so the LoadNetwork invocation and the
variable network receive the proper environment name.

---

Outside diff comments:
In `@examples/chain/13_BroadcastMsgWithoutSimulation/example.go`:
- Around line 21-37: Replace the silent discard of godotenv.Load() in main with
explicit error handling: call godotenv.Load() and if it returns an error log a
non-fatal warning (or decide to exit) so missing or malformed .env files are
visible; update the call site in main where godotenv.Load() is currently
assigned to _ and ensure the behavior still lets InitCosmosKeyring use
os.Getenv("INJECTIVE_PRIVATE_KEY") as its documented fallback when the env var
is absent.

---

Nitpick comments:
In `@chain/peggy/types/key.go`:
- Around line 314-367: These helpers accept raw []byte for ERC20 but should use
common.Address for consistency and to enforce 20-byte addresses; change the
parameter type of GetRateLimitKey, GetMintAmountERC20Key, GetTokenInflowPrefix,
GetTokenInflowByBlockKey, GetTokenOutflowPrefix, GetTokenOutflowByBlockKey, and
GetTokenNetOutflowKey to common.Address, replace uses of erc20 and len(erc20)
with addr.Bytes() and common.AddressLength (or len(addr.Bytes())), and update
the append calls to append(addr.Bytes()...) and capacity calculations
accordingly; also add the github.com/ethereum/go-ethereum/common import and
update any callers to pass a common.Address.

In `@chain/wasmx/types/params.go`:
- Around line 17-19: Replace the bit-twiddling max value with the explicit
constant: change the computation of MaxSafeExecutionGasLimit to use
math.MaxUint64 divided by ExecutionGasFeeMultiplier, and add the necessary
import for the math package; this touches the constants
ExecutionGasFeeMultiplier and MaxSafeExecutionGasLimit in params.go.

In `@examples/chain/13_BroadcastMsgWithoutSimulation/example.go`:
- Around line 21-22: In main(), currently the return value from godotenv.Load()
is ignored; change this to check the error from godotenv.Load() and call your
logger (or log.Printf/log.Warn) to emit a warning when loading .env fails (e.g.,
"warning: failed to load .env: %v"), while still allowing the program to
continue; update the code around the godotenv.Load() call in main() to capture
err and log the warning when err != nil.

In `@examples/chain/auction/query/2_Voucher/example.go`:
- Around line 65-68: The example calls chainClient.FetchAuctionVoucher and
prints the error but continues to use res; update the error handling in the
FetchAuctionVoucher call (res, err := chainClient.FetchAuctionVoucher(ctx,
denom, address)) to return early or panic on err (matching other examples)
instead of just fmt.Println(err), so the function exits when err != nil and does
not attempt to print or use a nil res.

In `@examples/chain/distribution/query/9_CommunityPool/example.go`:
- Line 18: Replace the silent ignore of godotenv.Load() with explicit error
handling: call godotenv.Load() and if it returns an error, log a warning (via
your logger or fmt.Printf) that the .env file failed to load and include the
error text; additionally validate presence of the INJECTIVE_PRIVATE_KEY
environment variable (or detect keyring fallback) before proceeding and
log/fatal if neither is available. Locate the call to godotenv.Load() and the
code that reads INJECTIVE_PRIVATE_KEY to add these checks and messages.

In `@examples/chain/exchange/query/18_SubaccountOrders/example.go`:
- Line 17: The call to godotenv.Load() currently discards errors; change it to
check the returned error and log a warning when the .env file is missing or any
load error occurs so developers know why defaults/env vars might be absent.
Specifically, replace the standalone godotenv.Load() invocation with an error
check around godotenv.Load() (in example.go, where godotenv.Load() is called),
and use the log package to emit a warning like " .env not found: %v" when
os.IsNotExist(err) (or a generic "failed to load .env: %v" for other errors) so
missing or problematic .env files are visible during debugging.

In `@examples/chain/exchange/query/51_OptedOutOfRewardsAccounts/example.go`:
- Around line 17-18: The call to godotenv.Load() in main currently ignores
errors; change this so the error is handled or documented: check the returned
error from godotenv.Load() in main and either log/warn/fatal the error (so
missing/malformed .env is visible before keyring initialization that uses
INJECTIVE_PRIVATE_KEY) or add a comment explaining that .env is intentionally
optional; ensure the fix references the godotenv.Load() invocation and the
subsequent keyring/private key usage so users won’t get silent failures.
- Around line 25-32: The code calls InitCosmosKeyring with
os.Getenv("INJECTIVE_PRIVATE_KEY") without validating it, which can lead to
unclear downstream errors; before calling InitCosmosKeyring, check that the
INJECTIVE_PRIVATE_KEY env var is non-empty and return or log a clear error if
missing (e.g., set a descriptive error and exit or propagate it), so update the
logic around the call that assigns senderAddress, cosmosKeyring, err to validate
the env var and handle the missing-key case explicitly.

In `@examples/chain/ibc/channel/query/13_NextSequenceReceive/example.go`:
- Around line 4-16: The import ordering in example.go is inconsistent: the
standard library import "os" is separated from the other stdlib imports
("context", "encoding/json", "fmt"); move "os" into the first import group so
all standard library packages are grouped together, keeping third-party imports
(github.com/..., rpchttp) and local aliases (chainclient, common) in their
respective groups; update the import block around the file-level imports to
reflect the standard Go grouping convention.

In `@examples/chain/insurance/1_MsgClaimVoucher/example.go`:
- Line 20: The call to godotenv.Load() currently discards any error; change it
to capture the returned error from godotenv.Load() in example.go (the call site
referencing godotenv.Load) and if err != nil, log a brief warning (e.g., using
log.Printf or fmt.Println) indicating the .env file failed to load and include
the error message so failures to parse are visible in examples; keep behavior
non-fatal so the example continues running.

In `@examples/chain/insurance/query/2_Voucher/example.go`:
- Around line 65-68: The error handling for the FetchInsuranceVoucher call is
inconsistent with other examples: locate the FetchInsuranceVoucher call (res,
err := chainClient.FetchInsuranceVoucher(ctx, denom, address)) and replace the
fmt.Println(err) branch with the project's standard error pattern used in
similar examples (e.g., panic(err) or log.Fatalf with a contextual message) so
failures abort/exit consistently; ensure you preserve the existing variable
names (res, err) and context (ctx, denom, address) when updating the handler.

In `@examples/exchange/oracle/5_StreamOracleList/example.go`:
- Around line 30-43: The current loop blocks on stream.Recv() so the ctx.Done()
case is never reached; refactor to perform Recv in a dedicated goroutine that
sends either the received message or its error on channels, then select between
ctx.Done(), the recv channel, and an optional timeout (time.After) to handle
cancellation and timeouts gracefully. Specifically, create a recv goroutine that
calls stream.Recv() and sends results to a msgChan/errChan, then in the main
loop select on ctx.Done() to return, on msgChan to marshal/print the message, on
errChan to log/handle the error and break, and optionally a timeout case to
cancel long waits; reference the existing ctx and stream.Recv() to locate where
to change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cf8cea67-60d5-4e5d-8007-e37755eea345

📥 Commits

Reviewing files that changed from the base of the PR and between 933045e and 955379a.

⛔ Files ignored due to path filters (27)
  • chain/auction/types/auction.pb.go is excluded by !**/*.pb.go
  • chain/auction/types/genesis.pb.go is excluded by !**/*.pb.go
  • chain/auction/types/query.pb.go is excluded by !**/*.pb.go
  • chain/auction/types/tx.pb.go is excluded by !**/*.pb.go
  • chain/common/vouchers/types/vouchers.pb.go is excluded by !**/*.pb.go
  • chain/exchange/types/exchange.pb.go is excluded by !**/*.pb.go
  • chain/exchange/types/v2/exchange.pb.go is excluded by !**/*.pb.go
  • chain/insurance/types/events.pb.go is excluded by !**/*.pb.go
  • chain/insurance/types/genesis.pb.go is excluded by !**/*.pb.go
  • chain/insurance/types/insurance.pb.go is excluded by !**/*.pb.go
  • chain/insurance/types/query.pb.go is excluded by !**/*.pb.go
  • chain/insurance/types/tx.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/events.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/genesis.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/oracle.pb.go is excluded by !**/*.pb.go
  • chain/peggy/types/genesis.pb.go is excluded by !**/*.pb.go
  • chain/peggy/types/msgs.pb.go is excluded by !**/*.pb.go
  • chain/peggy/types/rate_limit.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/events.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/genesis.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/params.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/permissions.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/query.pb.go is excluded by !**/*.pb.go
  • chain/txfees/types/tx.pb.go is excluded by !**/*.pb.go
  • chain/txfees/types/txfees.pb.go is excluded by !**/*.pb.go
  • chain/wasmx/types/tx.pb.go is excluded by !**/*.pb.go
  • exchange/accounts_rpc/pb/goadesign_goagen_injective_accounts_rpc.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (273)
  • .env.example
  • .github/workflows/golangci-lint.yml
  • .gitignore
  • Makefile
  • chain/auction/types/codec.go
  • chain/downtime-detector/types/keys.go
  • chain/evm/types/errors.go
  • chain/exchange/types/authz_common.go
  • chain/exchange/types/common_utils.go
  • chain/exchange/types/errors.go
  • chain/exchange/types/key.go
  • chain/exchange/types/msgs.go
  • chain/exchange/types/params.go
  • chain/exchange/types/proposal.go
  • chain/exchange/types/v2/authz.go
  • chain/exchange/types/v2/derivative.go
  • chain/exchange/types/v2/derivative_orders.go
  • chain/exchange/types/v2/fee_discounts.go
  • chain/exchange/types/v2/msgs.go
  • chain/exchange/types/v2/params.go
  • chain/exchange/types/v2/position.go
  • chain/exchange/types/v2/proposal.go
  • chain/insurance/types/codec.go
  • chain/oracle/types/chainlink_data_streams.go
  • chain/oracle/types/codec.go
  • chain/oracle/types/oracle.go
  • chain/oracle/types/params.go
  • chain/oracle/types/pyth.go
  • chain/peggy/types/key.go
  • chain/peggy/types/msgs.go
  • chain/types/config.go
  • chain/types/util.go
  • chain/wasmx/types/params.go
  • client/chain/chain_test_support.go
  • client/chain/chain_v2.go
  • client/exchange/exchange.go
  • examples/chain/13_BroadcastMsgWithoutSimulation/example.go
  • examples/chain/14_HistoricalQueryByHeight/example.go
  • examples/chain/1_LocalOrderHash/example.go
  • examples/chain/2_MsgBatchCancelSpotOrders/example.go
  • examples/chain/3_MsgBatchCancelDerivativeOrders/example.go
  • examples/chain/4_MsgBatchCreateSpotLimitOrders/example.go
  • examples/chain/5_MsgBatchCreateDerivativeLimitOrders/example.go
  • examples/chain/6_MsgRegisterAsDMM/example.go
  • examples/chain/8_OfflineSigning/example.go
  • examples/chain/auction/1_MsgBid/example.go
  • examples/chain/auction/2_MsgClaimVoucher/example.go
  • examples/chain/auction/query/1_Vouchers/example.go
  • examples/chain/auction/query/2_Voucher/example.go
  • examples/chain/auth/query/1_Account/example.go
  • examples/chain/authz/1_MsgGrant/example.go
  • examples/chain/authz/2_MsgExec/example.go
  • examples/chain/authz/3_MsgRevoke/example.go
  • examples/chain/authz/query/1_Grants/example.go
  • examples/chain/bank/1_MsgSend/example.go
  • examples/chain/bank/2_MsgMultiSend/example.go
  • examples/chain/bank/query/10_BankSendEnabled/example.go
  • examples/chain/bank/query/1_BankBalance/example.go
  • examples/chain/bank/query/2_BankBalances/example.go
  • examples/chain/bank/query/3_BankSpendableBalances/example.go
  • examples/chain/bank/query/4_BankSpendableBalancesByDenom/example.go
  • examples/chain/bank/query/5_BankTotalSupply/example.go
  • examples/chain/bank/query/6_BankSupplyOf/example.go
  • examples/chain/bank/query/7_DenomMetadata/example.go
  • examples/chain/bank/query/8_DenomsMetadata/example.go
  • examples/chain/bank/query/9_DenomOwners/example.go
  • examples/chain/distribution/1_SetWithdrawAddress/example.go
  • examples/chain/distribution/2_MsgWithdrawDelegatorReward/example.go
  • examples/chain/distribution/3_WithdrawValidatorCommission/example.go
  • examples/chain/distribution/4_FundCommunityPool/example.go
  • examples/chain/distribution/query/1_ValidatorDistributionInfo/example.go
  • examples/chain/distribution/query/2_ValidatorOutstandingRewards/example.go
  • examples/chain/distribution/query/3_ValidatorCommission/example.go
  • examples/chain/distribution/query/4_ValidatorSlashes/example.go
  • examples/chain/distribution/query/5_DelegationRewards/example.go
  • examples/chain/distribution/query/6_DelegationTotalRewards/example.go
  • examples/chain/distribution/query/7_DelegatorValidators/example.go
  • examples/chain/distribution/query/8_DelegatorWithdrawAddress/example.go
  • examples/chain/distribution/query/9_CommunityPool/example.go
  • examples/chain/erc20/1_CreateTokenPair/example.go
  • examples/chain/erc20/2_DeleteTokenPair/example.go
  • examples/chain/erc20/query/1_AllTokenPairs/example.go
  • examples/chain/erc20/query/2_TokenPairByDenom/example.go
  • examples/chain/erc20/query/3_TokenPairByERC20Address/example.go
  • examples/chain/evm/query/1_Account/example.go
  • examples/chain/evm/query/2_CosmosAccount/example.go
  • examples/chain/evm/query/3_ValidatorAccount/example.go
  • examples/chain/evm/query/4_Balance/example.go
  • examples/chain/evm/query/5_Storage/example.go
  • examples/chain/evm/query/6_Code/example.go
  • examples/chain/evm/query/7_BaseFee/example.go
  • examples/chain/exchange/10_MsgCreateDerivativeLimitOrder/example.go
  • examples/chain/exchange/11_MsgCreateDerivativeMarketOrder/example.go
  • examples/chain/exchange/12_MsgCancelDerivativeOrder/example.go
  • examples/chain/exchange/13_MsgInstantBinaryOptionsMarketLaunch/example.go
  • examples/chain/exchange/14_MsgSubaccountTransfer/example.go
  • examples/chain/exchange/15_MsgExternalTransfer/example.go
  • examples/chain/exchange/16_MsgLiquidatePosition/example.go
  • examples/chain/exchange/17_MsgIncreasePositionMargin/example.go
  • examples/chain/exchange/1_MsgDeposit/example.go
  • examples/chain/exchange/21_MsgRewardsOptOut/example.go
  • examples/chain/exchange/23_MsgDecreasePositionMargin/example.go
  • examples/chain/exchange/24_MsgUpdateSpotMarket/example.go
  • examples/chain/exchange/25_MsgUpdateDerivativeMarket/example.go
  • examples/chain/exchange/26_MsgAuthorizeStakeGrants/example.go
  • examples/chain/exchange/27_MsgActivateStakeGrant/example.go
  • examples/chain/exchange/28_MsgCreateGTBSpotLimitOrder/example.go
  • examples/chain/exchange/29_MsgCreateGTBDerivativeLimitOrder/example.go
  • examples/chain/exchange/2_MsgWithdraw/example.go
  • examples/chain/exchange/30_MsgOffsetPosition/example.go
  • examples/chain/exchange/3_MsgInstantSpotMarketLaunch/example.go
  • examples/chain/exchange/4_MsgInstantPerpetualMarketLaunch/example.go
  • examples/chain/exchange/5_MsgInstantExpiryFuturesMarketLaunch/example.go
  • examples/chain/exchange/6_MsgCreateSpotLimitOrder/example.go
  • examples/chain/exchange/7_MsgCreateSpotMarketOrder/example.go
  • examples/chain/exchange/8_MsgCancelSpotOrder/example.go
  • examples/chain/exchange/9_MsgBatchUpdateOrders/example.go
  • examples/chain/exchange/query/10_SpotMarkets/example.go
  • examples/chain/exchange/query/11_SpotMarket/example.go
  • examples/chain/exchange/query/12_FullSpotMarkets/example.go
  • examples/chain/exchange/query/13_FullSpotMarket/example.go
  • examples/chain/exchange/query/14_SpotOrderbook/example.go
  • examples/chain/exchange/query/15_TraderSpotOrders/example.go
  • examples/chain/exchange/query/16_AccountAddressSpotOrders/example.go
  • examples/chain/exchange/query/17_SpotOrdersByHashes/example.go
  • examples/chain/exchange/query/18_SubaccountOrders/example.go
  • examples/chain/exchange/query/19_TraderSpotTransientOrders/example.go
  • examples/chain/exchange/query/1_SubaccountDeposits/example.go
  • examples/chain/exchange/query/20_SpotMidPriceAndTOB/example.go
  • examples/chain/exchange/query/21_DerivativeMidPriceAndTOB/example.go
  • examples/chain/exchange/query/22_DerivativeOrderbook/example.go
  • examples/chain/exchange/query/23_TraderDerivativeOrders/example.go
  • examples/chain/exchange/query/24_AccountAddressDerivativeOrders/example.go
  • examples/chain/exchange/query/25_DerivativeOrdersByHashes/example.go
  • examples/chain/exchange/query/26_TraderDerivativeTransientOrders/example.go
  • examples/chain/exchange/query/27_DerivativeMarkets/example.go
  • examples/chain/exchange/query/28_DerivativeMarket/example.go
  • examples/chain/exchange/query/29_DerivativeMarketAddress/example.go
  • examples/chain/exchange/query/2_SubaccountDeposit/example.go
  • examples/chain/exchange/query/30_SubaccountTradeNonce/example.go
  • examples/chain/exchange/query/31_Positions/example.go
  • examples/chain/exchange/query/32_SubaccountPositions/example.go
  • examples/chain/exchange/query/33_SubaccountPositionInMarket/example.go
  • examples/chain/exchange/query/34_SubaccountEffectivePositionInMarket/example.go
  • examples/chain/exchange/query/35_PerpetualMarketInfo/example.go
  • examples/chain/exchange/query/36_ExpiryFuturesMarketInfo/example.go
  • examples/chain/exchange/query/37_PerpetualMarketFunding/example.go
  • examples/chain/exchange/query/38_SubaccountOrderMetadata/example.go
  • examples/chain/exchange/query/39_TradeRewardPoints/example.go
  • examples/chain/exchange/query/3_ExchangeBalances/example.go
  • examples/chain/exchange/query/40_PendingTradeRewardPoints/example.go
  • examples/chain/exchange/query/41_TradeRewardCampaign/example.go
  • examples/chain/exchange/query/42_FeeDiscountAccountInfo/example.go
  • examples/chain/exchange/query/43_FeeDiscountSchedule/example.go
  • examples/chain/exchange/query/44_BalanceMismatches/example.go
  • examples/chain/exchange/query/45_BalanceWithBalanceHolds/example.go
  • examples/chain/exchange/query/46_FeeDiscountTierStatistics/example.go
  • examples/chain/exchange/query/47_MitoVaultInfos/example.go
  • examples/chain/exchange/query/48_QueryMarketIDFromVault/example.go
  • examples/chain/exchange/query/49_HistoricalTradeRecords/example.go
  • examples/chain/exchange/query/4_AggregateVolume/example.go
  • examples/chain/exchange/query/50_IsOptedOutOfRewards/example.go
  • examples/chain/exchange/query/51_OptedOutOfRewardsAccounts/example.go
  • examples/chain/exchange/query/52_MarketVolatility/example.go
  • examples/chain/exchange/query/53_BinaryOptionsMarkets/example.go
  • examples/chain/exchange/query/54_TraderDerivativeConditionalOrders/example.go
  • examples/chain/exchange/query/55_MarketAtomicExecutionFeeMultiplier/example.go
  • examples/chain/exchange/query/56_ActivateStakeGrant/example.go
  • examples/chain/exchange/query/57_GrantAuthorization/example.go
  • examples/chain/exchange/query/57_GrantAuthorization/injective_data/ofac.json
  • examples/chain/exchange/query/58_GrantAuthorizations/example.go
  • examples/chain/exchange/query/59_MarketBalance/example.go
  • examples/chain/exchange/query/5_AggregateVolumes/example.go
  • examples/chain/exchange/query/60_MarketBalances/example.go
  • examples/chain/exchange/query/61_DenomMinNotional/example.go
  • examples/chain/exchange/query/62_DenomMinNotionals/example.go
  • examples/chain/exchange/query/63_L3DerivativeOrderBook/example.go
  • examples/chain/exchange/query/64_L3SpotOrderBook/example.go
  • examples/chain/exchange/query/65_PositionsInMarket/example.go
  • examples/chain/exchange/query/66_OpenInterest/example.go
  • examples/chain/exchange/query/6_AggregateMarketVolume/example.go
  • examples/chain/exchange/query/7_AggregateMarketVolumes/example.go
  • examples/chain/exchange/query/8_AuctionExchangeTransferDenomDecimal/example.go
  • examples/chain/exchange/query/9_AuctionExchangeTransferDenomDecimals/example.go
  • examples/chain/ibc/channel/query/10_PacketAcknowledgements/example.go
  • examples/chain/ibc/channel/query/11_UnreceivedPackets/example.go
  • examples/chain/ibc/channel/query/12_UnreceivedAcks/example.go
  • examples/chain/ibc/channel/query/13_NextSequenceReceive/example.go
  • examples/chain/ibc/channel/query/1_Channel/example.go
  • examples/chain/ibc/channel/query/2_Channels/example.go
  • examples/chain/ibc/channel/query/3_ConnectionChannels/example.go
  • examples/chain/ibc/channel/query/4_ChannelClientState/example.go
  • examples/chain/ibc/channel/query/5_ChannelConsensusState/example.go
  • examples/chain/ibc/channel/query/6_PacketCommitment/example.go
  • examples/chain/ibc/channel/query/7_PacketCommitments/example.go
  • examples/chain/ibc/channel/query/8_PacketReceipt/example.go
  • examples/chain/ibc/channel/query/9_PacketAcknowledgement/example.go
  • examples/chain/ibc/client/query/1_ClientState/example.go
  • examples/chain/ibc/client/query/2_ClientStates/example.go
  • examples/chain/ibc/client/query/3_ConsensusState/example.go
  • examples/chain/ibc/client/query/4_ConsensusStates/example.go
  • examples/chain/ibc/client/query/5_ConsensusStateHeight/example.go
  • examples/chain/ibc/client/query/6_ClientStatus/example.go
  • examples/chain/ibc/client/query/7_ClientParams/example.go
  • examples/chain/ibc/client/query/8_UpgradedClientState/example.go
  • examples/chain/ibc/client/query/9_UpgradedConsensusState/example.go
  • examples/chain/ibc/connection/query/1_Connection/example.go
  • examples/chain/ibc/connection/query/2_Connections/example.go
  • examples/chain/ibc/connection/query/3_ClientConnections/example.go
  • examples/chain/ibc/connection/query/4_ConnectionClientState/example.go
  • examples/chain/ibc/connection/query/5_ConnectionConsensusState/example.go
  • examples/chain/ibc/connection/query/6_ConnectionParams/example.go
  • examples/chain/ibc/transfer/1_MsgTransfer/example.go
  • examples/chain/ibc/transfer/query/1_DenomTrace/example.go
  • examples/chain/ibc/transfer/query/2_DenomTraces/example.go
  • examples/chain/ibc/transfer/query/3_DenomHash/example.go
  • examples/chain/ibc/transfer/query/4_EscrowAddress/example.go
  • examples/chain/ibc/transfer/query/5_TotalEscrowForDenom/example.go
  • examples/chain/insurance/1_MsgClaimVoucher/example.go
  • examples/chain/insurance/query/1_Vouchers/example.go
  • examples/chain/insurance/query/2_Voucher/example.go
  • examples/chain/oracle/1_MsgRelayPriceFeedPrice/example.go
  • examples/chain/peggy/1_MsgSendToEth/example.go
  • examples/chain/permissions/1_MsgCreateNamespace/example.go
  • examples/chain/permissions/2_MsgUpdateNamespace/example.go
  • examples/chain/permissions/3_MsgUpdateActorRoles/example.go
  • examples/chain/permissions/4_MsgClaimVoucher/example.go
  • examples/chain/permissions/query/10_Vouchers/example.go
  • examples/chain/permissions/query/11_Voucher/example.go
  • examples/chain/permissions/query/12_PermissionsModuleState/example.go
  • examples/chain/permissions/query/1_NamespaceDenoms/example.go
  • examples/chain/permissions/query/2_Namespaces/example.go
  • examples/chain/permissions/query/3_Namespace/example.go
  • examples/chain/permissions/query/4_RolesByActor/example.go
  • examples/chain/permissions/query/5_ActorsByRole/example.go
  • examples/chain/permissions/query/6_RoleManagers/example.go
  • examples/chain/permissions/query/7_RoleManager/example.go
  • examples/chain/permissions/query/8_PolicyStatuses/example.go
  • examples/chain/permissions/query/9_PolicyManagerCapabilities/example.go
  • examples/chain/staking/1_MsgDelegate/example.go
  • examples/chain/tendermint/query/1_GetNodeInfo/example.go
  • examples/chain/tendermint/query/2_GetSyncing/example.go
  • examples/chain/tendermint/query/3_GetLatestBlock/example.go
  • examples/chain/tendermint/query/4_GetBlockByHeight/example.go
  • examples/chain/tendermint/query/5_GetLatestValidatorSet/example.go
  • examples/chain/tendermint/query/6_GetValidatorSetByHeight/example.go
  • examples/chain/tokenfactory/1_CreateDenom/example.go
  • examples/chain/tokenfactory/2_MsgMint/example.go
  • examples/chain/tokenfactory/3_MsgBurn/example.go
  • examples/chain/tokenfactory/4_MsgSetDenomMetadata/example.go
  • examples/chain/tokenfactory/5_MsgChangeAdmin/example.go
  • examples/chain/tokenfactory/query/1_DenomAuthorityMetadata/example.go
  • examples/chain/tokenfactory/query/2_DenomsFromCreator/example.go
  • examples/chain/tokenfactory/query/3_TokenfactoryModuleState/example.go
  • examples/chain/tx/query/1_GetTx/example.go
  • examples/chain/txfees/query/1_GetEipBaseFee/example.go
  • examples/chain/wasm/query/10_ContractsByCreator/example.go
  • examples/chain/wasm/query/1_ContractInfo/example.go
  • examples/chain/wasm/query/2_ContractHistory/example.go
  • examples/chain/wasm/query/3_ContractsByCode/example.go
  • examples/chain/wasm/query/4_AllContractsState/example.go
  • examples/chain/wasm/query/5_RawContractState/example.go
  • examples/chain/wasm/query/6_SmartContractState/example.go
  • examples/chain/wasm/query/7_SmartContractCode/example.go
  • examples/chain/wasm/query/8_SmartContractCodes/example.go
  • examples/chain/wasm/query/9_SmartContractPinnedCodes/example.go
  • examples/chain/wasmx/1_MsgExecuteContractCompat/example.go
  • examples/exchange/oracle/1_StreamPrices/example.go
  • examples/exchange/oracle/1_StreamPrices/injective_data/ofac.json
  • examples/exchange/oracle/2_Price/example.go
  • examples/exchange/oracle/4_PriceV2/example.go
  • examples/exchange/oracle/5_StreamOracleList/example.go
  • examples/exchange/oracle/6_StreamPricesByMarkets/example.go
💤 Files with no reviewable changes (2)
  • examples/chain/exchange/query/57_GrantAuthorization/injective_data/ofac.json
  • examples/exchange/oracle/1_StreamPrices/injective_data/ofac.json

Comment on lines +351 to +385
func (p *Position) ApplyBankruptCloseWithoutPayouts(
closingPrice, closingQuantity math.LegacyDec,
) (pnl math.LegacyDec, positionDelta *PositionDelta) {
if p == nil {
return math.LegacyZeroDec(), nil
}

if p.Quantity.IsZero() || closingQuantity.IsZero() {
return math.LegacyZeroDec(), &PositionDelta{
IsLong: !p.IsLong,
ExecutionQuantity: math.LegacyZeroDec(),
ExecutionMargin: math.LegacyZeroDec(),
ExecutionPrice: closingPrice,
}
}

closingQuantity = math.LegacyMinDec(p.Quantity, closingQuantity)
positionDelta = &PositionDelta{
IsLong: !p.IsLong,
ExecutionQuantity: closingQuantity,
ExecutionMargin: math.LegacyZeroDec(),
ExecutionPrice: closingPrice,
}

pnl = p.GetPayoutFromPnl(closingPrice, closingQuantity)
remainingMargin := p.Margin.Add(pnl)
remainingQuantity := p.Quantity.Sub(closingQuantity)

if remainingQuantity.IsZero() {
p.ClosePositionWithoutPayouts()
return pnl, positionDelta
}

p.Quantity = remainingQuantity
p.Margin = remainingMargin
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Guard closingQuantity and fix the partial-close margin accounting.

A negative closingQuantity currently makes this method increase p.Quantity (remainingQuantity := p.Quantity.Sub(closingQuantity)), and the partial-close path keeps all pre-close margin on the reduced position via p.Margin = p.Margin.Add(pnl). That produces invalid state unless callers always pass the exact bankruptcy price for the closed slice. Please reject negative quantities up front and apportion/remove the closed slice’s margin explicitly in the partial-close branch.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/exchange/types/v2/position.go` around lines 351 - 385, In
ApplyBankruptCloseWithoutPayouts, guard against a negative closingQuantity by
returning early (e.g., return math.LegacyZeroDec(), nil) when
closingQuantity.IsNegative(); then compute the closed slice's margin and remove
it from the remaining position instead of keeping the whole pre-close margin:
capture origMargin := p.Margin and origQty := p.Quantity, compute closedMargin
:= origMargin.Mul(closingQuantity.Quo(origQty)) (use LegacyDec Mul/Quo), compute
pnl := p.GetPayoutFromPnl(closingPrice, closingQuantity) as you already do, and
set remainingMargin := origMargin.Sub(closedMargin).Add(pnl); set
remainingQuantity := origQty.Sub(closingQuantity); if remainingQuantity.IsZero()
call p.ClosePositionWithoutPayouts() else assign p.Quantity = remainingQuantity
and p.Margin = remainingMargin; keep constructing PositionDelta as you already
do (ExecutionQuantity = closingQuantity, ExecutionPrice = closingPrice, IsLong =
!p.IsLong).

Comment on lines +8 to +23
func NewPythPriceState(
priceID common.Hash,
emaPrice, emaConf, conf math.LegacyDec,
publishTime int64,
price math.LegacyDec,
blockTime int64,
) *PythPriceState {
return &PythPriceState{
PriceId: priceID.Hex(),
EmaPrice: emaPrice,
EmaConf: emaConf,
Conf: conf,
PublishTime: uint64(publishTime),
PriceState: *NewPriceState(price, blockTime),
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid wrapping negative publish times into huge uint64 values.

Line 20 converts publishTime from int64 to uint64 without validation. A negative input becomes a very large timestamp instead of being rejected, which lets this helper construct an invalid PythPriceState.

💡 Safer direction
 func NewPythPriceState(
 	priceID common.Hash,
 	emaPrice, emaConf, conf math.LegacyDec,
-	publishTime int64,
+	publishTime uint64,
 	price math.LegacyDec,
 	blockTime int64,
 ) *PythPriceState {
 	return &PythPriceState{
 		PriceId:     priceID.Hex(),
 		EmaPrice:    emaPrice,
 		EmaConf:     emaConf,
 		Conf:        conf,
-		PublishTime: uint64(publishTime),
+		PublishTime: publishTime,
 		PriceState:  *NewPriceState(price, blockTime),
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func NewPythPriceState(
priceID common.Hash,
emaPrice, emaConf, conf math.LegacyDec,
publishTime int64,
price math.LegacyDec,
blockTime int64,
) *PythPriceState {
return &PythPriceState{
PriceId: priceID.Hex(),
EmaPrice: emaPrice,
EmaConf: emaConf,
Conf: conf,
PublishTime: uint64(publishTime),
PriceState: *NewPriceState(price, blockTime),
}
}
func NewPythPriceState(
priceID common.Hash,
emaPrice, emaConf, conf math.LegacyDec,
publishTime uint64,
price math.LegacyDec,
blockTime int64,
) *PythPriceState {
return &PythPriceState{
PriceId: priceID.Hex(),
EmaPrice: emaPrice,
EmaConf: emaConf,
Conf: conf,
PublishTime: publishTime,
PriceState: *NewPriceState(price, blockTime),
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/oracle/types/pyth.go` around lines 8 - 23, NewPythPriceState currently
converts publishTime int64 to uint64 directly which silently wraps negative
times; update NewPythPriceState to validate publishTime is >= 0 and return an
error for negative values (change signature to NewPythPriceState(...)
(*PythPriceState, error)), or alternatively accept a uint64 publishTime so
callers must provide a non-negative value; ensure you adjust the creation of
PythPriceState.PriceState to use NewPriceState(price, blockTime) as before and
update all callers to handle the new error/return signature.

Comment on lines +42 to +49
func (p *PriceAttestation) GetPriceIDHash() common.Hash {
return common.HexToHash(p.PriceId)
}

func (p *PriceAttestation) Validate() error {
if len(p.GetPriceIDHash().Bytes()) != 32 {
return ErrInvalidPythPriceID
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In go-ethereum v1.15.x, what does common.HexToHash do with short or malformed hex strings, and does common.Hash.Bytes() always return 32 bytes?

💡 Result:

In go-ethereum v1.15.x, common.HexToHash(s string) Hash converts the hex string s (with optional "0x" prefix) to a common.Hash by first calling FromHex(s), which strips the prefix if present, pads odd-length hex strings with a leading zero, and decodes using hex.DecodeString (ignoring decode errors). The resulting bytes are then converted to a fixed-size [32]byte Hash via BytesToHash, which right-pads short byte arrays with zeros to 32 bytes or takes the rightmost 32 bytes if longer. For short hex strings (e.g., fewer than 64 hex chars), it produces a Hash with leading zero bytes (right-padded). For malformed hex strings (invalid chars), hex.DecodeString returns partial bytes up to the first invalid char (no error returned), so it produces a Hash from those bytes (right-padded if short). common.Hash.Bytes always returns a 32-byte slice, as Hash is type [32]byte and Bytes returns h[:], the full fixed array. v1.15.x releases (e.g., v1.15.8) use the same common package implementation as shown in master and v1.14.12 sources.

Citations:


🏁 Script executed:

# First, locate and read the pyth.go file
fd -t f "pyth.go" | head -5

Repository: InjectiveLabs/sdk-go

Length of output: 91


🏁 Script executed:

# Find the pyth.go file
find . -name "pyth.go" -type f 2>/dev/null

Repository: InjectiveLabs/sdk-go

Length of output: 93


🏁 Script executed:

# Read the pyth.go file to verify the code
cat -n chain/oracle/types/pyth.go | head -80

Repository: InjectiveLabs/sdk-go

Length of output: 2226


🏁 Script executed:

# Check the imports in the file
head -20 chain/oracle/types/pyth.go

Repository: InjectiveLabs/sdk-go

Length of output: 483


The price ID length check is ineffective.

common.HexToHash always normalizes input into a fixed 32-byte common.Hash, padding short byte sequences with zeros. The check len(p.GetPriceIDHash().Bytes()) != 32 will always succeed regardless of input validity, failing to reject short or malformed hex strings (e.g., "0x1", "0xZZ"). Validate the original hex string before conversion instead.

🔎 Suggested fix
 import (
+	"encoding/hex"
+	"strings"
+
 	"cosmossdk.io/math"
 	"github.com/ethereum/go-ethereum/common"
 )
@@
 func (p *PriceAttestation) Validate() error {
-	if len(p.GetPriceIDHash().Bytes()) != 32 {
+	raw := strings.TrimPrefix(p.PriceId, "0x")
+	decoded, err := hex.DecodeString(raw)
+	if err != nil || len(decoded) != common.HashLength {
 		return ErrInvalidPythPriceID
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (p *PriceAttestation) GetPriceIDHash() common.Hash {
return common.HexToHash(p.PriceId)
}
func (p *PriceAttestation) Validate() error {
if len(p.GetPriceIDHash().Bytes()) != 32 {
return ErrInvalidPythPriceID
}
func (p *PriceAttestation) GetPriceIDHash() common.Hash {
return common.HexToHash(p.PriceId)
}
func (p *PriceAttestation) Validate() error {
raw := strings.TrimPrefix(p.PriceId, "0x")
decoded, err := hex.DecodeString(raw)
if err != nil || len(decoded) != common.HashLength {
return ErrInvalidPythPriceID
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/oracle/types/pyth.go` around lines 42 - 49, The current check in
PriceAttestation.Validate is ineffective because GetPriceIDHash uses
common.HexToHash which always returns a 32-byte value; instead, validate the raw
p.PriceId string itself: strip an optional "0x" prefix, verify the hex string
length equals 64 characters (32 bytes), attempt to hex-decode it (e.g., with
hex.DecodeString) and return ErrInvalidPythPriceID if decoding fails or length
is wrong; after this validation you can still use GetPriceIDHash() safely.
Ensure you update PriceAttestation.Validate (and keep ErrInvalidPythPriceID) and
do not rely on common.HexToHash for input validation.

Comment thread chain/peggy/types/key.go
Comment on lines +120 to +121
RateLimitKey = []byte{0x1e}
MintAmountERC20Key = []byte{0x1f}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep deprecated aliases for the renamed exported keys.

Lines 120-121 rename exported symbols in a public package. That is a source-breaking change for downstream consumers still importing RateLimitsKey or MintAmountsERC20Key, even though the underlying prefix bytes did not change. Please keep the old names as deprecated aliases for this release and remove them in the next major version instead.

Suggested compatibility shim
 var (
-	RateLimitKey           = []byte{0x1e}
-	MintAmountERC20Key     = []byte{0x1f}
+	RateLimitKey       = []byte{0x1e}
+	// Deprecated: use RateLimitKey.
+	RateLimitsKey      = RateLimitKey
+	MintAmountERC20Key = []byte{0x1f}
+	// Deprecated: use MintAmountERC20Key.
+	MintAmountsERC20Key = MintAmountERC20Key
 	RateLimitInflowKey     = []byte{0x20}
 	RateLimitOutflowKey    = []byte{0x21}
 	RateLimitNetOutflowKey = []byte{0x22}
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/peggy/types/key.go` around lines 120 - 121, Add deprecated aliases for
the renamed exported keys so downstream consumers don’t break: keep the new
exported constants RateLimitKey and MintAmountERC20Key as-is and add variables
with the old names RateLimitsKey and MintAmountsERC20Key that point to those
same byte slices (marked/decorated as deprecated in comments). Update key.go to
define RateLimitsKey = RateLimitKey and MintAmountsERC20Key = MintAmountERC20Key
so the underlying prefix bytes remain unchanged while preserving the old symbol
names for this release.

Comment thread chain/peggy/types/msgs.go
Comment on lines +556 to +563
return tmhash.Sum([]byte(fmt.Sprintf("%d/%d/%d/%s/%s/%s",
b.ValsetNonce,
b.EventNonce,
b.BlockHeight,
b.Members,
b.RewardToken,
b.RewardAmount.String(),
)))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate MsgValsetUpdatedClaim and inspect Members type =="
rg -n -C2 'type MsgValsetUpdatedClaim struct|Members ' --glob '*.go'

echo
echo "== Inspect this ClaimHash implementation =="
rg -n -C3 'func \(b \*MsgValsetUpdatedClaim\) ClaimHash\(\)' --glob '*.go'

echo
echo "== Find chain/sdk peers that serialize valset members for hashing =="
rg -n -C3 'ValsetUpdatedClaim|ClaimHash\(\)|EthereumAddress.*Power|strings\.Join\(members' --glob '*.go'

Repository: InjectiveLabs/sdk-go

Length of output: 36515


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find BridgeValidator struct definition =="
rg -n 'type BridgeValidator struct' --glob '*.go' -A 10

echo
echo "== Check if there are canonical serialization patterns for members elsewhere =="
rg -n 'for.*Members|for.*members' --glob 'chain/peggy/types/*.go' -B 2 -A 3 | head -80

echo
echo "== Look for any existing member serialization in chain code =="
rg -n 'EthereumAddress.*Power|marshal.*[Mm]ember' --glob 'chain/peggy/**/*.go' -i | head -40

Repository: InjectiveLabs/sdk-go

Length of output: 5832


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat > /tmp/test_format.go << 'EOF'
package main

import (
	"fmt"
)

type BridgeValidator struct {
	Power           uint64
	EthereumAddress string
}

func main() {
	members := []*BridgeValidator{
		{Power: 1, EthereumAddress: "0xabc123"},
		{Power: 2, EthereumAddress: "0xdef456"},
	}
	
	// Test what %s produces
	output := fmt.Sprintf("%s", members)
	fmt.Printf("Output with %%s: %s\n", output)
	fmt.Printf("Output length: %d\n", len(output))
	
	// Test multiple times to check if deterministic
	output2 := fmt.Sprintf("%s", members)
	fmt.Printf("Second output matches first: %v\n", output == output2)
	
	// What about with %v?
	output3 := fmt.Sprintf("%v", members)
	fmt.Printf("Output with %%v: %s\n", output3)
}
EOF

go run /tmp/test_format.go 2>&1 || echo "Go test failed - checking environment"

Repository: InjectiveLabs/sdk-go

Length of output: 264


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Get the full ClaimHash method and context =="
sed -n '554,565p' chain/peggy/types/msgs.go

echo
echo "== Check what other ClaimHash methods look like =="
rg -n 'func \(.*\) ClaimHash\(\)' --glob 'chain/peggy/types/*.go' -A 5 | head -100

Repository: InjectiveLabs/sdk-go

Length of output: 2124


Use canonical member serialization instead of %s for the Members field.

b.Members is []*BridgeValidator, not a string. Using %s produces Go's error marker format (%!s(...)) rather than the validator contents, which breaks deterministic hashing. Since ClaimHash() is the canonical claim identifier for validator agreement, non-canonical serialization will cause hash mismatches with the chain and other clients, invalidating claim consensus.

Suggested fix
+members := make([]string, 0, len(b.Members))
+for _, m := range b.Members {
+	members = append(members, fmt.Sprintf("%s/%d", m.EthereumAddress, m.Power))
+}
-	return tmhash.Sum([]byte(fmt.Sprintf("%d/%d/%d/%s/%s/%s",
+	return tmhash.Sum([]byte(fmt.Sprintf("%d/%d/%d/%s/%s/%s",
 		b.ValsetNonce,
 		b.EventNonce,
 		b.BlockHeight,
-		b.Members,
+		strings.Join(members, ","),
 		b.RewardToken,
 		b.RewardAmount.String(),
 	)))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chain/peggy/types/msgs.go` around lines 556 - 563, The Members field
(b.Members, type []*BridgeValidator) is being printed with "%s", producing
non-canonical "%!s(...)" output and breaking deterministic hashing in
ClaimHash(); replace that with a deterministic serialization: iterate over
b.Members in order and build a canonical string (e.g., join(fmt.Sprintf("%s/%d",
member.GetAddress(), member.Power) for each member) or marshal each member with
a deterministic codec) and use that canonical string in the tmhash.Sum input so
ClaimHash() hashes the explicit, ordered validator contents rather than Go's
default "%s" representation.

Comment on lines +65 to +71
res, err := chainClient.FetchAuctionVouchers(ctx, denom)
if err != nil {
fmt.Println(err)
}

str, _ := json.MarshalIndent(res, "", "\t")
fmt.Print(string(str))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Stop on query/marshal failures instead of printing misleading output.

If FetchAuctionVouchers fails, the example still continues to marshal/print the zero-value response and exits successfully. Line 70 also drops the marshal error. This makes broken setups look like successful runs.

Suggested fix
 	res, err := chainClient.FetchAuctionVouchers(ctx, denom)
 	if err != nil {
-		fmt.Println(err)
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
 	}
 
-	str, _ := json.MarshalIndent(res, "", "\t")
+	str, err := json.MarshalIndent(res, "", "\t")
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
 	fmt.Print(string(str))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
res, err := chainClient.FetchAuctionVouchers(ctx, denom)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", "\t")
fmt.Print(string(str))
res, err := chainClient.FetchAuctionVouchers(ctx, denom)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
str, err := json.MarshalIndent(res, "", "\t")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Print(string(str))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/auction/query/1_Vouchers/example.go` around lines 65 - 71, If
FetchAuctionVouchers (call to chainClient.FetchAuctionVouchers) returns an
error, stop the example instead of continuing: check err and return/exit
non‑zero with a helpful message; do the same for json.MarshalIndent — check its
error and abort on failure. Concretely, after calling FetchAuctionVouchers, if
err != nil log/print the error and os.Exit(1) (or return), and when calling
json.MarshalIndent(res, "", "\t") capture the marshal error, handle it the same
way instead of ignoring it; this ensures you don't print a zero-value res on
failures and the example returns a non‑zero status on errors.

)

func main() {
_ = godotenv.Load()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In github.com/joho/godotenv v1.5.1, when godotenv.Load() is called with no arguments, does it only read .env from the current working directory, or does it also search parent directories?

💡 Result:

In github.com/joho/godotenv v1.5.1, when godotenv.Load is called with no arguments, it only reads .env from the current working directory. It does not search parent directories.

Citations:


godotenv.Load() is cwd-dependent here.

These examples sit several directories below the repo root. Calling Load() without arguments only reads .env from the current working directory, so running go run example.go from this folder will not pick up a repo-level .env file. Either resolve the file path explicitly or document that examples must be run from the repository root.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/ibc/channel/query/10_PacketAcknowledgements/example.go` at
line 21, The call to godotenv.Load() in example.go is cwd-dependent and won't
find the repo-level .env when running the example from its folder; update the
example to load the .env via an explicit path instead of relying on the working
directory (e.g., resolve the example file's directory with runtime.Caller or
compute the repo-root relative path and call godotenv.Load(resolvedPath)) so the
.env is loaded predictably when running the example; change the godotenv.Load()
invocation in this file to load the resolved path.

Comment on lines +65 to +71
res, err := chainClient.FetchInsuranceVouchers(ctx, denom)
if err != nil {
fmt.Println(err)
}

str, _ := json.MarshalIndent(res, "", "\t")
fmt.Print(string(str))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fail fast when the query or JSON encoding fails.

This example prints the fetch error but still marshals and prints the response, so a failed run can still look successful. The marshal error is also ignored.

Suggested fix
 	res, err := chainClient.FetchInsuranceVouchers(ctx, denom)
 	if err != nil {
-		fmt.Println(err)
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
 	}
 
-	str, _ := json.MarshalIndent(res, "", "\t")
+	str, err := json.MarshalIndent(res, "", "\t")
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
 	fmt.Print(string(str))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
res, err := chainClient.FetchInsuranceVouchers(ctx, denom)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", "\t")
fmt.Print(string(str))
res, err := chainClient.FetchInsuranceVouchers(ctx, denom)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
str, err := json.MarshalIndent(res, "", "\t")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Print(string(str))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain/insurance/query/1_Vouchers/example.go` around lines 65 - 71,
The example currently ignores errors from chainClient.FetchInsuranceVouchers and
json.MarshalIndent and proceeds to print potentially invalid output; modify the
handler around chainClient.FetchInsuranceVouchers(ctx, denom) so that if err !=
nil you fail fast (return or log.Fatal/exit) instead of continuing, and check
the error returned by json.MarshalIndent(res, "", "\t") storing to str and err
(or marshalErr) and fail fast on marshal errors as well; update references to
res, err, and str so errors are handled immediately after each call to
FetchInsuranceVouchers and json.MarshalIndent.

Comment thread examples/exchange/oracle/6_StreamPricesByMarkets/example.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/exchange/oracle/6_StreamPricesByMarkets/example.go`:
- Around line 21-25: The comment for market selection is inconsistent: the
variable marketIds in example.go is documented as "Pass an empty slice to
receive price updates for all markets" but is populated with two explicit market
IDs; either make marketIds an empty slice to match the comment or update the
comment to state that these two IDs will limit updates to those markets. Locate
the marketIds declaration in the 6_StreamPricesByMarkets example and choose one
fix: set marketIds to an empty slice (to subscribe to all markets) or change the
comment to describe that the listed IDs (e.g., the INJ/USDT and BTC/USDT perp
IDs) restrict updates to those markets.
- Around line 42-43: The code currently ignores the error returned by
json.MarshalIndent when serializing res; update the example (around the
stream.Recv() handling that produces res) to check the error from
json.MarshalIndent(res, "", "\t") and handle it explicitly: if marshalling
fails, print/log the error (e.g., fmt.Fprintf(os.Stderr, "marshal error: %v\n",
err)) and return or continue as appropriate instead of discarding the error,
then only call fmt.Print(string(str)) when err == nil so the example
demonstrates proper error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8cde9115-d881-429f-a04d-33e34bb10a1c

📥 Commits

Reviewing files that changed from the base of the PR and between 955379a and 0650b1b.

📒 Files selected for processing (1)
  • examples/exchange/oracle/6_StreamPricesByMarkets/example.go

Comment on lines +21 to +25
// Pass an empty slice to receive price updates for all markets.
marketIds := []string{
"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", // INJ/USDT perp
"0x54d4505adef6a5cef26bc403a33d595620ded4e15b9e2bc3dd489b714813366a", // BTC/USDT perp
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Comment and implementation conflict on market selection.

Line 21 says an empty slice is used to receive all markets, but Lines 22-25 pass two explicit market IDs. Please align the comment with the actual example behavior (or make the slice empty).

✏️ Suggested fix
-	// Pass an empty slice to receive price updates for all markets.
+	// Pass specific market IDs to receive price updates for those markets.
 	marketIds := []string{
 		"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", // INJ/USDT perp
 		"0x54d4505adef6a5cef26bc403a33d595620ded4e15b9e2bc3dd489b714813366a", // BTC/USDT perp
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Pass an empty slice to receive price updates for all markets.
marketIds := []string{
"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", // INJ/USDT perp
"0x54d4505adef6a5cef26bc403a33d595620ded4e15b9e2bc3dd489b714813366a", // BTC/USDT perp
}
// Pass specific market IDs to receive price updates for those markets.
marketIds := []string{
"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", // INJ/USDT perp
"0x54d4505adef6a5cef26bc403a33d595620ded4e15b9e2bc3dd489b714813366a", // BTC/USDT perp
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/exchange/oracle/6_StreamPricesByMarkets/example.go` around lines 21
- 25, The comment for market selection is inconsistent: the variable marketIds
in example.go is documented as "Pass an empty slice to receive price updates for
all markets" but is populated with two explicit market IDs; either make
marketIds an empty slice to match the comment or update the comment to state
that these two IDs will limit updates to those markets. Locate the marketIds
declaration in the 6_StreamPricesByMarkets example and choose one fix: set
marketIds to an empty slice (to subscribe to all markets) or change the comment
to describe that the listed IDs (e.g., the INJ/USDT and BTC/USDT perp IDs)
restrict updates to those markets.

Comment on lines +42 to +43
str, _ := json.MarshalIndent(res, "", "\t")
fmt.Print(string(str))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "example.go" -path "*/6_StreamPricesByMarkets/*" -type f

Repository: InjectiveLabs/sdk-go

Length of output: 126


🏁 Script executed:

sed -n '35,50p' ./examples/exchange/oracle/6_StreamPricesByMarkets/example.go

Repository: InjectiveLabs/sdk-go

Length of output: 252


🏁 Script executed:

sed -n '20,50p' ./examples/exchange/oracle/6_StreamPricesByMarkets/example.go

Repository: InjectiveLabs/sdk-go

Length of output: 667


🏁 Script executed:

sed -n '1,35p' ./examples/exchange/oracle/6_StreamPricesByMarkets/example.go

Repository: InjectiveLabs/sdk-go

Length of output: 857


Handle JSON marshal failures explicitly.

Line 42 discards the json.MarshalIndent error, which can hide serialization failures and print incomplete output. Although res is guaranteed valid from the preceding stream.Recv() check, explicit error handling demonstrates proper patterns for example code.

🛠️ Suggested fix
-			str, _ := json.MarshalIndent(res, "", "\t")
-			fmt.Print(string(str))
+			str, err := json.MarshalIndent(res, "", "\t")
+			if err != nil {
+				fmt.Println(err)
+				continue
+			}
+			fmt.Print(string(str))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
str, _ := json.MarshalIndent(res, "", "\t")
fmt.Print(string(str))
str, err := json.MarshalIndent(res, "", "\t")
if err != nil {
fmt.Println(err)
continue
}
fmt.Print(string(str))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/exchange/oracle/6_StreamPricesByMarkets/example.go` around lines 42
- 43, The code currently ignores the error returned by json.MarshalIndent when
serializing res; update the example (around the stream.Recv() handling that
produces res) to check the error from json.MarshalIndent(res, "", "\t") and
handle it explicitly: if marshalling fails, print/log the error (e.g.,
fmt.Fprintf(os.Stderr, "marshal error: %v\n", err)) and return or continue as
appropriate instead of discarding the error, then only call
fmt.Print(string(str)) when err == nil so the example demonstrates proper error
handling.

@aarmoa aarmoa merged commit ce7baf2 into master Apr 27, 2026
5 of 6 checks passed
@aarmoa aarmoa deleted the release/update_master_for_v1_61 branch April 27, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant