diff --git a/.rubocop.yml b/.rubocop.yml index 8df2355..e69e79e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -14,13 +14,16 @@ Metrics/BlockLength: Exclude: - 'spec/**/*' -# The next 3 rubocop enabled disallow visual alignment (EasyAlign) +# The next 4 rubocop enabled disallow visual alignment (EasyAlign) Layout/ExtraSpacing: Enabled: false Layout/HashAlignment: Enabled: false Layout/SpaceBeforeFirstArg: Enabled: false +Layout/SpaceInsideParens: + Exclude: + - 'spec/**/*' Layout/SpaceInsideHashLiteralBraces: Enabled: false diff --git a/README.md b/README.md index 66b6a8c..cdb02f5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,11 @@ Then type code like: ```ruby account = StrikeMe::API::Account.new account.profile.attributes -account.balances.map(&:attributes) +account.balances.map(&:attributes) # same as account.balances.to_a +account.balances.btc # to get the BTC specific one + +invoices = StrikeMe::API::Invoices.new +invoices.any? ``` Usage diff --git a/bin/randomize_uuids b/bin/randomize_uuids new file mode 100755 index 0000000..7d47159 --- /dev/null +++ b/bin/randomize_uuids @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# give a replacement version of a file replacing found UUIDs, +# preserving multiple instances that might indicate relations + +require 'active_support/all' +require 'pry' + +file_path = $ARGV.first + +abort 'Specify the file to replace' unless file_path.present? + +matcher = /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/ +content = File.read(file_path) + +puts '==== Old content ====' +puts content +puts "--------------------------\n\n" +uuids = content.scan(matcher).uniq +uuids.each do |uuid| + content.gsub! uuid, SecureRandom.uuid +end +puts '==== New content ====' +puts content diff --git a/lib/strike_me/api.rb b/lib/strike_me/api.rb index 33b844a..7fa8c3a 100644 --- a/lib/strike_me/api.rb +++ b/lib/strike_me/api.rb @@ -29,6 +29,7 @@ module StrikeMe autoload_default :BaseClient autoload_default :BaseModel autoload_default :Account + autoload_default :Invoices autoload_default :InvoiceResponse end end diff --git a/lib/strike_me/api/invoices.rb b/lib/strike_me/api/invoices.rb new file mode 100644 index 0000000..1a9aee8 --- /dev/null +++ b/lib/strike_me/api/invoices.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module StrikeMe + module API + # Factory helper object connecting the client to the models + class Invoices + include BaseClient + include Enumerable + + autoload_default :Invoice + + delegate :first, :last, :size, :any?, to: :list + + def each(&block) + list.each(&block) + end + + def list + return @list if @list.present? + + url = 'invoices' + response = client.get url + + raise ResponseError.new(url, response.body) unless response.success? + + @list = response.body['items'].map { |item| Invoice.new item } + end + end + end +end diff --git a/lib/strike_me/api/invoices/invoice.rb b/lib/strike_me/api/invoices/invoice.rb new file mode 100644 index 0000000..6118284 --- /dev/null +++ b/lib/strike_me/api/invoices/invoice.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module StrikeMe + module API + class Invoices + class Invoice < BaseModel + attribute :invoiceId + attribute :amount + attribute :state + attribute :created, :datetime + attribute :description + attribute :issuerId + attribute :receiverId + attribute :payerId + + attribute_names.select { _1.end_with? 'Id' }.each do |snake_name| + alias_attribute snake_name.underscore, snake_name + end + + def paid? + state == 'PAID' + end + end + end + end +end diff --git a/spec/strike_me/api/invoices_spec.rb b/spec/strike_me/api/invoices_spec.rb new file mode 100644 index 0000000..d095aaa --- /dev/null +++ b/spec/strike_me/api/invoices_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +RSpec.describe StrikeMe::API::Invoices do + subject { described_class.new } + + describe 'list' do + context 'success response' do + before { stub_request(:get, 'https://api.strike.me/v1/invoices').to_return(status: 200, body: '{"items":[{"invoiceId":"97dca64c-6dde-4a87-b970-279f1a8e0ac5","amount":{"amount":"0.00014","currency":"BTC"},"state":"PAID","created":"2025-08-08T22:28:44.195825+00:00","description":"Hi there","issuerId":"41952e07-483c-4cd7-afa4-b6a8ec729809","receiverId":"41952e07-483c-4cd7-afa4-b6a8ec729809","payerId":"f75c22bf-625f-4c47-acdf-acb9c596bb8c"},{"invoiceId":"aed2cbf7-e2cd-4a1c-874e-a84489342ac2","amount":{"amount":"8.00","currency":"USD"},"state":"PAID","created":"2025-07-31T22:24:19.302922+00:00","description":"","issuerId":"a34a9cdc-1853-4f3b-9bd8-66d6700b1558","receiverId":"a34a9cdc-1853-4f3b-9bd8-66d6700b1558","payerId":"f75c22bf-625f-4c47-acdf-acb9c596bb8c"},{"invoiceId":"4773efeb-9aa7-47a0-a3cc-0a57a3f7718a","amount":{"amount":"0.00047455","currency":"BTC"},"state":"PAID","created":"2025-07-10T23:22:28.324613+00:00","description":"","issuerId":"a34a9cdc-1853-4f3b-9bd8-66d6700b1558","receiverId":"a34a9cdc-1853-4f3b-9bd8-66d6700b1558","payerId":"f75c22bf-625f-4c47-acdf-acb9c596bb8c"},{"invoiceId":"f3853f94-d198-4b83-8b9a-11a836926819","amount":{"amount":"40.00","currency":"USDT"},"state":"UNPAID","created":"2023-05-20T22:44:36.856775+00:00","description":"","issuerId":"f75c22bf-625f-4c47-acdf-acb9c596bb8c","receiverId":"f75c22bf-625f-4c47-acdf-acb9c596bb8c"}],"count":4,"isCountUnknown":false}', headers: {'Content-Type' => 'application/json'}) } + + it '...' do + list = subject.list + expect(list.first).to be_paid + expect(list.last ).not_to be_paid + + expect(list.first.attributes).to eq( + 'invoiceId' => '97dca64c-6dde-4a87-b970-279f1a8e0ac5', + 'amount' => {'amount' => '0.00014', 'currency' => 'BTC'}, + 'state' => 'PAID', + 'created' => '2025-08-08 22:28:44.195825 +0000', # is actual Time + 'description' => 'Hi there', + 'issuerId' => '41952e07-483c-4cd7-afa4-b6a8ec729809', + 'receiverId' => '41952e07-483c-4cd7-afa4-b6a8ec729809', + 'payerId' => 'f75c22bf-625f-4c47-acdf-acb9c596bb8c' + ) + expect(list.first.created).to be_a Time + + expect(list.last.attributes).to eq( + 'invoiceId' => 'f3853f94-d198-4b83-8b9a-11a836926819', + 'amount' => {'amount' => '40.00', 'currency' => 'USDT'}, + 'state' => 'UNPAID', + 'created' => '2023-05-20 22:44:36.856775 +0000', + 'description' => '', + 'issuerId' => 'f75c22bf-625f-4c47-acdf-acb9c596bb8c', + 'receiverId' => 'f75c22bf-625f-4c47-acdf-acb9c596bb8c', + 'payerId' => nil + ) + end + end + end +end