Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
kalshi (0.0.1)
kalshi (0.0.2)
dry-cli
dry-configurable
dry-container
Expand Down Expand Up @@ -230,7 +230,7 @@ CHECKSUMS
httpx (1.7.0) sha256=e219689555951f9c13c40862da120cdd2535e1454189bed589f04d7059557154
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
json (2.18.0) sha256=b10506aee4183f5cf49e0efc48073d7b75843ce3782c68dbeb763351c08fd505
kalshi (0.0.1)
kalshi (0.0.2)
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
Expand Down
26 changes: 26 additions & 0 deletions Readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,32 @@ candlesticks = client.market.candlesticks.batch(
)
----

=== Search

Access Search endpoints via the `search` namespace.

==== Tags by Category

https://docs.kalshi.com/api-reference/search/get-tags-for-series-categories[API Reference]

Get tags organized by series categories:

[source,ruby]
----
tags = client.search.tags_by_category
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The method name in the documentation doesn't match the actual implementation. The code implements tags_by_categories (plural) but the documentation shows tags_by_category (singular). Update the documentation to match the implementation.

Copilot uses AI. Check for mistakes.
----

==== Filters by Sport

https://docs.kalshi.com/api-reference/search/get-filters-for-sports[API Reference]

Get filters organized by sport:

[source,ruby]
----
filters = client.search.filters_by_sport
Comment on lines +174 to +182
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The method name in the documentation doesn't match the actual implementation. The code implements filters_by_sports (plural) but the documentation shows filters_by_sport (singular). Update the documentation to match the implementation.

Suggested change
==== Filters by Sport
https://docs.kalshi.com/api-reference/search/get-filters-for-sports[API Reference]
Get filters organized by sport:
[source,ruby]
----
filters = client.search.filters_by_sport
==== Filters by Sports
https://docs.kalshi.com/api-reference/search/get-filters-for-sports[API Reference]
Get filters organized by sports:
[source,ruby]
----
filters = client.search.filters_by_sports

Copilot uses AI. Check for mistakes.
----

=== WebSocket Client

A raw WebSocket client is included in `bin/wss-raw` for testing connection and subscription.
Expand Down
14 changes: 14 additions & 0 deletions lib/kalshi/api_client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Rubyists
module Kalshi
# API Client Base Class
class ApiClient
attr_reader :client

def initialize(client)
@client = client
end
end
Comment on lines +1 to +12
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The new ApiClient base class duplicates the exact pattern from Market::Client (attr_reader :client and initialize method). Consider having Market::Client inherit from ApiClient to avoid duplication and maintain consistency across API client implementations.

Copilot uses AI. Check for mistakes.
end
end
4 changes: 4 additions & 0 deletions lib/kalshi/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ def market
@market ||= Market::Client.new(clone)
end

def search
@search ||= Search::Client.new(clone)
end

private

def full_url(path)
Expand Down
18 changes: 18 additions & 0 deletions lib/kalshi/search/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Rubyists
module Kalshi
module Search
# Search API Client
class Client < ApiClient
def tags_by_categories
SeriesTags.new(client).all
end

def filters_by_sports
SportsFilters.new(client).all
Comment on lines +9 to +13
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Consider adding memoization for the SportsFilters instance to match the pattern used in Market::Client. The endpoint classes should be instantiated once and reused, similar to how series_list, markets, and other endpoints are memoized with ||= in the Market::Client implementation.

Suggested change
SeriesTags.new(client).all
end
def filters_by_sports
SportsFilters.new(client).all
@series_tags ||= SeriesTags.new(client)
@series_tags.all
end
def filters_by_sports
@sports_filters ||= SportsFilters.new(client)
@sports_filters.all

Copilot uses AI. Check for mistakes.
end
Comment on lines +9 to +14
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Consider adding memoization for the SeriesTags instance to match the pattern used in Market::Client. The endpoint classes should be instantiated once and reused, similar to how series_list, markets, and other endpoints are memoized with ||= in the Market::Client implementation.

Suggested change
SeriesTags.new(client).all
end
def filters_by_sports
SportsFilters.new(client).all
end
series_tags.all
end
def filters_by_sports
sports_filters.all
end
private
def series_tags
@series_tags ||= SeriesTags.new(client)
end
def sports_filters
@sports_filters ||= SportsFilters.new(client)
end

Copilot uses AI. Check for mistakes.
end
end
end
end
14 changes: 14 additions & 0 deletions lib/kalshi/search/series_tags.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Rubyists
module Kalshi
module Search
# Series Tags API endpoint
class SeriesTags < Kalshi::Endpoint
def all
client.get('search/tags_by_categories')
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/kalshi/search/sports_filters.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Rubyists
module Kalshi
module Search
# Sports Filters API endpoint
class SportsFilters < Kalshi::Endpoint
def all
client.get('search/filters_by_sports')
end
end
end
end
end
8 changes: 8 additions & 0 deletions test/kalshi/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
assert_instance_of Rubyists::Kalshi::Market::Client, client.market
end
end

describe '#search' do
it 'returns a Search::Client instance' do
client = Rubyists::Kalshi::Client.new

assert_instance_of Rubyists::Kalshi::Search::Client, client.search
end
end
Comment on lines +29 to +35
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Missing memoization test for the search method. Following the existing pattern established for the market method in this file and the Market::Client tests, you should add a test to verify that multiple calls to client.search return the same instance using assert_same.

Copilot uses AI. Check for mistakes.
end

describe Rubyists::Kalshi do
Expand Down
31 changes: 31 additions & 0 deletions test/kalshi/search/client_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require_relative '../../helper'

describe Rubyists::Kalshi::Search::Client do
let(:client) { Rubyists::Kalshi::Client.new }
let(:search_client) { client.search }
let(:base_url) { Rubyists::Kalshi.config.base_url }

describe '#tags_by_categories' do
it 'fetches tags by categories' do
stub_request(:get, "#{base_url}/search/tags_by_categories")
.to_return(status: 200, body: '{"tags_by_categories": {}}', headers: { 'Content-Type' => 'application/json' })

response = search_client.tags_by_categories

assert_equal({ tags_by_categories: {} }, response)
end
end
Comment on lines +10 to +19
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Missing test coverage for memoization behavior. Following the pattern in test/kalshi/market/client_test.rb, you should add tests to verify that SeriesTags instances are memoized when tags_by_categories is called multiple times. This ensures consistent behavior across API client implementations.

Copilot uses AI. Check for mistakes.

describe '#filters_by_sports' do
it 'fetches filters by sports' do
stub_request(:get, "#{base_url}/search/filters_by_sports")
.to_return(status: 200, body: '{"filters_by_sports": {}}', headers: { 'Content-Type' => 'application/json' })

response = search_client.filters_by_sports

assert_equal({ filters_by_sports: {} }, response)
end
end
Comment on lines +21 to +30
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Missing test coverage for memoization behavior. Following the pattern in test/kalshi/market/client_test.rb, you should add tests to verify that SportsFilters instances are memoized when filters_by_sports is called multiple times. This ensures consistent behavior across API client implementations.

Copilot uses AI. Check for mistakes.
end