add fiat balance
This commit is contained in:
1
Gemfile
1
Gemfile
@@ -20,6 +20,7 @@ gem "devise-i18n"
|
||||
gem "administrate-field-active_storage"
|
||||
gem "tailwindcss-rails"
|
||||
gem "administrate"
|
||||
gem "money-rails"
|
||||
gem "enumerize"
|
||||
gem "graphql"
|
||||
gem "pundit"
|
||||
|
||||
10
Gemfile.lock
10
Gemfile.lock
@@ -157,6 +157,15 @@ GEM
|
||||
minitest (5.14.4)
|
||||
momentjs-rails (2.20.1)
|
||||
railties (>= 3.1)
|
||||
monetize (1.9.4)
|
||||
money (~> 6.12)
|
||||
money (6.13.8)
|
||||
i18n (>= 0.6.4, <= 2)
|
||||
money-rails (1.14.0)
|
||||
activesupport (>= 3.0)
|
||||
monetize (~> 1.9.0)
|
||||
money (~> 6.13.2)
|
||||
railties (>= 3.0)
|
||||
msgpack (1.4.2)
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.12.1)
|
||||
@@ -330,6 +339,7 @@ DEPENDENCIES
|
||||
graphql_playground-rails
|
||||
image_processing (~> 1.12)
|
||||
listen (~> 3.3)
|
||||
money-rails
|
||||
pg (~> 1.1)
|
||||
pry-byebug
|
||||
puma (~> 5.0)
|
||||
|
||||
15
app/graphql/types/fiat_balance_type.rb
Normal file
15
app/graphql/types/fiat_balance_type.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
module Types
|
||||
class FiatBalanceType < Types::BaseObject
|
||||
implements GraphQL::Types::Relay::Node
|
||||
global_id_field :id
|
||||
|
||||
graphql_name "FiatBalance"
|
||||
|
||||
field :id, ID, null: false
|
||||
field :amount_cents, Integer, null: false
|
||||
field :amount_currency, String, null: false
|
||||
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
|
||||
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
|
||||
end
|
||||
end
|
||||
@@ -13,5 +13,10 @@ module Types
|
||||
def balances
|
||||
Pundit.policy_scope(current_user, Balance)
|
||||
end
|
||||
|
||||
field :fiat_balances, FiatBalanceType.connection_type, null: false
|
||||
def fiat_balances
|
||||
Pundit.policy_scope(current_user, FiatBalance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,8 @@ class XStakeSchema < GraphQL::Schema
|
||||
Types::CurrencyType
|
||||
when Balance
|
||||
Types::BalanceType
|
||||
when FiatBalance
|
||||
Types::FiatBalanceType
|
||||
else
|
||||
raise(GraphQL::RequiredImplementationMissingError, "Unexpected object: #{obj}")
|
||||
end
|
||||
|
||||
71
app/javascript/__generated__/schema.graphql
generated
71
app/javascript/__generated__/schema.graphql
generated
@@ -1,5 +1,5 @@
|
||||
type Balance implements Node {
|
||||
amount: Float!
|
||||
amount: String!
|
||||
currency: Currency!
|
||||
id: ID!
|
||||
}
|
||||
@@ -44,6 +44,54 @@ type Currency implements Node {
|
||||
name: String!
|
||||
}
|
||||
|
||||
type FiatBalance implements Node {
|
||||
amountCents: Int!
|
||||
amountCurrency: String!
|
||||
createdAt: ISO8601DateTime!
|
||||
id: ID!
|
||||
updatedAt: ISO8601DateTime!
|
||||
}
|
||||
|
||||
"""
|
||||
The connection type for FiatBalance.
|
||||
"""
|
||||
type FiatBalanceConnection {
|
||||
"""
|
||||
A list of edges.
|
||||
"""
|
||||
edges: [FiatBalanceEdge]
|
||||
|
||||
"""
|
||||
A list of nodes.
|
||||
"""
|
||||
nodes: [FiatBalance]
|
||||
|
||||
"""
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
"""
|
||||
An edge in a connection.
|
||||
"""
|
||||
type FiatBalanceEdge {
|
||||
"""
|
||||
A cursor for use in pagination.
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
The item at the end of the edge.
|
||||
"""
|
||||
node: FiatBalance
|
||||
}
|
||||
|
||||
"""
|
||||
An ISO 8601-encoded datetime
|
||||
"""
|
||||
scalar ISO8601DateTime
|
||||
|
||||
"""
|
||||
An object with an ID.
|
||||
"""
|
||||
@@ -102,6 +150,27 @@ type Query {
|
||||
last: Int
|
||||
): BalanceConnection!
|
||||
currentUser: User
|
||||
fiatBalances(
|
||||
"""
|
||||
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
|
||||
): FiatBalanceConnection!
|
||||
|
||||
"""
|
||||
Fetches an object given its ID.
|
||||
|
||||
81
app/javascript/src/pages/Wallet/Balances.tsx
Normal file
81
app/javascript/src/pages/Wallet/Balances.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { graphql } from "babel-plugin-relay/macro";
|
||||
import type { FC } from "react";
|
||||
import React from "react";
|
||||
import { useFragment } from "react-relay";
|
||||
|
||||
import { getCurrencyLogo } from "../../utils/getCurrencyLogo";
|
||||
import type { Balances_balances$key } from "./__generated__/Balances_balances.graphql";
|
||||
|
||||
type Props = {
|
||||
balancesRef: Balances_balances$key;
|
||||
};
|
||||
export const Balances: FC<Props> = ({ balancesRef }) => {
|
||||
const { nodes } = useFragment<Balances_balances$key>(
|
||||
graphql`
|
||||
fragment Balances_balances on BalanceConnection {
|
||||
nodes {
|
||||
id
|
||||
amount
|
||||
currency {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
balancesRef
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto">
|
||||
<div className="inline-block min-w-full shadow rounded-lg overflow-hidden">
|
||||
<table className="min-w-full leading-normal">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
|
||||
>
|
||||
Moeda
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
|
||||
>
|
||||
Saldo
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{nodes?.map((balance) => {
|
||||
return (
|
||||
<tr key={balance?.id}>
|
||||
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<img
|
||||
alt={`${balance?.currency.name} icon`}
|
||||
src={getCurrencyLogo(balance?.currency.name)}
|
||||
className="mx-auto object-cover rounded-full h-10 w-10 "
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<p className="text-gray-900 whitespace-no-wrap">
|
||||
{balance?.currency.name}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
|
||||
<p className="text-gray-900 whitespace-no-wrap">
|
||||
{balance?.amount}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
58
app/javascript/src/pages/Wallet/FiatBalances.tsx
Normal file
58
app/javascript/src/pages/Wallet/FiatBalances.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { graphql } from "babel-plugin-relay/macro";
|
||||
import type { FC } from "react";
|
||||
import React from "react";
|
||||
import { useFragment } from "react-relay";
|
||||
|
||||
import type { FiatBalances_fiatBalances$key } from "./__generated__/FiatBalances_fiatBalances.graphql";
|
||||
|
||||
type Props = {
|
||||
fiatBalancesRef: FiatBalances_fiatBalances$key;
|
||||
};
|
||||
export const FiatBalances: FC<Props> = ({ fiatBalancesRef }) => {
|
||||
const { nodes } = useFragment<FiatBalances_fiatBalances$key>(
|
||||
graphql`
|
||||
fragment FiatBalances_fiatBalances on FiatBalanceConnection {
|
||||
nodes {
|
||||
id
|
||||
amountCents
|
||||
amountCurrency
|
||||
}
|
||||
}
|
||||
`,
|
||||
fiatBalancesRef
|
||||
);
|
||||
|
||||
if (!nodes?.length) return null;
|
||||
|
||||
const [firstResult] = nodes;
|
||||
|
||||
const amount = (
|
||||
firstResult?.amountCents ? firstResult?.amountCents / 100 : 0
|
||||
).toFixed(2);
|
||||
|
||||
return (
|
||||
<div className="shadow rounded-lg p-4 bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center">
|
||||
<span className="rounded-xl relative p-4 bg-green-200">
|
||||
<svg
|
||||
width="40"
|
||||
fill="currentColor"
|
||||
height="40"
|
||||
className="text-green-500 h-4 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
viewBox="0 0 1792 1792"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M1362 1185q0 153-99.5 263.5t-258.5 136.5v175q0 14-9 23t-23 9h-135q-13 0-22.5-9.5t-9.5-22.5v-175q-66-9-127.5-31t-101.5-44.5-74-48-46.5-37.5-17.5-18q-17-21-2-41l103-135q7-10 23-12 15-2 24 9l2 2q113 99 243 125 37 8 74 8 81 0 142.5-43t61.5-122q0-28-15-53t-33.5-42-58.5-37.5-66-32-80-32.5q-39-16-61.5-25t-61.5-26.5-62.5-31-56.5-35.5-53.5-42.5-43.5-49-35.5-58-21-66.5-8.5-78q0-138 98-242t255-134v-180q0-13 9.5-22.5t22.5-9.5h135q14 0 23 9t9 23v176q57 6 110.5 23t87 33.5 63.5 37.5 39 29 15 14q17 18 5 38l-81 146q-8 15-23 16-14 3-27-7-3-3-14.5-12t-39-26.5-58.5-32-74.5-26-85.5-11.5q-95 0-155 43t-60 111q0 26 8.5 48t29.5 41.5 39.5 33 56 31 60.5 27 70 27.5q53 20 81 31.5t76 35 75.5 42.5 62 50 53 63.5 31.5 76.5 13 94z" />
|
||||
</svg>
|
||||
</span>
|
||||
<p className="text-md text-black dark:text-white ml-2">Saldo Fiat</p>
|
||||
</div>
|
||||
<div className="flex flex-col justify-start">
|
||||
<p className="text-gray-700 dark:text-gray-100 text-4xl text-left font-bold my-4">
|
||||
{amount}
|
||||
<span className="text-sm">{firstResult?.amountCurrency}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -3,21 +3,19 @@ import type { FC } from "react";
|
||||
import React from "react";
|
||||
import { useLazyLoadQuery } from "react-relay";
|
||||
|
||||
import { getCurrencyLogo } from "../../utils/getCurrencyLogo";
|
||||
import { Balances } from "./Balances";
|
||||
import { FiatBalances } from "./FiatBalances";
|
||||
import type { WalletQuery } from "./__generated__/WalletQuery.graphql";
|
||||
|
||||
export const Wallet: FC = () => {
|
||||
const { balances } = useLazyLoadQuery<WalletQuery>(
|
||||
const { fiatBalances, balances } = useLazyLoadQuery<WalletQuery>(
|
||||
graphql`
|
||||
query WalletQuery {
|
||||
fiatBalances {
|
||||
...FiatBalances_fiatBalances
|
||||
}
|
||||
balances {
|
||||
nodes {
|
||||
id
|
||||
amount
|
||||
currency {
|
||||
name
|
||||
}
|
||||
}
|
||||
...Balances_balances
|
||||
}
|
||||
}
|
||||
`,
|
||||
@@ -28,57 +26,8 @@ export const Wallet: FC = () => {
|
||||
<div className="flex flex-col h-full w-full overflow-x-hidden">
|
||||
<div className="container mx-auto px-4 sm:px-8 max-w-3xl">
|
||||
<div className="py-8">
|
||||
<div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto">
|
||||
<div className="inline-block min-w-full shadow rounded-lg overflow-hidden">
|
||||
<table className="min-w-full leading-normal">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
|
||||
>
|
||||
Moeda
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
|
||||
>
|
||||
Saldo
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{balances.nodes?.map((balance) => {
|
||||
return (
|
||||
<tr key={balance?.id}>
|
||||
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<img
|
||||
alt={`${balance?.currency.name} icon`}
|
||||
src={getCurrencyLogo(balance?.currency.name)}
|
||||
className="mx-auto object-cover rounded-full h-10 w-10 "
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<p className="text-gray-900 whitespace-no-wrap">
|
||||
{balance?.currency.name}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
|
||||
<p className="text-gray-900 whitespace-no-wrap">
|
||||
{balance?.amount}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<FiatBalances fiatBalancesRef={fiatBalances} />
|
||||
<Balances balancesRef={balances} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
79
app/javascript/src/pages/Wallet/__generated__/Balances_balances.graphql.ts
generated
Normal file
79
app/javascript/src/pages/Wallet/__generated__/Balances_balances.graphql.ts
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from "relay-runtime";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type Balances_balances = {
|
||||
readonly nodes: ReadonlyArray<{
|
||||
readonly id: string;
|
||||
readonly amount: string;
|
||||
readonly currency: {
|
||||
readonly name: string;
|
||||
};
|
||||
} | null> | null;
|
||||
readonly " $refType": "Balances_balances";
|
||||
};
|
||||
export type Balances_balances$data = Balances_balances;
|
||||
export type Balances_balances$key = {
|
||||
readonly " $data"?: Balances_balances$data;
|
||||
readonly " $fragmentRefs": FragmentRefs<"Balances_balances">;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "Balances_balances",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Balance",
|
||||
"kind": "LinkedField",
|
||||
"name": "nodes",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amount",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Currency",
|
||||
"kind": "LinkedField",
|
||||
"name": "currency",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "BalanceConnection",
|
||||
"abstractKey": null
|
||||
};
|
||||
(node as any).hash = '2704da1dc9949b1becbd9ec947c5ec33';
|
||||
export default node;
|
||||
66
app/javascript/src/pages/Wallet/__generated__/FiatBalances_fiatBalances.graphql.ts
generated
Normal file
66
app/javascript/src/pages/Wallet/__generated__/FiatBalances_fiatBalances.graphql.ts
generated
Normal file
@@ -0,0 +1,66 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from "relay-runtime";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type FiatBalances_fiatBalances = {
|
||||
readonly nodes: ReadonlyArray<{
|
||||
readonly id: string;
|
||||
readonly amountCents: number;
|
||||
readonly amountCurrency: string;
|
||||
} | null> | null;
|
||||
readonly " $refType": "FiatBalances_fiatBalances";
|
||||
};
|
||||
export type FiatBalances_fiatBalances$data = FiatBalances_fiatBalances;
|
||||
export type FiatBalances_fiatBalances$key = {
|
||||
readonly " $data"?: FiatBalances_fiatBalances$data;
|
||||
readonly " $fragmentRefs": FragmentRefs<"FiatBalances_fiatBalances">;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "FiatBalances_fiatBalances",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "FiatBalance",
|
||||
"kind": "LinkedField",
|
||||
"name": "nodes",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amountCents",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amountCurrency",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "FiatBalanceConnection",
|
||||
"abstractKey": null
|
||||
};
|
||||
(node as any).hash = '0584f36abe6ca6f8612b8c593c4cfb6d';
|
||||
export default node;
|
||||
@@ -3,16 +3,14 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from "relay-runtime";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type WalletQueryVariables = {};
|
||||
export type WalletQueryResponse = {
|
||||
readonly balances: {
|
||||
readonly nodes: ReadonlyArray<{
|
||||
readonly id: string;
|
||||
readonly amount: number;
|
||||
readonly currency: {
|
||||
readonly name: string;
|
||||
readonly fiatBalances: {
|
||||
readonly " $fragmentRefs": FragmentRefs<"FiatBalances_fiatBalances">;
|
||||
};
|
||||
} | null> | null;
|
||||
readonly balances: {
|
||||
readonly " $fragmentRefs": FragmentRefs<"Balances_balances">;
|
||||
};
|
||||
};
|
||||
export type WalletQuery = {
|
||||
@@ -24,7 +22,15 @@ export type WalletQuery = {
|
||||
|
||||
/*
|
||||
query WalletQuery {
|
||||
fiatBalances {
|
||||
...FiatBalances_fiatBalances
|
||||
}
|
||||
balances {
|
||||
...Balances_balances
|
||||
}
|
||||
}
|
||||
|
||||
fragment Balances_balances on BalanceConnection {
|
||||
nodes {
|
||||
id
|
||||
amount
|
||||
@@ -34,6 +40,13 @@ query WalletQuery {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment FiatBalances_fiatBalances on FiatBalanceConnection {
|
||||
nodes {
|
||||
id
|
||||
amountCents
|
||||
amountCurrency
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -44,20 +57,6 @@ var v0 = {
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amount",
|
||||
"storageKey": null
|
||||
},
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
@@ -66,6 +65,22 @@ return {
|
||||
"metadata": null,
|
||||
"name": "WalletQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "FiatBalanceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "fiatBalances",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "FiatBalances_fiatBalances"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -75,29 +90,9 @@ return {
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Balance",
|
||||
"kind": "LinkedField",
|
||||
"name": "nodes",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Currency",
|
||||
"kind": "LinkedField",
|
||||
"name": "currency",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"kind": "FragmentSpread",
|
||||
"name": "Balances_balances"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -112,6 +107,43 @@ return {
|
||||
"kind": "Operation",
|
||||
"name": "WalletQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "FiatBalanceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "fiatBalances",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "FiatBalance",
|
||||
"kind": "LinkedField",
|
||||
"name": "nodes",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amountCents",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amountCurrency",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -129,7 +161,13 @@ return {
|
||||
"plural": true,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "amount",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -138,7 +176,13 @@ return {
|
||||
"name": "currency",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -152,14 +196,14 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "6b8d0c664bd2d9df4d323c19c4a823a5",
|
||||
"cacheID": "82d013e2bf418b53aeec5412f2f92661",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "WalletQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query WalletQuery {\n balances {\n nodes {\n id\n amount\n currency {\n name\n id\n }\n }\n }\n}\n"
|
||||
"text": "query WalletQuery {\n fiatBalances {\n ...FiatBalances_fiatBalances\n }\n balances {\n ...Balances_balances\n }\n}\n\nfragment Balances_balances on BalanceConnection {\n nodes {\n id\n amount\n currency {\n name\n id\n }\n }\n}\n\nfragment FiatBalances_fiatBalances on FiatBalanceConnection {\n nodes {\n id\n amountCents\n amountCurrency\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
(node as any).hash = '428f4f1ab769f9056dd38ec641a30733';
|
||||
(node as any).hash = '855efce679c691a77938b64376a1a805';
|
||||
export default node;
|
||||
|
||||
28
app/models/fiat_balance.rb
Normal file
28
app/models/fiat_balance.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: fiat_balances
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# amount_cents :integer default(0), not null
|
||||
# amount_currency :string default("BRL"), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# user_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_fiat_balances_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (user_id => users.id)
|
||||
#
|
||||
class FiatBalance < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
monetize :amount_cents
|
||||
|
||||
validates :amount, presence: true
|
||||
end
|
||||
@@ -26,6 +26,7 @@ class User < ApplicationRecord
|
||||
|
||||
has_many :documents, class_name: "UserDocument", dependent: :destroy
|
||||
has_many :balances, dependent: :restrict_with_error
|
||||
has_one :fiat_balance, dependent: :restrict_with_error
|
||||
|
||||
validates :first_name, :last_name, :email, presence: true
|
||||
validates :email, uniqueness: true
|
||||
|
||||
10
app/policies/fiat_balance_policy.rb
Normal file
10
app/policies/fiat_balance_policy.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
class FiatBalancePolicy < ApplicationPolicy
|
||||
class Scope < Scope
|
||||
def resolve
|
||||
return scope.none if user.nil?
|
||||
|
||||
scope.where(user_id: user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
7
config/initializers/money.rb
Normal file
7
config/initializers/money.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
MoneyRails.configure do |config|
|
||||
config.default_currency = :brl
|
||||
config.rounding_mode = BigDecimal::ROUND_HALF_UP
|
||||
config.locale_backend = :i18n
|
||||
end
|
||||
11
db/migrate/20210812011039_create_fiat_balances.rb
Normal file
11
db/migrate/20210812011039_create_fiat_balances.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
class CreateFiatBalances < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table(:fiat_balances) do |t|
|
||||
t.references(:user, null: false, foreign_key: true)
|
||||
t.monetize(:amount)
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
12
db/schema.rb
generated
12
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_08_11_121726) do
|
||||
ActiveRecord::Schema.define(version: 2021_08_12_011039) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@@ -71,6 +71,15 @@ ActiveRecord::Schema.define(version: 2021_08_11_121726) do
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
end
|
||||
|
||||
create_table "fiat_balances", force: :cascade do |t|
|
||||
t.bigint "user_id", null: false
|
||||
t.integer "amount_cents", default: 0, null: false
|
||||
t.string "amount_currency", default: "BRL", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["user_id"], name: "index_fiat_balances_on_user_id"
|
||||
end
|
||||
|
||||
create_table "user_documents", force: :cascade do |t|
|
||||
t.string "status", null: false
|
||||
t.bigint "user_id", null: false
|
||||
@@ -97,5 +106,6 @@ ActiveRecord::Schema.define(version: 2021_08_11_121726) do
|
||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "balances", "currencies"
|
||||
add_foreign_key "balances", "users"
|
||||
add_foreign_key "fiat_balances", "users"
|
||||
add_foreign_key "user_documents", "users"
|
||||
end
|
||||
|
||||
@@ -214,3 +214,5 @@ currencies.each do |currency|
|
||||
amount: random_floating_number
|
||||
)
|
||||
end
|
||||
|
||||
FiatBalance.create(user_id: user.id)
|
||||
|
||||
26
spec/models/fiat_balance_spec.rb
Normal file
26
spec/models/fiat_balance_spec.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: fiat_balances
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# amount_cents :integer default(0), not null
|
||||
# amount_currency :string default("BRL"), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# user_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_fiat_balances_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (user_id => users.id)
|
||||
#
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe(FiatBalance, type: :model) do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
||||
6
spec/policies/fiat_balance_policy_spec.rb
Normal file
6
spec/policies/fiat_balance_policy_spec.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe(FiatBalancePolicy, type: :policy) do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
||||
Reference in New Issue
Block a user