From c4e6807d61d5c63d94ecfc14fa2ce85d6e1c1ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sun, 5 Sep 2021 21:21:10 -0300 Subject: [PATCH 1/6] add DepositOrder model and query --- app/graphql/types/deposit_order_type.rb | 16 ++ app/graphql/types/query_type.rb | 5 + app/graphql/x_stake_schema.rb | 2 + app/javascript/__generated__/schema.graphql | 60 +++++ app/models/deposit_order.rb | 31 +++ app/policies/deposit_order_policy.rb | 10 + .../20210905234913_create_deposit_orders.rb | 14 ++ db/schema.rb | 13 +- erd.svg | 219 ++++++++++-------- spec/factories/deposit_orders.rb | 28 +++ spec/models/deposit_order_spec.rb | 27 +++ 11 files changed, 328 insertions(+), 97 deletions(-) create mode 100644 app/graphql/types/deposit_order_type.rb create mode 100644 app/models/deposit_order.rb create mode 100644 app/policies/deposit_order_policy.rb create mode 100644 db/migrate/20210905234913_create_deposit_orders.rb create mode 100644 spec/factories/deposit_orders.rb create mode 100644 spec/models/deposit_order_spec.rb diff --git a/app/graphql/types/deposit_order_type.rb b/app/graphql/types/deposit_order_type.rb new file mode 100644 index 0000000..e0ae3bd --- /dev/null +++ b/app/graphql/types/deposit_order_type.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +module Types + class DepositOrderType < Types::BaseObject + implements GraphQL::Types::Relay::Node + global_id_field :id + + graphql_name "DepositOrder" + + field :id, ID, null: false + field :status, String, null: false + field :received_amount_cents, Integer, null: false + field :paid_amount_cents, Integer, null: false + field :created_at, GraphQL::Types::ISO8601DateTime, null: false + field :updated_at, GraphQL::Types::ISO8601DateTime, null: false + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index ff4b89b..9d41d4f 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -31,5 +31,10 @@ module Types ransack(scope, filter) end + + field :deposit_orders, DepositOrderType.connection_type, null: false + def deposit_orders + Pundit.policy_scope(current_user, DepositOrder) + end end end diff --git a/app/graphql/x_stake_schema.rb b/app/graphql/x_stake_schema.rb index 268a968..bca4b1f 100644 --- a/app/graphql/x_stake_schema.rb +++ b/app/graphql/x_stake_schema.rb @@ -14,6 +14,8 @@ class XStakeSchema < GraphQL::Schema Types::SellCryptoOrderType when BuyCryptoOrder Types::BuyCryptoOrderType + when DepositOrder + Types::DepositOrderType else raise(GraphQL::RequiredImplementationMissingError, "Unexpected object: #{obj}") end diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index 878a20c..29a8a31 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -172,6 +172,45 @@ type CreateStakeRemoveOrderPayload { order: StakeOrder } +type DepositOrder implements Node { + createdAt: ISO8601DateTime! + id: ID! + paidAmountCents: Int! + receivedAmountCents: Int! + status: String! + updatedAt: ISO8601DateTime! +} + +""" +The connection type for DepositOrder. +""" +type DepositOrderConnection { + """ + A list of edges. + """ + edges: [DepositOrderEdge!]! + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type DepositOrderEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: DepositOrder! +} + type FiatBalance implements Node { amountCents: Int! amountCurrency: String! @@ -286,6 +325,27 @@ type Query { last: Int ): BuyCryptoOrderConnection! currentUser: User + depositOrders( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): DepositOrderConnection! """ Fetches an object given its ID. diff --git a/app/models/deposit_order.rb b/app/models/deposit_order.rb new file mode 100644 index 0000000..947c3c3 --- /dev/null +++ b/app/models/deposit_order.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: deposit_orders +# +# id :bigint not null, primary key +# paid_amount_cents :integer default(0), not null +# received_amount_cents :integer default(0), not null +# status :string not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_deposit_orders_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +class DepositOrder < ApplicationRecord + include Processable + include Trackable + + belongs_to :user + + monetize :paid_amount_cents + monetize :received_amount_cents +end diff --git a/app/policies/deposit_order_policy.rb b/app/policies/deposit_order_policy.rb new file mode 100644 index 0000000..e6e254c --- /dev/null +++ b/app/policies/deposit_order_policy.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +class DepositOrderPolicy < ApplicationPolicy + class Scope < Scope + def resolve + return scope.none if user.nil? + + scope.where(user_id: user.id) + end + end +end diff --git a/db/migrate/20210905234913_create_deposit_orders.rb b/db/migrate/20210905234913_create_deposit_orders.rb new file mode 100644 index 0000000..0a31d59 --- /dev/null +++ b/db/migrate/20210905234913_create_deposit_orders.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true +class CreateDepositOrders < ActiveRecord::Migration[6.1] + def change + create_table(:deposit_orders) do |t| + t.references(:user, null: false, foreign_key: true) + t.string(:status, null: false) + + t.integer(:received_amount_cents, null: false, default: 0) + t.integer(:paid_amount_cents, null: false, default: 0) + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 0dccd51..7e98d4f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_08_28_041104) do +ActiveRecord::Schema.define(version: 2021_09_05_234913) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -73,6 +73,16 @@ ActiveRecord::Schema.define(version: 2021_08_28_041104) do t.index ["user_id"], name: "index_buy_crypto_orders_on_user_id" end + create_table "deposit_orders", force: :cascade do |t| + t.bigint "user_id", null: false + t.string "status", null: false + t.integer "received_amount_cents", default: 0, null: false + t.integer "paid_amount_cents", default: 0, null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["user_id"], name: "index_deposit_orders_on_user_id" + end + create_table "fiat_balances", force: :cascade do |t| t.bigint "user_id", null: false t.integer "amount_cents", default: 0, null: false @@ -139,6 +149,7 @@ ActiveRecord::Schema.define(version: 2021_08_28_041104) do add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "balances", "users" add_foreign_key "buy_crypto_orders", "users" + add_foreign_key "deposit_orders", "users" add_foreign_key "fiat_balances", "users" add_foreign_key "sell_crypto_orders", "users" add_foreign_key "stake_orders", "users" diff --git a/erd.svg b/erd.svg index 77ee004..508d039 100644 --- a/erd.svg +++ b/erd.svg @@ -1,83 +1,104 @@ - - - + + XStake - -XStake domain model + +XStake domain model m_AdminUser - -AdminUser - -email -string ∗ U -encrypted_password -string ∗ -remember_created_at -datetime -reset_password_sent_at -datetime -reset_password_token -string + +AdminUser + +email +string ∗ U +encrypted_password +string ∗ +remember_created_at +datetime +reset_password_sent_at +datetime +reset_password_token +string m_Balance - -Balance - -amount -decimal (20,10) ∗ -user_id -integer (8) ∗ FK + +Balance + +amount +decimal (20,10) ∗ +user_id +integer (8) ∗ FK - + m_PaperTrail::Version - -PaperTrail::Version - -event -string ∗ -item_id -integer (8) ∗ FK -item_type -string ∗ -object -text -whodunnit -string + +PaperTrail::Version + +event +string ∗ +item_id +integer (8) ∗ FK +item_type +string ∗ +object +text +whodunnit +string m_Balance->m_PaperTrail::Version - - + + m_BuyCryptoOrder - -BuyCryptoOrder - -paid_amount_cents -integer ∗ -received_amount -decimal (20,10) ∗ -status -string ∗ -user_id -integer (8) ∗ FK + +BuyCryptoOrder + +paid_amount_cents +integer ∗ +received_amount +decimal (20,10) ∗ +status +string ∗ +user_id +integer (8) ∗ FK + + + +m_DepositOrder + +DepositOrder + +paid_amount_cents +integer ∗ +received_amount_cents +integer ∗ +status +string ∗ +user_id +integer (8) ∗ FK + + + +m_DepositOrder->m_PaperTrail::Version + + - + m_FiatBalance FiatBalance @@ -90,13 +111,13 @@ integer (8) ∗ FK - + m_FiatBalance->m_PaperTrail::Version - - + + - + m_SellCryptoOrder SellCryptoOrder @@ -111,7 +132,7 @@ integer (8) ∗ FK - + m_StakeOrder StakeOrder @@ -126,58 +147,64 @@ integer (8) ∗ FK - + m_User - -User - -email -string ∗ U -encrypted_password -string ∗ -first_name -string ∗ -last_name -string ∗ -remember_created_at -datetime -reset_password_sent_at -datetime -reset_password_token -string -wallet_address -string + +User + +email +string ∗ U +encrypted_password +string ∗ +first_name +string ∗ +last_name +string ∗ +remember_created_at +datetime +reset_password_sent_at +datetime +reset_password_token +string +wallet_address +string - + m_User->m_Balance - + - + m_User->m_BuyCryptoOrder - - + + + + + +m_User->m_DepositOrder + + - + m_User->m_FiatBalance - + - + m_User->m_SellCryptoOrder - - + + - + m_User->m_StakeOrder - - + + - + m_UserDocument UserDocument @@ -188,10 +215,10 @@ integer (8) ∗ FK - + m_User->m_UserDocument - - + + diff --git a/spec/factories/deposit_orders.rb b/spec/factories/deposit_orders.rb new file mode 100644 index 0000000..869cf26 --- /dev/null +++ b/spec/factories/deposit_orders.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: deposit_orders +# +# id :bigint not null, primary key +# paid_amount_cents :integer default(0), not null +# received_amount_cents :integer default(0), not null +# status :string not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_deposit_orders_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :deposit_order do + user { nil } + status { "MyString" } + end +end diff --git a/spec/models/deposit_order_spec.rb b/spec/models/deposit_order_spec.rb new file mode 100644 index 0000000..13164d1 --- /dev/null +++ b/spec/models/deposit_order_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: deposit_orders +# +# id :bigint not null, primary key +# paid_amount_cents :integer default(0), not null +# received_amount_cents :integer default(0), not null +# status :string not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_deposit_orders_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +require "rails_helper" + +RSpec.describe(DepositOrder, type: :model) do + pending "add some examples to (or delete) #{__FILE__}" +end From 1decb1a2b8145297ac74cf59bd819f708b3760ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sun, 5 Sep 2021 21:25:25 -0300 Subject: [PATCH 2/6] add status filter to DespositOrder --- app/graphql/inputs/deposit_order_filter_input.rb | 6 ++++++ app/graphql/types/query_type.rb | 10 +++++++--- app/javascript/__generated__/schema.graphql | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 app/graphql/inputs/deposit_order_filter_input.rb diff --git a/app/graphql/inputs/deposit_order_filter_input.rb b/app/graphql/inputs/deposit_order_filter_input.rb new file mode 100644 index 0000000..b1ddab8 --- /dev/null +++ b/app/graphql/inputs/deposit_order_filter_input.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +module Inputs + class DepositOrderFilterInput < Types::BaseInputObject + argument :status, [Types::ProcessStatusEnum], required: false + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 9d41d4f..48ae7f8 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -32,9 +32,13 @@ module Types ransack(scope, filter) end - field :deposit_orders, DepositOrderType.connection_type, null: false - def deposit_orders - Pundit.policy_scope(current_user, DepositOrder) + field :deposit_orders, DepositOrderType.connection_type, null: false do + argument :filter, Inputs::DepositOrderFilterInput, required: false + end + + def deposit_orders(filter: nil) + scope = Pundit.policy_scope(current_user, DepositOrder) + scope.where(status: filter.status) if filter&.status end end end diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index 29a8a31..5b9dc6b 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -211,6 +211,10 @@ type DepositOrderEdge { node: DepositOrder! } +input DepositOrderFilterInput { + status: [ProcessStatus!] +} + type FiatBalance implements Node { amountCents: Int! amountCurrency: String! @@ -335,6 +339,7 @@ type Query { Returns the elements in the list that come before the specified cursor. """ before: String + filter: DepositOrderFilterInput """ Returns the first _n_ elements from the list. From d3d7f6b8da8feae27a4fe2f3b687690acbf1ea40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sun, 5 Sep 2021 22:06:16 -0300 Subject: [PATCH 3/6] use Table component on Stake and Exhcange history --- app/javascript/src/components/Table/Table.tsx | 27 +++++ .../src/components/Table/TableRow.tsx | 21 ++++ app/javascript/src/components/Table/index.ts | 2 + app/javascript/src/components/index.ts | 1 + .../ExchangeHistory/ExchangeHistory.tsx | 43 ++----- .../src/pages/Orders/Stake/Stake.tsx | 112 ++++++------------ app/javascript/src/pages/Orders/index.ts | 2 + 7 files changed, 98 insertions(+), 110 deletions(-) create mode 100644 app/javascript/src/components/Table/Table.tsx create mode 100644 app/javascript/src/components/Table/TableRow.tsx create mode 100644 app/javascript/src/components/Table/index.ts diff --git a/app/javascript/src/components/Table/Table.tsx b/app/javascript/src/components/Table/Table.tsx new file mode 100644 index 0000000..252e826 --- /dev/null +++ b/app/javascript/src/components/Table/Table.tsx @@ -0,0 +1,27 @@ +import type { FC } from "react"; +import React from "react"; + +type Props = { + columns: string[]; +}; + +export const Table: FC = ({ columns, children }) => { + return ( + + + + {columns.map((column, index) => ( + + ))} + + + {children} +
+ {column} +
+ ); +}; diff --git a/app/javascript/src/components/Table/TableRow.tsx b/app/javascript/src/components/Table/TableRow.tsx new file mode 100644 index 0000000..cc6ed40 --- /dev/null +++ b/app/javascript/src/components/Table/TableRow.tsx @@ -0,0 +1,21 @@ +import type { FC, ReactNode } from "react"; +import React from "react"; + +type Props = { + items?: Array; +}; + +export const TableRow: FC = ({ items }) => { + return ( + + {items?.map((item, index) => ( + +

{item}

+ + ))} + + ); +}; diff --git a/app/javascript/src/components/Table/index.ts b/app/javascript/src/components/Table/index.ts new file mode 100644 index 0000000..c26fc70 --- /dev/null +++ b/app/javascript/src/components/Table/index.ts @@ -0,0 +1,2 @@ +export * from "./Table"; +export * from "./TableRow"; diff --git a/app/javascript/src/components/index.ts b/app/javascript/src/components/index.ts index 90b1af0..b9980c2 100644 --- a/app/javascript/src/components/index.ts +++ b/app/javascript/src/components/index.ts @@ -4,3 +4,4 @@ export * from "./Modal"; export * from "./Input"; export * from "./Button"; export * from "./Spinner"; +export * from "./Table"; diff --git a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx index 1e9370e..5037dde 100644 --- a/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx +++ b/app/javascript/src/pages/Orders/Exchange/ExchangeHistory/ExchangeHistory.tsx @@ -3,6 +3,7 @@ import type { FC } from "react"; import React from "react"; import { useFragment } from "react-relay"; +import { Table } from "../../../../components"; import { Messages } from "../../../../messages"; import { centsToUnit } from "../../../../utils/fiatMoney"; import type { CryptoExchangeOrderProps } from "./components/CryptoExchangeOrder"; @@ -119,41 +120,13 @@ export const ExchangeHistory: FC = ({
- - - - - - - - - - - {orderRows.map((order) => { - return ; - })} - -
- Valor pago - - Valor recebido - - Criado em - - Status -
+ + {orderRows.map((order) => { + return ; + })} +
diff --git a/app/javascript/src/pages/Orders/Stake/Stake.tsx b/app/javascript/src/pages/Orders/Stake/Stake.tsx index ee88cf2..c05f2f7 100644 --- a/app/javascript/src/pages/Orders/Stake/Stake.tsx +++ b/app/javascript/src/pages/Orders/Stake/Stake.tsx @@ -7,6 +7,7 @@ import cx from "classnames"; import { getStatusTextAndColors } from "../utils/processStatus"; import type { StakeQuery } from "./__generated__/StakeQuery.graphql"; import { Messages } from "../../../messages"; +import { Table, TableRow } from "../../../components"; export const Stake: FC = () => { const { stakeOrders } = useLazyLoadQuery( @@ -36,82 +37,43 @@ export const Stake: FC = () => {
- - - - - - - - - - - {stakeOrders.edges.map(({ node }) => { - const [label, textStyles, bgStyles] = getStatusTextAndColors( - node.status - ); +
- Pool - - Montante - - Criado em - - Status -
+ {stakeOrders.edges.map(({ node }) => { + const [label, textStyles, bgStyles] = getStatusTextAndColors( + node.status + ); - return ( - - - - - - - ); - })} - -
-

- {node.poolName} -

-
-

- {node.amount} -

-
-

- {new Date( - node.createdAt as string - ).toLocaleTimeString()} -

-
- - -
+ const status = ( + + + ); + + return ( + + ); + })} +
diff --git a/app/javascript/src/pages/Orders/index.ts b/app/javascript/src/pages/Orders/index.ts index 7c2f26f..b62d13d 100644 --- a/app/javascript/src/pages/Orders/index.ts +++ b/app/javascript/src/pages/Orders/index.ts @@ -1,7 +1,9 @@ import { Exchange } from "./Exchange"; import { Stake } from "./Stake"; +import { Deposit } from "./Deposit"; export const Orders = { + Deposit, Exchange, Stake, }; From 3bedd32502feb3e94d533296047741c4048958b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sun, 5 Sep 2021 22:22:47 -0300 Subject: [PATCH 4/6] add deposit history page --- app/graphql/types/deposit_order_type.rb | 2 +- app/graphql/types/query_type.rb | 5 +- app/javascript/__generated__/schema.graphql | 2 +- app/javascript/src/Routes.tsx | 3 + .../src/components/SideNav/SideNav.tsx | 4 + .../src/pages/Orders/Deposit/Deposit.tsx | 90 +++++++++++ .../__generated__/DepositQuery.graphql.ts | 143 ++++++++++++++++++ .../src/pages/Orders/Deposit/index.ts | 1 + .../src/pages/Orders/Stake/Stake.tsx | 2 +- 9 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 app/javascript/src/pages/Orders/Deposit/Deposit.tsx create mode 100644 app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Deposit/index.ts diff --git a/app/graphql/types/deposit_order_type.rb b/app/graphql/types/deposit_order_type.rb index e0ae3bd..d3ef59e 100644 --- a/app/graphql/types/deposit_order_type.rb +++ b/app/graphql/types/deposit_order_type.rb @@ -7,7 +7,7 @@ module Types graphql_name "DepositOrder" field :id, ID, null: false - field :status, String, null: false + field :status, ProcessStatusEnum, null: false field :received_amount_cents, Integer, null: false field :paid_amount_cents, Integer, null: false field :created_at, GraphQL::Types::ISO8601DateTime, null: false diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 48ae7f8..029e8ec 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -38,7 +38,10 @@ module Types def deposit_orders(filter: nil) scope = Pundit.policy_scope(current_user, DepositOrder) - scope.where(status: filter.status) if filter&.status + + return scope.where(status: filter.status) if filter&.status + + scope end end end diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index 5b9dc6b..fc23c6a 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -177,7 +177,7 @@ type DepositOrder implements Node { id: ID! paidAmountCents: Int! receivedAmountCents: Int! - status: String! + status: ProcessStatus! updatedAt: ISO8601DateTime! } diff --git a/app/javascript/src/Routes.tsx b/app/javascript/src/Routes.tsx index 391fcdd..9ca3819 100644 --- a/app/javascript/src/Routes.tsx +++ b/app/javascript/src/Routes.tsx @@ -22,6 +22,9 @@ export const Routes: FC = () => { + + + ); }; diff --git a/app/javascript/src/components/SideNav/SideNav.tsx b/app/javascript/src/components/SideNav/SideNav.tsx index eec31e1..c57f116 100644 --- a/app/javascript/src/components/SideNav/SideNav.tsx +++ b/app/javascript/src/components/SideNav/SideNav.tsx @@ -31,6 +31,10 @@ const MenuItems: MenuItem[] = [ label: "Ordem de Stake", path: "/orders/stake", }, + { + label: "Ordem de Depósito", + path: "/orders/deposit", + }, ]; export const SideNav = () => { diff --git a/app/javascript/src/pages/Orders/Deposit/Deposit.tsx b/app/javascript/src/pages/Orders/Deposit/Deposit.tsx new file mode 100644 index 0000000..bed7466 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Deposit.tsx @@ -0,0 +1,90 @@ +import { graphql } from "babel-plugin-relay/macro"; +import type { FC } from "react"; +import React from "react"; +import { useLazyLoadQuery } from "react-relay"; +import cs from "classnames"; + +import { Table, TableRow } from "../../../components"; +import type { DepositQuery } from "./__generated__/DepositQuery.graphql"; +import { getStatusTextAndColors } from "../utils/processStatus"; +import { centsToUnit } from "../../../utils/fiatMoney"; +import { Messages } from "../../../messages"; + +export const Deposit: FC = () => { + const { depositOrders } = useLazyLoadQuery( + graphql` + query DepositQuery { + depositOrders { + edges { + node { + id + status + createdAt + paidAmountCents + receivedAmountCents + } + } + } + } + `, + {} + ); + + if (!depositOrders.edges.length) + return ; + + return ( +
+
+
+
+ + {depositOrders.edges.map(({ node }) => { + const [label, textStyles, bgStyles] = getStatusTextAndColors( + node.status + ); + + const status = ( + + + ); + + return ( + + ); + })} +
+
+
+
+
+ ); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts b/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts new file mode 100644 index 0000000..6505c04 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts @@ -0,0 +1,143 @@ +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from "relay-runtime"; +export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value"; +export type DepositQueryVariables = {}; +export type DepositQueryResponse = { + readonly depositOrders: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly status: ProcessStatus; + readonly createdAt: unknown; + readonly paidAmountCents: number; + readonly receivedAmountCents: number; + }; + }>; + }; +}; +export type DepositQuery = { + readonly response: DepositQueryResponse; + readonly variables: DepositQueryVariables; +}; + + + +/* +query DepositQuery { + depositOrders { + edges { + node { + id + status + createdAt + paidAmountCents + receivedAmountCents + } + } + } +} +*/ + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrderConnection", + "kind": "LinkedField", + "name": "depositOrders", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrderEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrder", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "paidAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "receivedAmountCents", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } +]; +return { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "DepositQuery", + "selections": (v0/*: any*/), + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "DepositQuery", + "selections": (v0/*: any*/) + }, + "params": { + "cacheID": "50b4e177048e536e83735990104fce02", + "id": null, + "metadata": {}, + "name": "DepositQuery", + "operationKind": "query", + "text": "query DepositQuery {\n depositOrders {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmountCents\n }\n }\n }\n}\n" + } +}; +})(); +(node as any).hash = 'f4d2d75a8903d262de47e02f44136a65'; +export default node; diff --git a/app/javascript/src/pages/Orders/Deposit/index.ts b/app/javascript/src/pages/Orders/Deposit/index.ts new file mode 100644 index 0000000..e131aa2 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/index.ts @@ -0,0 +1 @@ +export * from "./Deposit"; diff --git a/app/javascript/src/pages/Orders/Stake/Stake.tsx b/app/javascript/src/pages/Orders/Stake/Stake.tsx index c05f2f7..9a24b1a 100644 --- a/app/javascript/src/pages/Orders/Stake/Stake.tsx +++ b/app/javascript/src/pages/Orders/Stake/Stake.tsx @@ -37,7 +37,7 @@ export const Stake: FC = () => {
- +
{stakeOrders.edges.map(({ node }) => { const [label, textStyles, bgStyles] = getStatusTextAndColors( node.status From c7a799af1e1ea6d3bd8c09f6ec17ccd39e2f7d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sun, 5 Sep 2021 22:32:15 -0300 Subject: [PATCH 5/6] add createDepositOrder mutation --- .../create_deposit_order_attributes_input.rb | 6 ++++ app/graphql/mutations/create_deposit_order.rb | 19 +++++++++++ app/graphql/types/mutation_type.rb | 1 + app/javascript/__generated__/schema.graphql | 33 +++++++++++++++++++ app/services/build_deposit_order.rb | 19 +++++++++++ 5 files changed, 78 insertions(+) create mode 100644 app/graphql/inputs/create_deposit_order_attributes_input.rb create mode 100644 app/graphql/mutations/create_deposit_order.rb create mode 100644 app/services/build_deposit_order.rb diff --git a/app/graphql/inputs/create_deposit_order_attributes_input.rb b/app/graphql/inputs/create_deposit_order_attributes_input.rb new file mode 100644 index 0000000..245eac7 --- /dev/null +++ b/app/graphql/inputs/create_deposit_order_attributes_input.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +module Inputs + class CreateDepositOrderAttributesInput < Types::BaseInputObject + argument :amount_cents, Integer, "Amount to be paid", required: true + end +end diff --git a/app/graphql/mutations/create_deposit_order.rb b/app/graphql/mutations/create_deposit_order.rb new file mode 100644 index 0000000..8be66e6 --- /dev/null +++ b/app/graphql/mutations/create_deposit_order.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true +module Mutations + class CreateDepositOrder < BaseMutation + field :order, Types::DepositOrderType, null: true + + argument :order, Inputs::CreateStakeOrderAttributesInput, required: true + + def resolve(order:) + ActiveRecord::Base.transaction do + record = BuildDepositOrder.new(paid_amount_cents: order[:amount_cents], user: current_user.id) + record.save! + + { order: record } + rescue ActiveRecord::RecordInvalid => e + { errors: Resolvers::ModelErrors.from_active_record_model(e.record) } + end + end + end +end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index c4eee07..3458594 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true module Types class MutationType < Types::BaseObject + field :create_deposit_order, mutation: Mutations::CreateDepositOrder field :create_stake_remove_order, mutation: Mutations::CreateStakeRemoveOrder field :create_stake_order, mutation: Mutations::CreateStakeOrder field :create_sell_crypto_order, mutation: Mutations::CreateSellCryptoOrder diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index fc23c6a..e895691 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -76,6 +76,33 @@ type CreateBuyCryptoOrderPayload { order: BuyCryptoOrder } +""" +Autogenerated input type of CreateDepositOrder +""" +input CreateDepositOrderInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + order: CreateStakeOrderAttributesInput! +} + +""" +Autogenerated return type of CreateDepositOrder +""" +type CreateDepositOrderPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [RecordInvalid!] + order: DepositOrder +} + input CreateSellCryptoOrderAttributesInput { """ Amount to be paid @@ -233,6 +260,12 @@ type Mutation { """ input: CreateBuyCryptoOrderInput! ): CreateBuyCryptoOrderPayload + createDepositOrder( + """ + Parameters for CreateDepositOrder + """ + input: CreateDepositOrderInput! + ): CreateDepositOrderPayload createSellCryptoOrder( """ Parameters for CreateSellCryptoOrder diff --git a/app/services/build_deposit_order.rb b/app/services/build_deposit_order.rb new file mode 100644 index 0000000..9f19023 --- /dev/null +++ b/app/services/build_deposit_order.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true +class BuildDepositOrder + DEPOSIT_FEE = 0.05 + + attr_reader :paid_amount_cents, :user_id + + def initilize(paid_amount_cents:, user_id:) + @paid_amount_cents = paid_amount_cents + @user_id = user_id + end + + def build + DepositOrder.new( + user_id: user_id, + paid_amount_cents: paid_amount_cents, + received_amount_cents: paid_amount_cents + (paid_amount_cents * DEPOSIT_FEE) + ) + end +end From 3529773c61c41792198b3397678d05e4c291b92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Mon, 6 Sep 2021 00:38:48 -0300 Subject: [PATCH 6/6] add pix qr code to deposit order --- app/graphql/types/base_connection.rb | 6 + app/graphql/types/deposit_order_type.rb | 1 + app/javascript/__generated__/schema.graphql | 5 + app/javascript/src/components/Modal/Modal.tsx | 16 +- .../src/components/Table/TableRow.tsx | 12 +- .../src/pages/Orders/Deposit/Deposit.tsx | 63 +---- .../pages/Orders/Deposit/History/History.tsx | 87 +++++++ .../History_depositOrders.graphql.ts | 102 ++++++++ .../src/pages/Orders/Deposit/History/index.ts | 1 + .../src/pages/Orders/Deposit/Show/Show.tsx | 94 ++++++++ .../Show_deposit_order.graphql.ts | 70 ++++++ .../Orders/Deposit/Show/hooks/usePixQr.ts | 33 +++ .../src/pages/Orders/Deposit/Show/index.ts | 1 + .../__generated__/DepositQuery.graphql.ts | 225 ++++++++++-------- app/models/deposit_order.rb | 1 + db/migrate/20210906021555_enable_uuid.rb | 6 + ...610_add_transaction_id_to_despoit_order.rb | 6 + db/schema.rb | 4 +- erd.svg | 118 ++++----- package.json | 2 + spec/factories/deposit_orders.rb | 1 + spec/models/deposit_order_spec.rb | 1 + yarn.lock | 209 +++++++++++++++- 23 files changed, 843 insertions(+), 221 deletions(-) create mode 100644 app/javascript/src/pages/Orders/Deposit/History/History.tsx create mode 100644 app/javascript/src/pages/Orders/Deposit/History/__generated__/History_depositOrders.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Deposit/History/index.ts create mode 100644 app/javascript/src/pages/Orders/Deposit/Show/Show.tsx create mode 100644 app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Deposit/Show/hooks/usePixQr.ts create mode 100644 app/javascript/src/pages/Orders/Deposit/Show/index.ts create mode 100644 db/migrate/20210906021555_enable_uuid.rb create mode 100644 db/migrate/20210906021610_add_transaction_id_to_despoit_order.rb diff --git a/app/graphql/types/base_connection.rb b/app/graphql/types/base_connection.rb index 1e1b775..6a79da0 100644 --- a/app/graphql/types/base_connection.rb +++ b/app/graphql/types/base_connection.rb @@ -5,5 +5,11 @@ module Types has_nodes_field(false) edges_nullable(false) edge_nullable(false) + + field :total_count, Integer, null: false + + def total_count + object.items.count + end end end diff --git a/app/graphql/types/deposit_order_type.rb b/app/graphql/types/deposit_order_type.rb index d3ef59e..9689dc7 100644 --- a/app/graphql/types/deposit_order_type.rb +++ b/app/graphql/types/deposit_order_type.rb @@ -10,6 +10,7 @@ module Types field :status, ProcessStatusEnum, null: false field :received_amount_cents, Integer, null: false field :paid_amount_cents, Integer, null: false + field :transaction_id, String, null: false field :created_at, GraphQL::Types::ISO8601DateTime, null: false field :updated_at, GraphQL::Types::ISO8601DateTime, null: false end diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index e895691..dd38274 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -25,6 +25,7 @@ type BuyCryptoOrderConnection { Information to aid in pagination. """ pageInfo: PageInfo! + totalCount: Int! } """ @@ -205,6 +206,7 @@ type DepositOrder implements Node { paidAmountCents: Int! receivedAmountCents: Int! status: ProcessStatus! + transactionId: String! updatedAt: ISO8601DateTime! } @@ -221,6 +223,7 @@ type DepositOrderConnection { Information to aid in pagination. """ pageInfo: PageInfo! + totalCount: Int! } """ @@ -478,6 +481,7 @@ type SellCryptoOrderConnection { Information to aid in pagination. """ pageInfo: PageInfo! + totalCount: Int! } """ @@ -517,6 +521,7 @@ type StakeOrderConnection { Information to aid in pagination. """ pageInfo: PageInfo! + totalCount: Int! } """ diff --git a/app/javascript/src/components/Modal/Modal.tsx b/app/javascript/src/components/Modal/Modal.tsx index 3069ba2..f54da3b 100644 --- a/app/javascript/src/components/Modal/Modal.tsx +++ b/app/javascript/src/components/Modal/Modal.tsx @@ -1,10 +1,11 @@ import type { FC } from "react"; import React, { Fragment } from "react"; import { Dialog, Transition } from "@headlessui/react"; +import cs from "classnames"; type Props = { isOpen: boolean; - setIsOpen: (state: boolean) => void; + setIsOpen?: (state: boolean) => void; title: string; className?: string; }; @@ -17,7 +18,9 @@ export const Modal: FC = ({ className = "", }) => { const closeModal = () => { - setIsOpen(false); + if (setIsOpen) { + setIsOpen(false); + } }; return ( @@ -25,7 +28,7 @@ export const Modal: FC = ({
@@ -56,7 +59,12 @@ export const Modal: FC = ({ leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > -
+
; + id?: string; + onClick?: (itemId: string) => void; }; -export const TableRow: FC = ({ items }) => { +export const TableRow: FC = ({ items, id, onClick }) => { + const handleClick = () => { + if (onClick && id) { + onClick(id); + } + }; + return ( -
+ {items?.map((item, index) => (
{ const { depositOrders } = useLazyLoadQuery( graphql` query DepositQuery { depositOrders { - edges { - node { - id - status - createdAt - paidAmountCents - receivedAmountCents - } - } + totalCount + ...History_depositOrders } } `, {} ); - if (!depositOrders.edges.length) + if (!depositOrders.totalCount) return ; return ( @@ -38,50 +28,7 @@ export const Deposit: FC = () => {
- - {depositOrders.edges.map(({ node }) => { - const [label, textStyles, bgStyles] = getStatusTextAndColors( - node.status - ); - - const status = ( - - - ); - - return ( - - ); - })} -
+
diff --git a/app/javascript/src/pages/Orders/Deposit/History/History.tsx b/app/javascript/src/pages/Orders/Deposit/History/History.tsx new file mode 100644 index 0000000..a6882d9 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/History/History.tsx @@ -0,0 +1,87 @@ +import { graphql } from "babel-plugin-relay/macro"; +import type { FC } from "react"; +import React, { useState } from "react"; +import cs from "classnames"; +import { useFragment } from "react-relay"; + +import { Table, TableRow } from "../../../../components"; +import { getStatusTextAndColors } from "../../utils/processStatus"; +import { centsToUnit } from "../../../../utils/fiatMoney"; +import type { History_depositOrders$key } from "./__generated__/History_depositOrders.graphql"; +import { Show } from "../Show"; + +type Props = { + ordersRef: History_depositOrders$key; +}; + +export const History: FC = ({ ordersRef }) => { + const [openOrderId, setOpenOrderId] = useState(null); + + const { edges } = useFragment( + graphql` + fragment History_depositOrders on DepositOrderConnection { + edges { + node { + id + status + createdAt + paidAmountCents + receivedAmountCents + ...Show_deposit_order + } + } + } + `, + ordersRef + ); + + const openOrder = edges.find(({ node }) => node.id === openOrderId); + const onClose = () => setOpenOrderId(null); + + return ( + <> + {openOrder && } + + {edges.map(({ node }) => { + const [label, textStyles, bgStyles] = getStatusTextAndColors( + node.status + ); + + const status = ( + + + ); + + return ( + setOpenOrderId(orderId)} + id={node.id} + items={[ + `${centsToUnit(node.paidAmountCents)} BRL`, + `${centsToUnit(node.receivedAmountCents)} BRL`, + new Date(node.createdAt as string).toLocaleTimeString(), + status, + ]} + /> + ); + })} +
+ + ); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/History/__generated__/History_depositOrders.graphql.ts b/app/javascript/src/pages/Orders/Deposit/History/__generated__/History_depositOrders.graphql.ts new file mode 100644 index 0000000..f177211 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/History/__generated__/History_depositOrders.graphql.ts @@ -0,0 +1,102 @@ +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from "relay-runtime"; +import { FragmentRefs } from "relay-runtime"; +export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value"; +export type History_depositOrders = { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly status: ProcessStatus; + readonly createdAt: unknown; + readonly paidAmountCents: number; + readonly receivedAmountCents: number; + readonly " $fragmentRefs": FragmentRefs<"Show_deposit_order">; + }; + }>; + readonly " $refType": "History_depositOrders"; +}; +export type History_depositOrders$data = History_depositOrders; +export type History_depositOrders$key = { + readonly " $data"?: History_depositOrders$data; + readonly " $fragmentRefs": FragmentRefs<"History_depositOrders">; +}; + + + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "History_depositOrders", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrderEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrder", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "paidAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "receivedAmountCents", + "storageKey": null + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "Show_deposit_order" + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "DepositOrderConnection", + "abstractKey": null +}; +(node as any).hash = 'f810eed214d3beb7c443588e670d8f39'; +export default node; diff --git a/app/javascript/src/pages/Orders/Deposit/History/index.ts b/app/javascript/src/pages/Orders/Deposit/History/index.ts new file mode 100644 index 0000000..a54747e --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/History/index.ts @@ -0,0 +1 @@ +export * from "./History"; diff --git a/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx b/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx new file mode 100644 index 0000000..5f61dae --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx @@ -0,0 +1,94 @@ +import { graphql } from "babel-plugin-relay/macro"; +import type { FC } from "react"; +import React from "react"; +import { useFragment } from "react-relay"; +import copy from "copy-to-clipboard"; + +import { Button, Modal } from "../../../../components"; +import { usePixQr } from "./hooks/usePixQr"; +import type { Show_deposit_order$key } from "./__generated__/Show_deposit_order.graphql"; +import { centsToUnit } from "../../../../utils/fiatMoney"; +import { getStatusTextAndColors } from "../../utils/processStatus"; + +type Props = { + orderRef: Show_deposit_order$key; + onClose: () => void; +}; + +export const Show: FC = ({ orderRef, onClose }) => { + const order = useFragment( + graphql` + fragment Show_deposit_order on DepositOrder { + transactionId + paidAmountCents + receivedAmountCents + status + createdAt + } + `, + orderRef + ); + + const { qr, payload } = usePixQr({ + value: order.paidAmountCents / 100, + transactionId: order.transactionId, + }); + + const handleClose = (_value: boolean) => { + onClose(); + }; + + const handleCopy = () => { + copy(payload); + }; + + const [statusLabel] = getStatusTextAndColors(order.status); + + return ( + +
+
+
    +
  • + Montante pago:{" "} + + {centsToUnit(order.paidAmountCents)} BRL + +
  • +
  • + Montante recebido:{" "} + + {centsToUnit(order.receivedAmountCents)} + +
  • +
  • + Pedido feito em:{" "} + + {new Date(order.createdAt as string).toLocaleTimeString()} + +
  • +
  • + Metodo de pagamento: PIX +
  • +
  • + Status: {statusLabel} +
  • +
+
+
+ QR code para o PIX de deposito + +
+
+
+ ); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts b/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts new file mode 100644 index 0000000..8ffbd48 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from "relay-runtime"; +import { FragmentRefs } from "relay-runtime"; +export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value"; +export type Show_deposit_order = { + readonly transactionId: string; + readonly paidAmountCents: number; + readonly receivedAmountCents: number; + readonly status: ProcessStatus; + readonly createdAt: unknown; + readonly " $refType": "Show_deposit_order"; +}; +export type Show_deposit_order$data = Show_deposit_order; +export type Show_deposit_order$key = { + readonly " $data"?: Show_deposit_order$data; + readonly " $fragmentRefs": FragmentRefs<"Show_deposit_order">; +}; + + + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "Show_deposit_order", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "transactionId", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "paidAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "receivedAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + } + ], + "type": "DepositOrder", + "abstractKey": null +}; +(node as any).hash = '73e84cef63c17faa3087f19ba2c73e69'; +export default node; diff --git a/app/javascript/src/pages/Orders/Deposit/Show/hooks/usePixQr.ts b/app/javascript/src/pages/Orders/Deposit/Show/hooks/usePixQr.ts new file mode 100644 index 0000000..dfbc310 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Show/hooks/usePixQr.ts @@ -0,0 +1,33 @@ +import { useEffect, useState } from "react"; +import { QrCodePix } from "qrcode-pix"; + +type Props = { + value: number; + transactionId: string; +}; + +export const usePixQr = ({ value, transactionId }: Props) => { + const [qr, setQr] = useState(); + + const qrCodePix = QrCodePix({ + version: "01", + key: "joao.geonizeli@gmail.com", + name: "X Stake", + city: "TERESOPOLIS", + transactionId, + value, + notRepeatPayment: true, + }); + + useEffect(() => { + qrCodePix.base64().then((result) => { + setQr(result); + }); + }, []); + + return { + payload: qrCodePix.payload(), + loading: !qr, + qr, + }; +}; diff --git a/app/javascript/src/pages/Orders/Deposit/Show/index.ts b/app/javascript/src/pages/Orders/Deposit/Show/index.ts new file mode 100644 index 0000000..af83ede --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Show/index.ts @@ -0,0 +1 @@ +export * from "./Show"; diff --git a/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts b/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts index 6505c04..0bcf7ef 100644 --- a/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts +++ b/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts @@ -3,19 +3,12 @@ // @ts-nocheck import { ConcreteRequest } from "relay-runtime"; -export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value"; +import { FragmentRefs } from "relay-runtime"; export type DepositQueryVariables = {}; export type DepositQueryResponse = { readonly depositOrders: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly id: string; - readonly status: ProcessStatus; - readonly createdAt: unknown; - readonly paidAmountCents: number; - readonly receivedAmountCents: number; - }; - }>; + readonly totalCount: number; + readonly " $fragmentRefs": FragmentRefs<"History_depositOrders">; }; }; export type DepositQuery = { @@ -28,97 +21,66 @@ export type DepositQuery = { /* query DepositQuery { depositOrders { - edges { - node { - id - status - createdAt - paidAmountCents - receivedAmountCents - } + totalCount + ...History_depositOrders + } +} + +fragment History_depositOrders on DepositOrderConnection { + edges { + node { + id + status + createdAt + paidAmountCents + receivedAmountCents + ...Show_deposit_order } } } + +fragment Show_deposit_order on DepositOrder { + transactionId + paidAmountCents + receivedAmountCents + status + createdAt +} */ const node: ConcreteRequest = (function(){ -var v0 = [ - { - "alias": null, - "args": null, - "concreteType": "DepositOrderConnection", - "kind": "LinkedField", - "name": "depositOrders", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "DepositOrderEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "DepositOrder", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "status", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "paidAmountCents", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "receivedAmountCents", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } -]; +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "totalCount", + "storageKey": null +}; return { "fragment": { "argumentDefinitions": [], "kind": "Fragment", "metadata": null, "name": "DepositQuery", - "selections": (v0/*: any*/), + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrderConnection", + "kind": "LinkedField", + "name": "depositOrders", + "plural": false, + "selections": [ + (v0/*: any*/), + { + "args": null, + "kind": "FragmentSpread", + "name": "History_depositOrders" + } + ], + "storageKey": null + } + ], "type": "Query", "abstractKey": null }, @@ -127,17 +89,94 @@ return { "argumentDefinitions": [], "kind": "Operation", "name": "DepositQuery", - "selections": (v0/*: any*/) + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrderConnection", + "kind": "LinkedField", + "name": "depositOrders", + "plural": false, + "selections": [ + (v0/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "DepositOrderEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrder", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "paidAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "receivedAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "transactionId", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ] }, "params": { - "cacheID": "50b4e177048e536e83735990104fce02", + "cacheID": "99f3fbbd023ef8a38b0490275cb58aa6", "id": null, "metadata": {}, "name": "DepositQuery", "operationKind": "query", - "text": "query DepositQuery {\n depositOrders {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmountCents\n }\n }\n }\n}\n" + "text": "query DepositQuery {\n depositOrders {\n totalCount\n ...History_depositOrders\n }\n}\n\nfragment History_depositOrders on DepositOrderConnection {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmountCents\n ...Show_deposit_order\n }\n }\n}\n\nfragment Show_deposit_order on DepositOrder {\n transactionId\n paidAmountCents\n receivedAmountCents\n status\n createdAt\n}\n" } }; })(); -(node as any).hash = 'f4d2d75a8903d262de47e02f44136a65'; +(node as any).hash = '8394525008fabe782ee41126e50d63b1'; export default node; diff --git a/app/models/deposit_order.rb b/app/models/deposit_order.rb index 947c3c3..4998f82 100644 --- a/app/models/deposit_order.rb +++ b/app/models/deposit_order.rb @@ -10,6 +10,7 @@ # status :string not null # created_at :datetime not null # updated_at :datetime not null +# transaction_id :uuid not null # user_id :bigint not null # # Indexes diff --git a/db/migrate/20210906021555_enable_uuid.rb b/db/migrate/20210906021555_enable_uuid.rb new file mode 100644 index 0000000..558ea52 --- /dev/null +++ b/db/migrate/20210906021555_enable_uuid.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class EnableUuid < ActiveRecord::Migration[6.1] + def change + enable_extension("pgcrypto") + end +end diff --git a/db/migrate/20210906021610_add_transaction_id_to_despoit_order.rb b/db/migrate/20210906021610_add_transaction_id_to_despoit_order.rb new file mode 100644 index 0000000..dc32e32 --- /dev/null +++ b/db/migrate/20210906021610_add_transaction_id_to_despoit_order.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class AddTransactionIdToDespoitOrder < ActiveRecord::Migration[6.1] + def change + add_column(:deposit_orders, :transaction_id, :uuid, default: "gen_random_uuid()", null: false) + end +end diff --git a/db/schema.rb b/db/schema.rb index 7e98d4f..ee33d14 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,10 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_09_05_234913) do +ActiveRecord::Schema.define(version: 2021_09_06_021610) do # These are extensions that must be enabled in order to support this database + enable_extension "pgcrypto" enable_extension "plpgsql" create_table "active_storage_attachments", force: :cascade do |t| @@ -80,6 +81,7 @@ ActiveRecord::Schema.define(version: 2021_09_05_234913) do t.integer "paid_amount_cents", default: 0, null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.uuid "transaction_id", default: -> { "gen_random_uuid()" }, null: false t.index ["user_id"], name: "index_deposit_orders_on_user_id" end diff --git a/erd.svg b/erd.svg index 508d039..1c4f24f 100644 --- a/erd.svg +++ b/erd.svg @@ -4,12 +4,12 @@ - - + + XStake - -XStake domain model + +XStake domain model m_AdminUser @@ -30,72 +30,74 @@ m_Balance - -Balance - -amount -decimal (20,10) ∗ -user_id -integer (8) ∗ FK + +Balance + +amount +decimal (20,10) ∗ +user_id +integer (8) ∗ FK m_PaperTrail::Version - -PaperTrail::Version - -event -string ∗ -item_id -integer (8) ∗ FK -item_type -string ∗ -object -text -whodunnit -string + +PaperTrail::Version + +event +string ∗ +item_id +integer (8) ∗ FK +item_type +string ∗ +object +text +whodunnit +string m_Balance->m_PaperTrail::Version - - + + m_BuyCryptoOrder - -BuyCryptoOrder - -paid_amount_cents -integer ∗ -received_amount -decimal (20,10) ∗ -status -string ∗ -user_id -integer (8) ∗ FK + +BuyCryptoOrder + +paid_amount_cents +integer ∗ +received_amount +decimal (20,10) ∗ +status +string ∗ +user_id +integer (8) ∗ FK m_DepositOrder - -DepositOrder - -paid_amount_cents -integer ∗ -received_amount_cents -integer ∗ -status -string ∗ -user_id -integer (8) ∗ FK + +DepositOrder + +paid_amount_cents +integer ∗ +received_amount_cents +integer ∗ +status +string ∗ +transaction_id +uuid ∗ +user_id +integer (8) ∗ FK m_DepositOrder->m_PaperTrail::Version - - + + @@ -113,8 +115,8 @@ m_FiatBalance->m_PaperTrail::Version - - + + @@ -172,19 +174,19 @@ m_User->m_Balance - + m_User->m_BuyCryptoOrder - - + + m_User->m_DepositOrder - - + + diff --git a/package.json b/package.json index e3b02e6..e14c7ad 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,11 @@ "babel-plugin-relay": "^11.0.2", "bignumber.js": "^9.0.1", "classnames": "^2.3.1", + "copy-to-clipboard": "^3.3.1", "ethers": "^5.4.4", "graphql-scalars": "^1.10.0", "postcss": "^7", + "qrcode-pix": "^3.0.3", "ramda": "^0.27.1", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/spec/factories/deposit_orders.rb b/spec/factories/deposit_orders.rb index 869cf26..1f3faae 100644 --- a/spec/factories/deposit_orders.rb +++ b/spec/factories/deposit_orders.rb @@ -10,6 +10,7 @@ # status :string not null # created_at :datetime not null # updated_at :datetime not null +# transaction_id :uuid not null # user_id :bigint not null # # Indexes diff --git a/spec/models/deposit_order_spec.rb b/spec/models/deposit_order_spec.rb index 13164d1..8a4a1b5 100644 --- a/spec/models/deposit_order_spec.rb +++ b/spec/models/deposit_order_spec.rb @@ -10,6 +10,7 @@ # status :string not null # created_at :datetime not null # updated_at :datetime not null +# transaction_id :uuid not null # user_id :bigint not null # # Indexes diff --git a/yarn.lock b/yarn.lock index b8a8d54..7df691a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1053,6 +1053,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.5": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" @@ -1491,6 +1498,17 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1594,6 +1612,33 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.9.tgz#1cfb6d60ef3822c589f18e70f8b12f9a28ce8724" integrity sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^26.0.15": + version "26.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" + integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== + dependencies: + jest-diff "^26.0.0" + pretty-format "^26.0.0" + "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -1682,6 +1727,18 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^4.28.0": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.0.tgz#b866c9cd193bfaba5e89bade0015629ebeb27996" @@ -2345,7 +2402,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2563,7 +2620,25 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-from@^1.0.0: +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0, buffer-from@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -2587,6 +2662,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.4.3: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -3039,6 +3122,13 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +copy-to-clipboard@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" + integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== + dependencies: + toggle-selection "^1.0.6" + core-js-compat@^3.14.0, core-js-compat@^3.16.0: version "3.16.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.16.0.tgz#fced4a0a534e7e02f7e084bff66c701f8281805f" @@ -3519,6 +3609,11 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3528,6 +3623,11 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dijkstrajs@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257" + integrity sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4946,7 +5046,7 @@ icss-utils@^4.0.0, icss-utils@^4.1.1: dependencies: postcss "^7.0.14" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -5407,6 +5507,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -5424,6 +5529,21 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +jest-diff@^26.0.0: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + jest-worker@^26.5.0: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -5657,6 +5777,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.11: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -5707,7 +5832,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21, lodash@^4.17.5: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6686,6 +6811,11 @@ please-upgrade-node@^3.2.0: dependencies: semver-compare "^1.0.0" +pngjs@^3.3.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + pnp-webpack-plugin@^1.6.4: version "1.7.0" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz#65741384f6d8056f36e2255a8d67ffc20866f5c9" @@ -6693,6 +6823,11 @@ pnp-webpack-plugin@^1.6.4: dependencies: ts-pnp "^1.1.6" +polycrc@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/polycrc/-/polycrc-1.1.0.tgz#7ee75bd0b47d377d26d78ee7f5c529dde0c77af0" + integrity sha512-rEOTU2hpsys8CwOre1XptjEm1pGA8F2mCLI0Hxb1lc7HweXi0m9K70FX5uiGB63v1kklyZ0UfbWNo7pOXp/BHg== + portfinder@^1.0.26: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" @@ -7423,6 +7558,16 @@ prettier@^2.3.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== +pretty-format@^26.0.0, pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" @@ -7464,6 +7609,11 @@ prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +property-expr@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910" + integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + proxy-addr@~2.0.5: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -7544,6 +7694,29 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +qrcode-pix@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/qrcode-pix/-/qrcode-pix-3.0.3.tgz#2cc050f42ce216fad0092d8d82c95b0e8a51ff1d" + integrity sha512-/4j4ibP0PLmhvJRJTPUv6RSNn6iJ3CmVke1i59v8gbiB1N7V0ZJZ0tgZoGMeQ85H9X0I8hzaQhtet0KX0YMANg== + dependencies: + "@types/jest" "^26.0.15" + polycrc "^1.0.1" + qrcode "^1.4.4" + yup "^0.30.0" + +qrcode@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83" + integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q== + dependencies: + buffer "^5.4.3" + buffer-alloc "^1.2.0" + buffer-from "^1.1.1" + dijkstrajs "^1.0.1" + isarray "^2.0.1" + pngjs "^3.3.0" + yargs "^13.2.4" + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -7631,6 +7804,11 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-relay@^11.0.2: version "11.0.2" resolved "https://registry.yarnpkg.com/react-relay/-/react-relay-11.0.2.tgz#5f77e30e0d592f19c641e5dcc42f5d828bd16da5" @@ -8914,11 +9092,21 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toggle-selection@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + ts-pnp@^1.1.6: version "1.2.0" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" @@ -9487,7 +9675,7 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^13.3.2: +yargs@^13.2.4, yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== @@ -9524,3 +9712,14 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yup@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.30.0.tgz#427ee076abb1d7e01e747fb782801f7df252fb76" + integrity sha512-GX3vqpC9E+Ow0fmQPgqbEg7UV40XRrN1IOEgKF5v04v6T4ha2vBas/hu0thWgewk8L4wUEBLRO/EnXwYyP+p+A== + dependencies: + "@babel/runtime" "^7.10.5" + lodash "^4.17.20" + lodash-es "^4.17.11" + property-expr "^2.0.4" + toposort "^2.0.2"