Merge pull request #53 from exstake/feature/get-cake-balance-from-bsc-wallet
get cake balance from bsc wallet
This commit is contained in:
1
.env
1
.env
@@ -4,6 +4,7 @@ MAILTRAP_ADDRESS=smtp.mailtrap.io
|
|||||||
MAILTRAP_DOMAIN=smtp.mailtrap.io
|
MAILTRAP_DOMAIN=smtp.mailtrap.io
|
||||||
MAILTRAP_PORT=2525
|
MAILTRAP_PORT=2525
|
||||||
MAILER_DEFAULT_URL_HOST=localhost:5000
|
MAILER_DEFAULT_URL_HOST=localhost:5000
|
||||||
|
TATUM_API_KEY=d8f66b09-d3ff-43ca-9b59-31b1b78d2660
|
||||||
# SLACK_WEBHOOK_URL=https://hooks.slack.com/services/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
|
# SLACK_WEBHOOK_URL=https://hooks.slack.com/services/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
|
||||||
|
|
||||||
# production
|
# production
|
||||||
|
|||||||
1
Gemfile
1
Gemfile
@@ -29,6 +29,7 @@ gem "enumerize"
|
|||||||
gem "graphql"
|
gem "graphql"
|
||||||
gem "pundit"
|
gem "pundit"
|
||||||
gem "ransack", "~> 2.4"
|
gem "ransack", "~> 2.4"
|
||||||
|
gem "httparty", "~> 0.19.0"
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem "dotenv-rails"
|
gem "dotenv-rails"
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ GEM
|
|||||||
graphql (1.12.14)
|
graphql (1.12.14)
|
||||||
graphql_playground-rails (2.1.0)
|
graphql_playground-rails (2.1.0)
|
||||||
rails (>= 5.1.0)
|
rails (>= 5.1.0)
|
||||||
|
httparty (0.19.0)
|
||||||
|
mime-types (~> 3.0)
|
||||||
|
multi_xml (>= 0.5.2)
|
||||||
i18n (1.8.10)
|
i18n (1.8.10)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
image_processing (1.12.1)
|
image_processing (1.12.1)
|
||||||
@@ -155,6 +158,9 @@ GEM
|
|||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
marcel (1.0.1)
|
marcel (1.0.1)
|
||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
|
mime-types (3.3.1)
|
||||||
|
mime-types-data (~> 3.2015)
|
||||||
|
mime-types-data (3.2021.0901)
|
||||||
mini_magick (4.11.0)
|
mini_magick (4.11.0)
|
||||||
mini_mime (1.1.0)
|
mini_mime (1.1.0)
|
||||||
mini_portile2 (2.6.1)
|
mini_portile2 (2.6.1)
|
||||||
@@ -171,6 +177,7 @@ GEM
|
|||||||
money (~> 6.13.2)
|
money (~> 6.13.2)
|
||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
msgpack (1.4.2)
|
msgpack (1.4.2)
|
||||||
|
multi_xml (0.6.0)
|
||||||
nio4r (2.5.8)
|
nio4r (2.5.8)
|
||||||
nokogiri (1.12.1)
|
nokogiri (1.12.1)
|
||||||
mini_portile2 (~> 2.6.1)
|
mini_portile2 (~> 2.6.1)
|
||||||
@@ -366,6 +373,7 @@ DEPENDENCIES
|
|||||||
foreman
|
foreman
|
||||||
graphql
|
graphql
|
||||||
graphql_playground-rails
|
graphql_playground-rails
|
||||||
|
httparty (~> 0.19.0)
|
||||||
image_processing (~> 1.12)
|
image_processing (~> 1.12)
|
||||||
listen (~> 3.3)
|
listen (~> 3.3)
|
||||||
money-rails
|
money-rails
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class FiatBalanceDashboard < Administrate::BaseDashboard
|
|||||||
# FORM_ATTRIBUTES
|
# FORM_ATTRIBUTES
|
||||||
# an array of attributes that will be displayed
|
# an array of attributes that will be displayed
|
||||||
# on the model's form (`new` and `edit`) pages.
|
# on the model's form (`new` and `edit`) pages.
|
||||||
FORM_ATTRIBUTES = [:user, :amount_cents].freeze
|
FORM_ATTRIBUTES = [:amount_cents].freeze
|
||||||
|
|
||||||
# COLLECTION_FILTERS
|
# COLLECTION_FILTERS
|
||||||
# a hash that defines filters that can be used while searching via the search
|
# a hash that defines filters that can be used while searching via the search
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ module Types
|
|||||||
field :email, String, null: false
|
field :email, String, null: false
|
||||||
field :first_name, String, null: false
|
field :first_name, String, null: false
|
||||||
field :last_name, String, null: false
|
field :last_name, String, null: false
|
||||||
field :wallet_address, String, null: true
|
|
||||||
field :fiat_balance, FiatBalanceType, null: false
|
field :fiat_balance, FiatBalanceType, null: false
|
||||||
|
field :wallet, WalletType, null: false
|
||||||
|
def wallet
|
||||||
|
Wallet.new(object)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
9
app/graphql/types/wallet_type.rb
Normal file
9
app/graphql/types/wallet_type.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class WalletType < Types::BaseObject
|
||||||
|
graphql_name "Wallet"
|
||||||
|
|
||||||
|
field :address, String, null: true
|
||||||
|
field :cake_balance, String, null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
7
app/javascript/__generated__/schema.graphql
generated
7
app/javascript/__generated__/schema.graphql
generated
@@ -553,5 +553,10 @@ type User {
|
|||||||
firstName: String!
|
firstName: String!
|
||||||
id: ID!
|
id: ID!
|
||||||
lastName: String!
|
lastName: String!
|
||||||
walletAddress: String
|
wallet: Wallet!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Wallet {
|
||||||
|
address: String
|
||||||
|
cakeBalance: String!
|
||||||
}
|
}
|
||||||
|
|||||||
23
app/javascript/src/__generated__/AppQuery.graphql.ts
generated
23
app/javascript/src/__generated__/AppQuery.graphql.ts
generated
@@ -27,7 +27,9 @@ query AppQuery {
|
|||||||
|
|
||||||
fragment UserProvider_user on User {
|
fragment UserProvider_user on User {
|
||||||
firstName
|
firstName
|
||||||
walletAddress
|
wallet {
|
||||||
|
address
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -82,8 +84,19 @@ const node: ConcreteRequest = {
|
|||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"concreteType": "Wallet",
|
||||||
"name": "walletAddress",
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "address",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -99,12 +112,12 @@ const node: ConcreteRequest = {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "56b4be302cf9b9ec226ad8145170961b",
|
"cacheID": "ae618245e5a3baf946034e1efe3682de",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "AppQuery",
|
"name": "AppQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query AppQuery {\n currentUser {\n ...UserProvider_user\n id\n }\n}\n\nfragment UserProvider_user on User {\n firstName\n walletAddress\n}\n"
|
"text": "query AppQuery {\n currentUser {\n ...UserProvider_user\n id\n }\n}\n\nfragment UserProvider_user on User {\n firstName\n wallet {\n address\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(node as any).hash = 'aac57a65620cf50754d54f3c8d6495cf';
|
(node as any).hash = 'aac57a65620cf50754d54f3c8d6495cf';
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ export const UserProvider: FC<Props> = ({ userRef, children }) => {
|
|||||||
graphql`
|
graphql`
|
||||||
fragment UserProvider_user on User {
|
fragment UserProvider_user on User {
|
||||||
firstName
|
firstName
|
||||||
walletAddress
|
wallet {
|
||||||
|
address
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
userRef
|
userRef
|
||||||
@@ -42,7 +44,7 @@ export const UserProvider: FC<Props> = ({ userRef, children }) => {
|
|||||||
const user = userData
|
const user = userData
|
||||||
? {
|
? {
|
||||||
firstName: userData.firstName,
|
firstName: userData.firstName,
|
||||||
walletAddress: userData.walletAddress,
|
walletAddress: userData.wallet.address,
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import { ReaderFragment } from "relay-runtime";
|
|||||||
import { FragmentRefs } from "relay-runtime";
|
import { FragmentRefs } from "relay-runtime";
|
||||||
export type UserProvider_user = {
|
export type UserProvider_user = {
|
||||||
readonly firstName: string;
|
readonly firstName: string;
|
||||||
readonly walletAddress: string | null;
|
readonly wallet: {
|
||||||
|
readonly address: string | null;
|
||||||
|
};
|
||||||
readonly " $refType": "UserProvider_user";
|
readonly " $refType": "UserProvider_user";
|
||||||
};
|
};
|
||||||
export type UserProvider_user$data = UserProvider_user;
|
export type UserProvider_user$data = UserProvider_user;
|
||||||
@@ -33,13 +35,24 @@ const node: ReaderFragment = {
|
|||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"concreteType": "Wallet",
|
||||||
"name": "walletAddress",
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "address",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "User",
|
"type": "User",
|
||||||
"abstractKey": null
|
"abstractKey": null
|
||||||
};
|
};
|
||||||
(node as any).hash = 'ef997d2646b4d39178c6f3318509a7cb';
|
(node as any).hash = '4f6b86f489ce0df288106cd92060b889';
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -1,14 +1,30 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useLazyLoadQuery } from "react-relay";
|
||||||
|
import { graphql } from "babel-plugin-relay/macro";
|
||||||
|
|
||||||
import { Pool } from "./Pool";
|
import { Pool } from "./Pool";
|
||||||
import { Spinner } from "../../components";
|
import { Spinner } from "../../components";
|
||||||
import { usePoolListing } from "./hooks";
|
import { usePoolListing } from "./hooks";
|
||||||
|
import type { PoolListingQuery } from "./__generated__/PoolListingQuery.graphql";
|
||||||
|
import { formatCake } from "../../utils/cake";
|
||||||
|
|
||||||
export const PoolListing = () => {
|
export const PoolListing = () => {
|
||||||
const { isLoading, validPools } = usePoolListing();
|
const { isLoading, validPools } = usePoolListing();
|
||||||
|
|
||||||
// TODO<wallet>: puxar valor da wallet
|
const { currentUser } = useLazyLoadQuery<PoolListingQuery>(
|
||||||
const balance = "0";
|
graphql`
|
||||||
|
query PoolListingQuery {
|
||||||
|
currentUser {
|
||||||
|
wallet {
|
||||||
|
cakeBalance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const balance = formatCake(currentUser?.wallet.cakeBalance);
|
||||||
|
|
||||||
if (isLoading && !validPools.length) {
|
if (isLoading && !validPools.length) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
112
app/javascript/src/pages/Home/__generated__/PoolListingQuery.graphql.ts
generated
Normal file
112
app/javascript/src/pages/Home/__generated__/PoolListingQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from "relay-runtime";
|
||||||
|
export type PoolListingQueryVariables = {};
|
||||||
|
export type PoolListingQueryResponse = {
|
||||||
|
readonly currentUser: {
|
||||||
|
readonly wallet: {
|
||||||
|
readonly cakeBalance: string;
|
||||||
|
};
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
export type PoolListingQuery = {
|
||||||
|
readonly response: PoolListingQueryResponse;
|
||||||
|
readonly variables: PoolListingQueryVariables;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
query PoolListingQuery {
|
||||||
|
currentUser {
|
||||||
|
wallet {
|
||||||
|
cakeBalance
|
||||||
|
}
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Wallet",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cakeBalance",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": [],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "PoolListingQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "User",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "currentUser",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": [],
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "PoolListingQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "User",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "currentUser",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "555226365d27590d8236ea1effdf9ddc",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "PoolListingQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query PoolListingQuery {\n currentUser {\n wallet {\n cakeBalance\n }\n id\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
(node as any).hash = 'afdc45802c0d92b114c2ebb5c3530ec2';
|
||||||
|
export default node;
|
||||||
@@ -9,6 +9,7 @@ import { commitCreateSellCryptoOrderMutation } from "./createSellCryptoOrder";
|
|||||||
import { commitCreateBuyCryptoOrderMutation } from "./createBuyCryptoOrder";
|
import { commitCreateBuyCryptoOrderMutation } from "./createBuyCryptoOrder";
|
||||||
import { Input, Button } from "../../../../components";
|
import { Input, Button } from "../../../../components";
|
||||||
import type { ExchangePanel_user$key } from "./__generated__/ExchangePanel_user.graphql";
|
import type { ExchangePanel_user$key } from "./__generated__/ExchangePanel_user.graphql";
|
||||||
|
import { formatCake } from "../../../../utils/cake";
|
||||||
|
|
||||||
const tabBaseStyles =
|
const tabBaseStyles =
|
||||||
"w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500";
|
"w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500";
|
||||||
@@ -32,14 +33,15 @@ export const ExchangePanel: FC<Props> = ({ userRef }) => {
|
|||||||
fiatBalance {
|
fiatBalance {
|
||||||
amountCents
|
amountCents
|
||||||
}
|
}
|
||||||
|
wallet {
|
||||||
|
cakeBalance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
userRef
|
userRef
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO<wallet>: puxar valor da wallet
|
const balanceAmount = formatCake(user?.wallet.cakeBalance);
|
||||||
const balanceAmount = 0;
|
|
||||||
|
|
||||||
const fiatBalanceAmount = user?.fiatBalance.amountCents ?? 0;
|
const fiatBalanceAmount = user?.fiatBalance.amountCents ?? 0;
|
||||||
|
|
||||||
const avaliableCrypto = new BigNumber(balanceAmount);
|
const avaliableCrypto = new BigNumber(balanceAmount);
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ export type ExchangePanel_user = {
|
|||||||
readonly fiatBalance: {
|
readonly fiatBalance: {
|
||||||
readonly amountCents: number;
|
readonly amountCents: number;
|
||||||
};
|
};
|
||||||
|
readonly wallet: {
|
||||||
|
readonly cakeBalance: string;
|
||||||
|
};
|
||||||
readonly " $refType": "ExchangePanel_user";
|
readonly " $refType": "ExchangePanel_user";
|
||||||
};
|
};
|
||||||
export type ExchangePanel_user$data = ExchangePanel_user;
|
export type ExchangePanel_user$data = ExchangePanel_user;
|
||||||
@@ -41,10 +44,28 @@ const node: ReaderFragment = {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Wallet",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cakeBalance",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "User",
|
"type": "User",
|
||||||
"abstractKey": null
|
"abstractKey": null
|
||||||
};
|
};
|
||||||
(node as any).hash = '2058ddb20a60f148a524083fa0a680ea';
|
(node as any).hash = '88cc0dedfa3a3b9bb73d6b4745e0cf5a';
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ fragment ExchangePanel_user on User {
|
|||||||
amountCents
|
amountCents
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
wallet {
|
||||||
|
cakeBalance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -192,6 +195,24 @@ return {
|
|||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Wallet",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cakeBalance",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
(v0/*: any*/)
|
(v0/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -301,12 +322,12 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "30aa6f9d81cfe033aee64b8577d15936",
|
"cacheID": "2168c066ea4bb43d5ab066a00a35a33b",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "ExchangeQuery",
|
"name": "ExchangeQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query ExchangeQuery {\n currentUser {\n ...ExchangePanel_user\n id\n }\n buyCryptoOrders {\n ...ExchangeHistory_buyCryptoOrders\n }\n sellCryptoOrders {\n ...ExchangeHistory_sellCryptoOrders\n }\n}\n\nfragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmount\n __typename\n }\n }\n}\n\nfragment ExchangeHistory_sellCryptoOrders on SellCryptoOrderConnection {\n edges {\n node {\n id\n status\n paidAmount\n receivedAmountCents\n createdAt\n __typename\n }\n }\n}\n\nfragment ExchangePanel_user on User {\n fiatBalance {\n amountCents\n id\n }\n}\n"
|
"text": "query ExchangeQuery {\n currentUser {\n ...ExchangePanel_user\n id\n }\n buyCryptoOrders {\n ...ExchangeHistory_buyCryptoOrders\n }\n sellCryptoOrders {\n ...ExchangeHistory_sellCryptoOrders\n }\n}\n\nfragment ExchangeHistory_buyCryptoOrders on BuyCryptoOrderConnection {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmount\n __typename\n }\n }\n}\n\nfragment ExchangeHistory_sellCryptoOrders on SellCryptoOrderConnection {\n edges {\n node {\n id\n status\n paidAmount\n receivedAmountCents\n createdAt\n __typename\n }\n }\n}\n\nfragment ExchangePanel_user on User {\n fiatBalance {\n amountCents\n id\n }\n wallet {\n cakeBalance\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
|
import { graphql } from "babel-plugin-relay/macro";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useFragment } from "react-relay";
|
||||||
|
|
||||||
import { Table, TableRow } from "../../components";
|
import { Table, TableRow } from "../../components";
|
||||||
|
import { formatCake } from "../../utils/cake";
|
||||||
import { getCurrencyLogo } from "../../utils/getCurrencyLogo";
|
import { getCurrencyLogo } from "../../utils/getCurrencyLogo";
|
||||||
|
import type { Balance_wallet$key } from "./__generated__/Balance_wallet.graphql";
|
||||||
|
|
||||||
export const Balance: FC = () => {
|
type Props = {
|
||||||
const node = {
|
userRef: Balance_wallet$key;
|
||||||
amount: "PUXAR VALOR DA CARTEIRA",
|
};
|
||||||
};
|
|
||||||
|
export const Balance: FC<Props> = ({ userRef }) => {
|
||||||
|
const { wallet } = useFragment<Balance_wallet$key>(
|
||||||
|
graphql`
|
||||||
|
fragment Balance_wallet on User {
|
||||||
|
wallet {
|
||||||
|
cakeBalance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
userRef
|
||||||
|
);
|
||||||
|
|
||||||
|
const cakeBalance = formatCake(wallet.cakeBalance);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto">
|
<div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto">
|
||||||
@@ -27,7 +44,7 @@ export const Balance: FC = () => {
|
|||||||
<p className="text-gray-900 whitespace-no-wrap">CAKE</p>
|
<p className="text-gray-900 whitespace-no-wrap">CAKE</p>
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
node.amount,
|
cakeBalance,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -6,22 +6,24 @@ import { useFragment } from "react-relay";
|
|||||||
import type { FiatBalance_fiatBalance$key } from "./__generated__/FiatBalance_fiatBalance.graphql";
|
import type { FiatBalance_fiatBalance$key } from "./__generated__/FiatBalance_fiatBalance.graphql";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
fiatBalancesRef: FiatBalance_fiatBalance$key;
|
userRef: FiatBalance_fiatBalance$key;
|
||||||
};
|
};
|
||||||
export const FiatBalance: FC<Props> = ({ fiatBalancesRef }) => {
|
export const FiatBalance: FC<Props> = ({ userRef }) => {
|
||||||
const userFiatBalance = useFragment<FiatBalance_fiatBalance$key>(
|
const { fiatBalance } = useFragment<FiatBalance_fiatBalance$key>(
|
||||||
graphql`
|
graphql`
|
||||||
fragment FiatBalance_fiatBalance on FiatBalance {
|
fragment FiatBalance_fiatBalance on User {
|
||||||
amountCents
|
fiatBalance {
|
||||||
amountCurrency
|
amountCents
|
||||||
|
amountCurrency
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
fiatBalancesRef
|
userRef
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!userFiatBalance) return null;
|
if (!fiatBalance) return null;
|
||||||
|
|
||||||
const { amountCents, amountCurrency } = userFiatBalance;
|
const { amountCents, amountCurrency } = fiatBalance;
|
||||||
|
|
||||||
const amount = (amountCents ? amountCents / 100 : 0).toFixed(2);
|
const amount = (amountCents ? amountCents / 100 : 0).toFixed(2);
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,8 @@ export const Wallet: FC = () => {
|
|||||||
graphql`
|
graphql`
|
||||||
query WalletQuery {
|
query WalletQuery {
|
||||||
currentUser {
|
currentUser {
|
||||||
fiatBalance {
|
...FiatBalance_fiatBalance
|
||||||
...FiatBalance_fiatBalance
|
...Balance_wallet
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@@ -30,8 +29,8 @@ export const Wallet: FC = () => {
|
|||||||
<div className="flex flex-col h-full w-full overflow-x-hidden">
|
<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="container mx-auto px-4 sm:px-8 max-w-3xl">
|
||||||
<div className="py-8">
|
<div className="py-8">
|
||||||
<FiatBalance fiatBalancesRef={currentUser.fiatBalance} />
|
<FiatBalance userRef={currentUser} />
|
||||||
<Balance />
|
<Balance userRef={currentUser} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
50
app/javascript/src/pages/Wallet/__generated__/Balance_wallet.graphql.ts
generated
Normal file
50
app/javascript/src/pages/Wallet/__generated__/Balance_wallet.graphql.ts
generated
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ReaderFragment } from "relay-runtime";
|
||||||
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type Balance_wallet = {
|
||||||
|
readonly wallet: {
|
||||||
|
readonly cakeBalance: string;
|
||||||
|
};
|
||||||
|
readonly " $refType": "Balance_wallet";
|
||||||
|
};
|
||||||
|
export type Balance_wallet$data = Balance_wallet;
|
||||||
|
export type Balance_wallet$key = {
|
||||||
|
readonly " $data"?: Balance_wallet$data;
|
||||||
|
readonly " $fragmentRefs": FragmentRefs<"Balance_wallet">;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const node: ReaderFragment = {
|
||||||
|
"argumentDefinitions": [],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "Balance_wallet",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Wallet",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cakeBalance",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "User",
|
||||||
|
"abstractKey": null
|
||||||
|
};
|
||||||
|
(node as any).hash = '27ddb42954aa66b033735eeea5746516';
|
||||||
|
export default node;
|
||||||
@@ -5,8 +5,10 @@
|
|||||||
import { ReaderFragment } from "relay-runtime";
|
import { ReaderFragment } from "relay-runtime";
|
||||||
import { FragmentRefs } from "relay-runtime";
|
import { FragmentRefs } from "relay-runtime";
|
||||||
export type FiatBalance_fiatBalance = {
|
export type FiatBalance_fiatBalance = {
|
||||||
readonly amountCents: number;
|
readonly fiatBalance: {
|
||||||
readonly amountCurrency: string;
|
readonly amountCents: number;
|
||||||
|
readonly amountCurrency: string;
|
||||||
|
};
|
||||||
readonly " $refType": "FiatBalance_fiatBalance";
|
readonly " $refType": "FiatBalance_fiatBalance";
|
||||||
};
|
};
|
||||||
export type FiatBalance_fiatBalance$data = FiatBalance_fiatBalance;
|
export type FiatBalance_fiatBalance$data = FiatBalance_fiatBalance;
|
||||||
@@ -26,20 +28,31 @@ const node: ReaderFragment = {
|
|||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"concreteType": "FiatBalance",
|
||||||
"name": "amountCents",
|
"kind": "LinkedField",
|
||||||
"storageKey": null
|
"name": "fiatBalance",
|
||||||
},
|
"plural": false,
|
||||||
{
|
"selections": [
|
||||||
"alias": null,
|
{
|
||||||
"args": null,
|
"alias": null,
|
||||||
"kind": "ScalarField",
|
"args": null,
|
||||||
"name": "amountCurrency",
|
"kind": "ScalarField",
|
||||||
|
"name": "amountCents",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "amountCurrency",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "FiatBalance",
|
"type": "User",
|
||||||
"abstractKey": null
|
"abstractKey": null
|
||||||
};
|
};
|
||||||
(node as any).hash = 'dc28e4dca104c7d25465a30412661af2';
|
(node as any).hash = '4371bbd59e9a50e7f32aa65bf982c19e';
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import { FragmentRefs } from "relay-runtime";
|
|||||||
export type WalletQueryVariables = {};
|
export type WalletQueryVariables = {};
|
||||||
export type WalletQueryResponse = {
|
export type WalletQueryResponse = {
|
||||||
readonly currentUser: {
|
readonly currentUser: {
|
||||||
readonly fiatBalance: {
|
readonly " $fragmentRefs": FragmentRefs<"FiatBalance_fiatBalance" | "Balance_wallet">;
|
||||||
readonly " $fragmentRefs": FragmentRefs<"FiatBalance_fiatBalance">;
|
|
||||||
};
|
|
||||||
} | null;
|
} | null;
|
||||||
};
|
};
|
||||||
export type WalletQuery = {
|
export type WalletQuery = {
|
||||||
@@ -22,17 +20,24 @@ export type WalletQuery = {
|
|||||||
/*
|
/*
|
||||||
query WalletQuery {
|
query WalletQuery {
|
||||||
currentUser {
|
currentUser {
|
||||||
fiatBalance {
|
...FiatBalance_fiatBalance
|
||||||
...FiatBalance_fiatBalance
|
...Balance_wallet
|
||||||
id
|
|
||||||
}
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment FiatBalance_fiatBalance on FiatBalance {
|
fragment Balance_wallet on User {
|
||||||
amountCents
|
wallet {
|
||||||
amountCurrency
|
cakeBalance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment FiatBalance_fiatBalance on User {
|
||||||
|
fiatBalance {
|
||||||
|
amountCents
|
||||||
|
amountCurrency
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -60,20 +65,14 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
"args": null,
|
||||||
"concreteType": "FiatBalance",
|
"kind": "FragmentSpread",
|
||||||
"kind": "LinkedField",
|
"name": "FiatBalance_fiatBalance"
|
||||||
"name": "fiatBalance",
|
},
|
||||||
"plural": false,
|
{
|
||||||
"selections": [
|
"args": null,
|
||||||
{
|
"kind": "FragmentSpread",
|
||||||
"args": null,
|
"name": "Balance_wallet"
|
||||||
"kind": "FragmentSpread",
|
|
||||||
"name": "FiatBalance_fiatBalance"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"storageKey": null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -122,6 +121,24 @@ return {
|
|||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Wallet",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "wallet",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cakeBalance",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
(v0/*: any*/)
|
(v0/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -129,14 +146,14 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "4397ad78f82d23c0a186b71bea7c3898",
|
"cacheID": "4631f43e84d22d8fdfa82706d907f478",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "WalletQuery",
|
"name": "WalletQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query WalletQuery {\n currentUser {\n fiatBalance {\n ...FiatBalance_fiatBalance\n id\n }\n id\n }\n}\n\nfragment FiatBalance_fiatBalance on FiatBalance {\n amountCents\n amountCurrency\n}\n"
|
"text": "query WalletQuery {\n currentUser {\n ...FiatBalance_fiatBalance\n ...Balance_wallet\n id\n }\n}\n\nfragment Balance_wallet on User {\n wallet {\n cakeBalance\n }\n}\n\nfragment FiatBalance_fiatBalance on User {\n fiatBalance {\n amountCents\n amountCurrency\n id\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
(node as any).hash = '83fd609428103b13e79c14d20fefaabe';
|
(node as any).hash = 'a91fc17a25b5a68672b3016813de17bc';
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
2
app/javascript/src/utils/cake.ts
Normal file
2
app/javascript/src/utils/cake.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const formatCake = (value?: string) =>
|
||||||
|
parseFloat(value ?? "0").toFixed(5);
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class ApplicationRecord < ActiveRecord::Base
|
class ApplicationRecord < ActiveRecord::Base
|
||||||
self.abstract_class = true
|
self.abstract_class = true
|
||||||
|
|
||||||
|
default_scope { order(created_at: :desc) }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ module Processable
|
|||||||
|
|
||||||
included do
|
included do
|
||||||
enumerize :status, in: [:processing, :completed, :canceled], default: :processing
|
enumerize :status, in: [:processing, :completed, :canceled], default: :processing
|
||||||
|
|
||||||
|
status.values.each do |value|
|
||||||
|
scope value, -> { where(status: value) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def processing?
|
def processing?
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ class StakeOrder < ApplicationRecord
|
|||||||
super & ["pool_name", "amount"]
|
super & ["pool_name", "amount"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope :add, -> { where("amount > 0") }
|
||||||
|
scope :remove, -> { where("amount < 0") }
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def notification_message
|
def notification_message
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
has_many :documents, class_name: "UserDocument", dependent: :destroy
|
has_many :documents, class_name: "UserDocument", dependent: :destroy
|
||||||
has_many :stake_orders, dependent: :restrict_with_error
|
has_many :stake_orders, dependent: :restrict_with_error
|
||||||
|
has_many :sell_crypto_orders, dependent: :restrict_with_error
|
||||||
has_one :fiat_balance, dependent: :restrict_with_error
|
has_one :fiat_balance, dependent: :restrict_with_error
|
||||||
|
|
||||||
validates :first_name, :last_name, :email, presence: true
|
validates :first_name, :last_name, :email, presence: true
|
||||||
|
|||||||
21
app/services/bsc_client.rb
Normal file
21
app/services/bsc_client.rb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class BscClient
|
||||||
|
include HTTParty
|
||||||
|
|
||||||
|
base_uri "api-eu1.tatum.io/v3"
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@headers = {
|
||||||
|
"x-api-key": ENV["TATUM_API_KEY"],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def token_balance(contract:, digits:, wallet_address:)
|
||||||
|
result = self.class.get(
|
||||||
|
"https://api-eu1.tatum.io/v3/blockchain/token/balance/BSC/#{contract}/#{wallet_address}",
|
||||||
|
headers: @headers
|
||||||
|
).parsed_response["balance"]
|
||||||
|
|
||||||
|
(result.to_f / (10**digits)).round(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
34
app/value_objects/wallet.rb
Normal file
34
app/value_objects/wallet.rb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class Wallet
|
||||||
|
attr_reader :user, :address, :cake_balance
|
||||||
|
|
||||||
|
def initialize(user)
|
||||||
|
@user = user
|
||||||
|
@address = user.wallet_address
|
||||||
|
@cake_balance = total_cake
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def total_cake
|
||||||
|
return 0 if address.blank?
|
||||||
|
|
||||||
|
BscClient.new.token_balance(
|
||||||
|
contract: "0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82",
|
||||||
|
digits: 18,
|
||||||
|
wallet_address: address,
|
||||||
|
) - total_cake_debit
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_cake_debit
|
||||||
|
total_cake_stake_debit + total_cake_sell_debit
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_cake_stake_debit
|
||||||
|
user.stake_orders.processing.add.sum(&:amount).to_f
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_cake_sell_debit
|
||||||
|
user.sell_crypto_orders.processing.sum(&:paid_amount).to_f
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user