Skip to content

Commit

Permalink
Merge pull request #101 from cryptape/v2-transactions
Browse files Browse the repository at this point in the history
Add /api/v2/transactions
  • Loading branch information
classicalliu authored May 16, 2019
2 parents 375a51b + 37758f9 commit b43760e
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 3 deletions.
8 changes: 5 additions & 3 deletions API_DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,20 @@ Also Support camelCase.

Get transactions list and paginate it.

> GET /api/transactions
> GET /api/v2/transactions
#### params

Also Support camelCase.

```ruby
{
"account": "the addr transactions related to (from or to)", # hash string
"from": "the addr transactions from", # hash string
"to": "the addr transactions to", # hash string
"valueFormat": "decimal", # set value to decimal number, default hex number
"value_format": "decimal", # set value to decimal number, default hex number
"page": "1", # integer, default 1
"perPage": "10", # integer, default 10
"per_page": "10", # integer, default 10
# offset and limit has lower priority than page and perPage
"offset": "1", # integer, default to 0
"limit": "10", # integer, default to 10
Expand Down
49 changes: 49 additions & 0 deletions app/controllers/api/v2/transactions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

class Api::V2::TransactionsController < ApplicationController
# params:
# {
# "account": "the addr transactions related to", // hash
# "from": "the addr transactions from", // hash
# "to": "the addr transactions to", // hash
# "page": "1", // default 1
# "per_page": "10", // default 10
# "value_format": "decimal", // set value to decimal number, default hex number
#
# # offset and limit has lower priority than page and perPage
# "offset": "1", // default to 0
# "limit": "10", // default to 10
# }
#
# GET /api/v2/transactions
def index
params.transform_keys!(&:underscore)

# use ILIKE to ignore case
options = {
from_or_to_matches: params[:account],
from_matches: params[:from],
to_matches: params[:to]
}

# FIXME: should order by block_number and index desc, change block_number to integer
transactions = Transaction.ransack(options).result.order(updated_at: :desc)

if params[:page].nil? && (params[:offset].present? || params[:limit].present?)
offset = params[:offset] || 0
limit = params[:limit] || 10
transactions = transactions.offset(offset).limit(limit)
else
transactions = transactions.page(params[:page]).per(params[:per_page])
end

# TODO: provide V2 api to set default value decimal
decimal_value = params[:value_format] == "decimal"

render json: {
result: {
transactions: ActiveModelSerializers::SerializableResource.new(transactions, each_serializer: ::Api::TransactionSerializer, decimal_value: decimal_value)
}
}
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

namespace :v2 do
resources :blocks, only: [:index]
resources :transactions, only: [:index]
end
end

Expand Down
117 changes: 117 additions & 0 deletions spec/controllers/api/v2/transactions_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
require 'rails_helper'

def random(num)
"0x" + SecureRandom.hex(num)
end

RSpec.describe Api::V2::TransactionsController, type: :controller do
let(:from) { random(20) }
let(:to) { random(20) }

let(:body) { Oj.load(response.body).with_indifferent_access }
let(:result) { body[:result] }
let(:count) { result[:transactions].size }

before do
mock_get_meta_data

block_one = create :block_one
13.times do
create :transaction, block: block_one, tx_hash: random(32)
end

create :transaction, block: block_one, tx_hash: random(32), from: from
create :transaction, block: block_one, tx_hash: random(32), to: to
end

context "index" do
it "no params" do
post :index, params: {}
expect(count).to eq 10
end

context "with account" do
it "equal to from" do
post :index, params: { account: from }
expect(count).to eq 1
end

it "equal to to" do
post :index, params: { account: to }
expect(count).to eq 1
end
end

it "with from" do
post :index, params: { from: from }
expect(count).to eq 1
end

it "with to" do
post :index, params: { to: to }
expect(count).to eq 1
end

context "ignore case" do
let(:swapcase_from) { from.swapcase }
let(:swapcase_to) { to.swapcase }

it "with swapcase from" do
post :index, params: { from: swapcase_from }
expect(count).to eq 1
end

it "with swapcase to" do
post :index, params: { to: swapcase_to }
expect(count).to eq 1
end

it "with swapcase account" do
post :index, params: { account: swapcase_from }
expect(count).to eq 1
end
end

it "with page and perPage" do
post :index, params: { page: 2, perPage: 10 }
expect(result[:transactions].count).to eq 5
end

it "with offset and limit" do
post :index, params: { offset: 10, limit: 10 }
expect(count).to eq 5
end

it "with offset" do
post :index, params: { offset: 0 }
expect(count).to eq 10
end

it "with limit" do
post :index, params: { limit: 5 }
expect(count).to eq 5
end

context "with valueFormat" do
let(:value_decimal) { attributes_for(:transaction)[:value] }
let(:value_hex) { "0x0000000000000000000000000000000000000000000000000000000000001000" }
it "return decimal if valueFormat equals decimal" do
get :index, params: { valueFormat: "decimal" }

expect(result["transactions"].map {|n| n["value"]}.uniq).to match_array [value_decimal]
end

it "return hex if valueFormat equals hex" do
get :index, params: { valueFormat: 'hex' }

expect(result["transactions"].map {|n| n["value"]}.uniq).to match_array [value_hex]
end

it "return hex if valueFormat not set" do
get :index

expect(result["transactions"].map {|n| n["value"]}.uniq).to match_array [value_hex]
end
end
end
end

0 comments on commit b43760e

Please sign in to comment.