Skip to content

Commit f47d173

Browse files
authored
feat: adds matching markets for sports by date, ticker, or slug (#7)
* feat: adds matching markets for sports by date, ticker, or slug * test: removes :nocov: from params blocks. They are working now * ci: adds copilot instructions * test: adds spec for market_matchers method
1 parent c0374b9 commit f47d173

File tree

15 files changed

+373
-24
lines changed

15 files changed

+373
-24
lines changed

.github/copilot-instructions.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copilot Code Review Guidelines
2+
3+
---
4+
This file configures GitHub Copilot Code Review according to GitHub’s official guidance: [Use Copilot Code Review](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/request-a-code-review/use-code-review).
5+
6+
## Project Context
7+
8+
**Language:** Ruby ~> 4
9+
**Framework:** [trailblazer](https://trailblazer.to/)
10+
**Testing:** [minitest](https://docs.seattlerb.org/minitest/) following [BetterSpecs](https://evenbetterspecs.github.io/) guidelines
11+
12+
---
13+
14+
## Purpose & Scope
15+
16+
Focused inline review guidance for Ruby pull requests—style, tests, performance, and tone. (CI setup, contributor workflows, and documentation policies belong in separate docs.)
17+
18+
---
19+
20+
## 1. Style Guides
21+
22+
> ⚠️ **Be constructive:** Frame style feedback as suggestions (e.g., “Consider using…”).
23+
24+
All standard rules follow the [Shopify Ruby Style Guide](https://ruby-style-guide.shopify.dev/); only team-specific overrides are listed below:
25+
- Indentation and line length enforced by RuboCop per project config.
26+
- Use guard clauses, and explicit receivers.
27+
- Prefer Railway Oriented Programming (ROP) for error handling and flow.
28+
- Leverage dry-rb conventions and Trailblazer patterns for clarity and maintainability.
29+
- Keep methods short. 1 line is fine. 5 is a lot. At 7, you should consider extracting a method.
30+
31+
---
32+
33+
## 2. Tone and Delivery
34+
35+
> 🤝 **Be succinct:** Don't overwhelm with too many minor issues; prioritize key improvements.
36+
37+
- Use phrasing like “Consider extracting…” or “You might simplify…” rather than absolutes.
38+
- Keep comments concise—2–3 sentences max.
39+
40+
---
41+
42+
## 3. Conventions & Readability
43+
44+
> **Keep it clear:** Propose naming and structure that clarify intent.
45+
46+
- **SOLID principles:** Single responsibility; inject dependencies via initializers.
47+
- **Descriptive names:** Recommend clear class, method, and variable names.
48+
- **DRY:** Suggest extracting duplicate logic into modules or service objects.
49+
- **Method size:** Flag methods >= 8 lines; suggest splitting into helpers.
50+
- Ensure files have EOF newline.
51+
- Flag trailing white space in code and comments.
52+
- Always ensure rubocop runs cleanly.
53+
54+
---
55+
56+
## 4. Testing and Coverage
57+
58+
> 🧪 **Be thorough:** Highlight gaps in meaningful test coverage.
59+
60+
- Flag missing or outdated specs for changed behaviors (unit, integration, request).
61+
- Suggest tests for edge cases: error conditions, invalid inputs, boundary values, and potential `nil` handling or pointer exceptions. Follow best practices from the [BetterSpecs style guide](https://evenbetterspecs.github.io/).
62+
- Encourage descriptive `context` blocks and example names per [BetterSpecs](https://evenbetterspecs.github.io/).
63+
- Flag missing specs when logic is updated but no tests were added or modified
64+
---
65+
66+
## 5. Performance and Security
67+
68+
> 🚀 **Guard quality:** Call out patterns that may hurt performance or security.
69+
70+
- Detect potential N+1 queries; suggest `includes` or batching.
71+
- Attempt to identify O(n^2) or O(n log n) algorithms; recommend more efficient alternatives.
72+
- Flag raw SQL, unsanitized interpolation, or other patterns that could introduce potential SQL injection vulnerabilities; recommend parameter binding and Sequel-based alternatives. Build these into a model, avoid raw sequel unless absolutely necessary.
73+
- Identify unescaped user input in route methods
74+
75+
---
76+
77+
## 6. Commit Message and PR title guidelines
78+
79+
> 📝 **Be clear:** Ensure commit messages and PR titles reflect changes accurately.
80+
81+
- We use Conventional Commits. Ensure commit messages follow the format: `<type>(<scope>): <description>`.
82+
- We use Semantic PR titles as well, ensure PR titles also match the conventional commit format.
83+
84+
## 7. Balancing Feedback
85+
86+
> ⚖️ **Be selective:** Focus on the highest-impact issues.
87+
88+
- Limit critical suggestions to the top 3–5 items per review.
89+
- Combine minor style tweaks into a single comment when possible.
90+
91+
---
92+
93+
## 8. Quick Reference
94+
95+
- **Max comment length:** 2–3 sentences.
96+
- **Severity tags:** `[Major]`, `[Medium]`, `[Minor]`.
97+
- **Mandatory header:** `Enable frozen-string-literal`.
98+
- **Top issues:** 3–5 critical comments.
99+
100+
---

Readme.adoc

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Access Polymarket endpoints via the `polymarket` namespace.
4747

4848
==== Markets
4949

50-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-markets)
50+
https://docs.domeapi.io/api-reference/endpoint/get-markets[API Reference]
5151

5252
List markets with optional filtering:
5353

@@ -69,7 +69,7 @@ price = client.polymarket.markets.price(token_id: 'token_id')
6969

7070
==== Candlesticks
7171

72-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-candlesticks)
72+
https://docs.domeapi.io/api-reference/endpoint/get-candlesticks[API Reference]
7373

7474
Get candlesticks:
7575

@@ -85,7 +85,7 @@ candlesticks = client.polymarket.candlesticks.list(
8585

8686
==== Trade History
8787

88-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-trade-history)
88+
https://docs.domeapi.io/api-reference/endpoint/get-trade-history[API Reference]
8989

9090
Get trade history:
9191

@@ -99,7 +99,7 @@ trades = client.polymarket.trade_history.list(
9999

100100
==== Orderbook
101101

102-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-orderbook-history)
102+
https://docs.domeapi.io/api-reference/endpoint/get-orderbook-history[API Reference]
103103

104104
Get orderbook history:
105105

@@ -114,7 +114,7 @@ snapshots = client.polymarket.orderbook.list(
114114

115115
==== Activity
116116

117-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-activity)
117+
https://docs.domeapi.io/api-reference/endpoint/get-activity[API Reference]
118118

119119
Get activity:
120120

@@ -128,7 +128,7 @@ activity = client.polymarket.activity.list(
128128

129129
==== Market Price
130130

131-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-market-price)
131+
https://docs.domeapi.io/api-reference/endpoint/get-market-price[API Reference]
132132

133133
Get market price history:
134134

@@ -142,7 +142,7 @@ prices = client.polymarket.market_price.list(
142142

143143
==== Wallet
144144

145-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-wallet)
145+
https://docs.domeapi.io/api-reference/endpoint/get-wallet[API Reference]
146146

147147
Get wallet information:
148148

@@ -155,7 +155,7 @@ wallet = client.polymarket.wallet.list(
155155

156156
==== Wallet Profit and Loss
157157

158-
[API Reference](https://docs.domeapi.io/api-reference/endpoint/get-wallet-pnl)
158+
https://docs.domeapi.io/api-reference/endpoint/get-wallet-pnl[API Reference]
159159

160160
Get wallet profit and loss:
161161

@@ -167,6 +167,41 @@ pnl = client.polymarket.wallet_profit_and_loss.list(
167167
)
168168
----
169169

170+
=== Matching Markets
171+
172+
Access Matching Markets endpoints via the `matching_markets` namespace.
173+
174+
==== Sports
175+
176+
https://docs.domeapi.io/api-reference/endpoint/get-matching-markets-sports[API Reference]
177+
178+
List matching markets for a specific sport and date:
179+
180+
[source,ruby]
181+
----
182+
# Using dynamic methods
183+
markets = client.matching_markets.nfl_on(Date.today)
184+
markets = client.matching_markets.nba_on('2023-12-25')
185+
186+
# Using sports_by_date method
187+
markets = client.matching_markets.sports_by_date(sport: 'nfl', date: Date.today)
188+
----
189+
190+
==== Markets
191+
192+
https://docs.domeapi.io/api-reference/endpoint/get-matching-markets[API Reference]
193+
194+
List matching markets by slug or ticker:
195+
196+
[source,ruby]
197+
----
198+
# By Polymarket slug
199+
markets = client.matching_markets.sports(polymarket_market_slug: 'super-bowl-lviii-winner')
200+
201+
# By Kalshi ticker
202+
markets = client.matching_markets.sports(kalshi_event_ticker: 'SB58')
203+
----
204+
170205
== Development
171206

172207
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

lib/domeapi/client.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ def polymarket
2828
@polymarket ||= Polymarket::Client.new(clone)
2929
end
3030

31+
def matching_markets
32+
@matching_markets ||= MatchingMarkets.new(self)
33+
end
34+
3135
private
3236

3337
def full_url(path)

lib/domeapi/matching_markets.rb

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# frozen_string_literal: true
2+
3+
module Rubyists
4+
module Domeapi
5+
# Matching Markets API endpoints
6+
class MatchingMarkets
7+
SPORTS = %w[nfl mlb cfb nba nhl cbb].freeze
8+
9+
# Filter for matching markets sports
10+
class SportsFilter < Contract
11+
propertize(%i[sport date])
12+
13+
validation do
14+
params do
15+
required(:sport).filled(:string, included_in?: SPORTS)
16+
required(:date).filled(:string, format?: /\A\d{4}-\d{2}-\d{2}\z/)
17+
end
18+
end
19+
end
20+
21+
# Filter for matching markets
22+
class Filter < Contract
23+
propertize(%i[polymarket_market_slug kalshi_event_ticker])
24+
25+
validation do
26+
params do
27+
optional(:polymarket_market_slug).maybe(Types::PolymarketMarketSlug)
28+
optional(:kalshi_event_ticker).maybe(Types::KalshiEventTicker)
29+
end
30+
31+
rule(:polymarket_market_slug, :kalshi_event_ticker) do
32+
if !values[:polymarket_market_slug] && !values[:kalshi_event_ticker]
33+
key.failure('Either polymarket_market_slug or kalshi_event_ticker must be provided')
34+
end
35+
end
36+
end
37+
end
38+
39+
attr_reader :client
40+
41+
# @param client [Rubyists::Domeapi::Client]
42+
#
43+
# @return [void]
44+
def initialize(client = Rubyists::Domeapi::Client.new)
45+
@client = client
46+
end
47+
48+
# List matching markets
49+
#
50+
# @param filter [Filter|Hash] Filter options
51+
#
52+
# @return [Hash|Array] resource data
53+
def sports(filter = Filter.new(Filter::Properties.new))
54+
filter = Filter.new(Filter::Properties.new(**filter)) if filter.is_a?(Hash)
55+
raise ArgumentError, filter.errors.full_messages.join(', ') unless filter.validate({})
56+
57+
client.get('matching-markets/sports', params: filter.to_h)
58+
end
59+
60+
# List matching markets for a specific sport and date
61+
#
62+
# @param filter [SportsFilter|Hash] Filter options
63+
#
64+
# @return [Hash|Array] resource data
65+
def sports_by_date(filter = SportsFilter.new(SportsFilter::Properties.new))
66+
filter = prepare_sports_filter(filter)
67+
raise ArgumentError, filter.errors.full_messages.join(', ') unless filter.validate({})
68+
69+
client.get("matching-markets/sports/#{filter.sport}", params: { date: filter.date })
70+
end
71+
72+
SPORTS.each do |sport|
73+
define_method("#{sport}_on") do |date|
74+
sports_by_date(sport: sport, date: date)
75+
end
76+
77+
define_singleton_method("#{sport}_on") do |date|
78+
new.send("#{sport}_on", date)
79+
end
80+
end
81+
82+
private
83+
84+
def prepare_sports_filter(filter)
85+
return filter unless filter.is_a?(Hash)
86+
87+
filter[:date] = filter[:date].strftime('%Y-%m-%d') if filter[:date].respond_to?(:strftime)
88+
SportsFilter.new(SportsFilter::Properties.new(**filter))
89+
end
90+
end
91+
end
92+
end

lib/domeapi/polymarket/activity.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class Filter < Contract
1414
propertize(%i[user start_time end_time market_slug condition_id limit offset])
1515

1616
validation do
17-
# :nocov:
1817
params do
1918
required(:user).filled(:string)
2019
optional(:start_time).maybe(:integer)
@@ -24,7 +23,6 @@ class Filter < Contract
2423
optional(:limit).maybe(:integer, gteq?: 1, lteq?: 1000)
2524
optional(:offset).maybe(:integer, gteq?: 0)
2625
end
27-
# :nocov:
2826
end
2927
end
3028
end

lib/domeapi/polymarket/candlesticks.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@ class Filter < Contract
1515
propertize(%i[condition_id start_time end_time interval])
1616

1717
validation do
18-
# :nocov:
1918
params do
2019
required(:condition_id).filled(:string)
2120
required(:start_time).filled(:integer)
2221
required(:end_time).filled(:integer)
2322
optional(:interval).maybe(:integer, gteq?: 1, lteq?: 1440)
2423
end
25-
# :nocov:
2624
end
2725
end
2826
end

lib/domeapi/polymarket/market_price.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ class Filter < Contract
1414
propertize(%i[token_id at_time])
1515

1616
validation do
17-
# :nocov:
1817
params do
1918
required(:token_id).filled(:string)
2019
optional(:at_time).maybe(:integer)
2120
end
22-
# :nocov:
2321
end
2422
end
2523
end

lib/domeapi/polymarket/markets.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ class Filter < Contract
1515
propertize(%i[market_slug event_slug condition_id tags status min_volume limit offset start_time end_time])
1616

1717
validation do
18-
# :nocov:
1918
params do
2019
optional(:status).maybe(:string, included_in?: %w[open closed])
2120
optional(:offset).maybe(:integer, gteq?: 0, lteq?: 100)
2221
end
23-
# :nocov:
2422
end
2523
end
2624

lib/domeapi/polymarket/orderbook.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,13 @@ class Filter < Contract
1414
propertize(%i[token_id start_time end_time limit offset])
1515

1616
validation do
17-
# :nocov:
1817
params do
1918
required(:token_id).filled(:string)
2019
required(:start_time).filled(:integer)
2120
required(:end_time).filled(:integer)
2221
optional(:limit).maybe(:integer, gteq?: 1, lteq?: 1000)
2322
optional(:offset).maybe(:integer, gteq?: 0)
2423
end
25-
# :nocov:
2624
end
2725
end
2826
end

0 commit comments

Comments
 (0)