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
24 changes: 24 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test Coverage

on:
workflow_call:

workflow_dispatch:

jobs:
SimpleCov:
runs-on: ubuntu-latest
steps:
# Only download these artifacts if they don't already exist
- if: ${{ hashFiles('coverage/.last_run.json') == '' }}
uses: actions/download-artifact@v4
with:
name: coverage-last-run
path: coverage/

- name: Check SimpleCov coverage
uses: joshmfrankel/simplecov-check-action@main
with:
minimum_suite_coverage: 97
minimum_file_coverage: 90
github_token: ${{ secrets.GITHUB_TOKEN }}
17 changes: 15 additions & 2 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,25 @@ jobs:
- '4.0.0'
steps:
- uses: actions/checkout@v4
name: Checkout code

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: false
bundler-cache: true

- name: Install dependencies
run: bundle install --jobs 4 --retry 3
- name: Run the default task

- name: Run the default rake task
run: bundle exec rake
env:
COVERAGE: "true"

- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage-last-run
path: coverage/
include-hidden-files: true
5 changes: 5 additions & 0 deletions .github/workflows/validations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ jobs:
validate_ruby:
name: Ruby Tests
uses: ./.github/workflows/main.yaml

ensure_coverage:
needs: validate_ruby
name: Check SimpleCov coverage
uses: ./.github/workflows/coverage.yaml
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ gem 'rubocop'
gem 'rubocop-minitest'
gem 'rubocop-performance'
gem 'rubocop-rake'
gem 'shoulda-context'
gem 'simplecov'
gem 'simplecov-json'
20 changes: 20 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ GEM
disposable (0.6.3)
declarative (>= 0.0.9, < 1.0.0)
representable (>= 3.1.1, < 4)
docile (1.4.1)
dry-cli (1.3.0)
dry-configurable (1.3.0)
dry-core (~> 1.1)
Expand Down Expand Up @@ -135,6 +136,16 @@ GEM
ruby-progressbar (1.13.0)
semantic_logger (4.17.0)
concurrent-ruby (~> 1.0)
shoulda-context (2.0.0)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.13.2)
simplecov-json (0.2.3)
json
simplecov
simplecov_json_formatter (0.1.4)
trailblazer (2.1.3)
trailblazer-activity-dsl-linear (>= 1.2.3, < 1.3.0)
trailblazer-developer (>= 0.1.0, < 0.2.0)
Expand Down Expand Up @@ -187,6 +198,9 @@ DEPENDENCIES
rubocop-minitest
rubocop-performance
rubocop-rake
shoulda-context
simplecov
simplecov-json

CHECKSUMS
addressable (2.8.8) sha256=7c13b8f9536cf6364c03b9d417c19986019e28f7c00ac8132da4eb0fe393b057
Expand All @@ -197,6 +211,7 @@ CHECKSUMS
crack (1.0.1) sha256=ff4a10390cd31d66440b7524eb1841874db86201d5b70032028553130b6d4c7e
declarative (0.0.20) sha256=8021dd6cb17ab2b61233c56903d3f5a259c5cf43c80ff332d447d395b17d9ff9
disposable (0.6.3) sha256=7f2a3fb251bff6cd83f25b164043d4ec3531209b51b066ed476a9df9c2d384cc
docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
domeapi (0.0.2)
dry-cli (1.3.0) sha256=984a715f9d7f8d9bf87b6530acdd4321dcf747636bfeb3ea7fd1b81bc0226e84
dry-configurable (1.3.0) sha256=882d862858567fc1210d2549d4c090f34370fc1bb7c5c1933de3fe792e18afa8
Expand Down Expand Up @@ -241,6 +256,11 @@ CHECKSUMS
rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
semantic_logger (4.17.0) sha256=c54b60d8596abe2e22bd4f20648d4f6c46e4287fba357779c7932335c8d130e9
shoulda-context (2.0.0) sha256=7adf45342cd800f507d2a053658cb1cce2884b616b26004d39684b912ea32c34
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
simplecov-json (0.2.3) sha256=c63823b5dfc95c85ff4cb94251765f08a166bdd68098f259368cbfe738e281f7
simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
trailblazer (2.1.3) sha256=8adf157f552a4843de51456f7e70e28422799e5d060b265814d145774b8845b7
trailblazer-activity (0.17.0) sha256=2166bc8b3410b808ad2bfe00efaf559533d1b9a6fb0d704cf3bdad02cd6c0b88
trailblazer-activity-dsl-linear (1.2.6) sha256=42e4d3c9bd9469b65f9265fba74c703cf1a4117ea7f42a0a78112ebb3bab986f
Expand Down
8 changes: 6 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# frozen_string_literal: true

require 'bundler/gem_tasks'
require 'minitest/test_task'
require 'rake/testtask'

Minitest::TestTask.create
Rake::TestTask.new do |t|
t.libs << 'test'
t.test_files = FileList['test/**/*_test.rb']
t.ruby_opts = %w[-rhelper]
end

require 'rubocop/rake_task'

Expand Down
16 changes: 16 additions & 0 deletions Readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ filter = Rubyists::Domeapi::Polymarket::TradeHistory::Filter.new(
trades = client.polymarket.trade_history.list(filter)
----

==== Orderbook

Get orderbook history:

[source,ruby]
----
filter = Rubyists::Domeapi::Polymarket::Orderbook::Filter.new(
Rubyists::Domeapi::Polymarket::Orderbook::Filter::Properties.new(
token_id: 'token_id',
start_time: 1625097600000,
end_time: 1625184000000
)
)
snapshots = client.polymarket.orderbook.list(filter)
----

== Development

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.
Expand Down
2 changes: 1 addition & 1 deletion lib/domeapi/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get(path, params: {})
end

def polymarket
@polymarket ||= Polymarket::Client.new(self)
@polymarket ||= Polymarket::Client.new(clone)
end

private
Expand Down
15 changes: 15 additions & 0 deletions lib/domeapi/contract.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ module Domeapi
class Contract < Reform::Form
feature Reform::Form::Dry

# Custom class methods can be defined here
module ClassMethods
def propertize(*names)
# names is always an array because of the splat
names = names.flatten
const_set(:Properties, Struct.new(*custom_definitions, *names, keyword_init: true))
names.each { |name| property name, populator: ->(value:, **) { value || skip! } }
end
end

def self.inherited(subclass)
subclass.extend ClassMethods
super
end

def self.custom_definitions = instance_variable_get(:@definitions)&.keys&.map(&:to_sym) || []

def to_h
Expand Down
11 changes: 11 additions & 0 deletions lib/domeapi/polymarket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,14 @@ module Polymarket
end
end
end

require_relative 'polymarket/endpoint'
require_relative 'polymarket/listable'
require_relative 'polymarket/markets'
require_relative 'polymarket/candlesticks'
require_relative 'polymarket/trade_history'
require_relative 'polymarket/orderbook'
require_relative 'polymarket/activity'
require_relative 'polymarket/market_price'
require_relative 'polymarket/wallet'
require_relative 'polymarket/wallet_profit_and_loss'
33 changes: 33 additions & 0 deletions lib/domeapi/polymarket/activity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module Rubyists
module Domeapi
module Polymarket
# Activity API endpoints
class Activity < Endpoint
include Listable

polymarket_path 'activity'

# Filter for activity
class Filter < Contract
propertize(%i[user start_time end_time market_slug condition_id limit offset])

validation do
# :nocov:
params do
required(:user).filled(:string)
optional(:start_time).maybe(:integer)
optional(:end_time).maybe(:integer)
optional(:market_slug).maybe(:string)
optional(:condition_id).maybe(:string)
optional(:limit).maybe(:integer, gteq?: 1, lteq?: 1000)
optional(:offset).maybe(:integer, gteq?: 0)
end
# :nocov:
end
end
end
end
end
end
27 changes: 7 additions & 20 deletions lib/domeapi/polymarket/candlesticks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,26 @@ module Domeapi
module Polymarket
# Candlesticks API endpoints
class Candlesticks < Endpoint
include Listable

polymarket_path 'markets/get_candlesticks'

# Filter for listing candlesticks,
# from https://docs.domeapi.io/api-reference/endpoint/get-candlesticks
class Filter < Contract
Properties = Struct.new(
:condition_id,
:start_time,
:end_time,
:interval,
keyword_init: true
)

Properties.members.each { |member| property member, populator: ->(value:, **) { value || skip! } }
propertize(%i[condition_id start_time end_time interval])

validation do
# :nocov:
params do
required(:condition_id).filled(:string)
required(:start_time).filled(:integer)
required(:end_time).filled(:integer)
optional(:interval).maybe(:integer, gteq?: 1, lteq?: 1440)
end
# :nocov:
end
end

# Get OHLC candlesticks
#
# @param filter [Filter] Filter options
#
# @return [Candlestick] The candlestick data
def list(filter = Filter.new(Filter::Properties.new))
raise ArgumentError, filter.errors.full_messages.join(', ') unless filter.valid?

client.get('markets/get_candlesticks', params: filter.to_h)
end
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions lib/domeapi/polymarket/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ def candlesticks
def trade_history
@trade_history ||= TradeHistory.new(client)
end

def orderbook
@orderbook ||= Orderbook.new(client)
end

def activity
@activity ||= Activity.new(client)
end

def market_price
@market_price ||= MarketPrice.new(client)
end

def wallet
@wallet ||= Wallet.new(client)
end

def wallet_profit_and_loss
@wallet_profit_and_loss ||= WalletProfitAndLoss.new(client)
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/domeapi/polymarket/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Endpoint
#
# @return [void]
def initialize(client = nil)
@client = client || ::Rubyists::Domeapi::Client.new
@client = client || Client.new
end
end
end
Expand Down
44 changes: 44 additions & 0 deletions lib/domeapi/polymarket/listable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

module Rubyists
module Domeapi
module Polymarket
# Mixin for listable resources
module Listable
def self.included(base)
base.extend(ClassMethods)
end

# Class methods for Listable
module ClassMethods
attr_accessor :endpoint_path

# Set the endpoint path for the resource
#
# @param path [String] API endpoint path
#
# @return [String] endpoint path
def polymarket_path(path)
self.endpoint_path = path
end

def list(...)
new.list(...)
end
end

# List resources
#
# @param filter [Filter|Hash] Filter options
#
# @return [Hash|Array] resource data
def list(filter = self.class::Filter.new(self.class::Filter::Properties.new))
filter = self.class::Filter.new(self.class::Filter::Properties.new(**filter)) if filter.is_a?(Hash)
raise ArgumentError, filter.errors.full_messages.join(', ') unless filter.validate({})

client.get(self.class.endpoint_path, params: filter.to_h)
end
end
end
end
end
28 changes: 28 additions & 0 deletions lib/domeapi/polymarket/market_price.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

module Rubyists
module Domeapi
module Polymarket
# Market Price API endpoints
class MarketPrice < Endpoint
include Listable

polymarket_path 'markets/get_market_price'

# Filter for market price
class Filter < Contract
propertize(%i[token_id at_time])

validation do
# :nocov:
params do
required(:token_id).filled(:string)
optional(:at_time).maybe(:integer)
end
# :nocov:
end
end
end
end
end
end
Loading