Merge pull request #37 from exstake/feature/unstake-request
Feature/unstake request
This commit is contained in:
1
Gemfile
1
Gemfile
@@ -28,6 +28,7 @@ gem "money-rails"
|
|||||||
gem "enumerize"
|
gem "enumerize"
|
||||||
gem "graphql"
|
gem "graphql"
|
||||||
gem "pundit"
|
gem "pundit"
|
||||||
|
gem "ransack", "~> 2.4"
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem "dotenv-rails"
|
gem "dotenv-rails"
|
||||||
|
|||||||
@@ -235,6 +235,10 @@ GEM
|
|||||||
thor (~> 1.0)
|
thor (~> 1.0)
|
||||||
rainbow (3.0.0)
|
rainbow (3.0.0)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
|
ransack (2.4.2)
|
||||||
|
activerecord (>= 5.2.4)
|
||||||
|
activesupport (>= 5.2.4)
|
||||||
|
i18n
|
||||||
rb-fsevent (0.11.0)
|
rb-fsevent (0.11.0)
|
||||||
rb-inotify (0.10.1)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
@@ -373,6 +377,7 @@ DEPENDENCIES
|
|||||||
rails (~> 6.1.4)
|
rails (~> 6.1.4)
|
||||||
rails-erd
|
rails-erd
|
||||||
rails-i18n (~> 6.0)
|
rails-i18n (~> 6.0)
|
||||||
|
ransack (~> 2.4)
|
||||||
rspec-graphql_matchers (~> 1.3)
|
rspec-graphql_matchers (~> 1.3)
|
||||||
rspec-rails
|
rspec-rails
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
module Inputs
|
module Inputs
|
||||||
class CreateStakeOrderAttributesInput < Types::BaseInputObject
|
class CreateStakeOrderAttributesInput < Types::BaseInputObject
|
||||||
argument :currency_id, ID, required: true
|
|
||||||
argument :pool_name, String, required: true
|
argument :pool_name, String, required: true
|
||||||
argument :amount, String, "Amount to be paid", required: true
|
argument :amount, String, "Amount to be paid", required: true
|
||||||
end
|
end
|
||||||
|
|||||||
9
app/graphql/inputs/predicate_input.rb
Normal file
9
app/graphql/inputs/predicate_input.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Inputs
|
||||||
|
class PredicateInput < Types::BaseInputObject
|
||||||
|
# https://github.com/activerecord-hackery/ransack#search-matchers
|
||||||
|
# add others if necessary
|
||||||
|
argument :eq, String, "Equal", required: false
|
||||||
|
argument :lt, Float, "Less than", required: false
|
||||||
|
end
|
||||||
|
end
|
||||||
10
app/graphql/inputs/stake_order_filter_input.rb
Normal file
10
app/graphql/inputs/stake_order_filter_input.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Inputs
|
||||||
|
class StakeOrderFilterInput < Types::BaseInputObject
|
||||||
|
StakeOrder.ransackable_attributes.each do |attr|
|
||||||
|
argument attr, PredicateInput, required: false
|
||||||
|
end
|
||||||
|
|
||||||
|
argument :status, [Types::ProcessStatusEnum], required: false
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -6,7 +6,7 @@ module Mutations
|
|||||||
argument :order, Inputs::CreateStakeOrderAttributesInput, required: true
|
argument :order, Inputs::CreateStakeOrderAttributesInput, required: true
|
||||||
|
|
||||||
def resolve(order:)
|
def resolve(order:)
|
||||||
currency_id = decode_id(order[:currency_id])
|
currency_id = Currency.find_by!(name: "CAKE").id
|
||||||
amount = BigDecimal(order[:amount])
|
amount = BigDecimal(order[:amount])
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
|||||||
29
app/graphql/mutations/create_stake_remove_order.rb
Normal file
29
app/graphql/mutations/create_stake_remove_order.rb
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Mutations
|
||||||
|
class CreateStakeRemoveOrder < BaseMutation
|
||||||
|
field :order, Types::StakeOrderType, null: true
|
||||||
|
|
||||||
|
argument :order, Inputs::CreateStakeOrderAttributesInput, required: true
|
||||||
|
|
||||||
|
def resolve(order:)
|
||||||
|
currency_id = Currency.find_by!(name: "CAKE").id
|
||||||
|
amount = -BigDecimal(order[:amount])
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
record = StakeOrder.find_or_initialize_by(
|
||||||
|
pool_name: order[:pool_name],
|
||||||
|
user_id: current_user.id,
|
||||||
|
currency_id: currency_id,
|
||||||
|
status: :processing
|
||||||
|
)
|
||||||
|
|
||||||
|
record.amount += amount
|
||||||
|
record.save!
|
||||||
|
|
||||||
|
{ order: record }
|
||||||
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
|
{ errors: Resolvers::ModelErrors.from_active_record_model(e.record) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
21
app/graphql/ransack_support.rb
Normal file
21
app/graphql/ransack_support.rb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module RansackSupport
|
||||||
|
def ransack(base, filter)
|
||||||
|
base.ransack(build_ransack_query(base, filter)).result
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_ransack_query(base, filter)
|
||||||
|
filter = filter.to_h
|
||||||
|
mapped_filter = {}
|
||||||
|
|
||||||
|
filter.each do |parent_key, parent_value|
|
||||||
|
next unless base.ransackable_attributes.include?(parent_key.to_s)
|
||||||
|
|
||||||
|
parent_value.each do |children_key, children_value|
|
||||||
|
mapped_filter["#{parent_key}_#{children_key}".to_sym] = children_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mapped_filter
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
module Types
|
module Types
|
||||||
class MutationType < Types::BaseObject
|
class MutationType < Types::BaseObject
|
||||||
|
field :create_stake_remove_order, mutation: Mutations::CreateStakeRemoveOrder
|
||||||
field :create_stake_order, mutation: Mutations::CreateStakeOrder
|
field :create_stake_order, mutation: Mutations::CreateStakeOrder
|
||||||
field :create_sell_crypto_order, mutation: Mutations::CreateSellCryptoOrder
|
field :create_sell_crypto_order, mutation: Mutations::CreateSellCryptoOrder
|
||||||
field :create_buy_crypto_order, mutation: Mutations::CreateBuyCryptoOrder
|
field :create_buy_crypto_order, mutation: Mutations::CreateBuyCryptoOrder
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module Types
|
|||||||
class QueryType < Types::BaseObject
|
class QueryType < Types::BaseObject
|
||||||
include GraphQL::Types::Relay::HasNodeField
|
include GraphQL::Types::Relay::HasNodeField
|
||||||
include GraphQL::Types::Relay::HasNodesField
|
include GraphQL::Types::Relay::HasNodesField
|
||||||
|
include RansackSupport
|
||||||
|
|
||||||
field :current_user, UserType, null: true
|
field :current_user, UserType, null: true
|
||||||
def current_user
|
def current_user
|
||||||
@@ -29,9 +30,16 @@ module Types
|
|||||||
Pundit.policy_scope(current_user, BuyCryptoOrder)
|
Pundit.policy_scope(current_user, BuyCryptoOrder)
|
||||||
end
|
end
|
||||||
|
|
||||||
field :stake_orders, StakeOrderType.connection_type, null: false
|
field :stake_orders, StakeOrderType.connection_type, null: false do
|
||||||
def stake_orders
|
argument :filter, Inputs::StakeOrderFilterInput, required: false
|
||||||
Pundit.policy_scope(current_user, StakeOrder)
|
end
|
||||||
|
|
||||||
|
def stake_orders(filter: nil)
|
||||||
|
scope = Pundit.policy_scope(current_user, StakeOrder)
|
||||||
|
|
||||||
|
scope = scope.where(status: filter.status) if filter&.status
|
||||||
|
|
||||||
|
ransack(scope, filter)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
53
app/javascript/__generated__/schema.graphql
generated
53
app/javascript/__generated__/schema.graphql
generated
@@ -149,7 +149,6 @@ input CreateStakeOrderAttributesInput {
|
|||||||
Amount to be paid
|
Amount to be paid
|
||||||
"""
|
"""
|
||||||
amount: String!
|
amount: String!
|
||||||
currencyId: ID!
|
|
||||||
poolName: String!
|
poolName: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +179,33 @@ type CreateStakeOrderPayload {
|
|||||||
order: StakeOrder
|
order: StakeOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of CreateStakeRemoveOrder
|
||||||
|
"""
|
||||||
|
input CreateStakeRemoveOrderInput {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
order: CreateStakeOrderAttributesInput!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of CreateStakeRemoveOrder
|
||||||
|
"""
|
||||||
|
type CreateStakeRemoveOrderPayload {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Errors encountered during execution of the mutation.
|
||||||
|
"""
|
||||||
|
errors: [RecordInvalid!]
|
||||||
|
order: StakeOrder
|
||||||
|
}
|
||||||
|
|
||||||
type Currency implements Node {
|
type Currency implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
name: String!
|
name: String!
|
||||||
@@ -245,6 +271,12 @@ type Mutation {
|
|||||||
"""
|
"""
|
||||||
input: CreateStakeOrderInput!
|
input: CreateStakeOrderInput!
|
||||||
): CreateStakeOrderPayload
|
): CreateStakeOrderPayload
|
||||||
|
createStakeRemoveOrder(
|
||||||
|
"""
|
||||||
|
Parameters for CreateStakeRemoveOrder
|
||||||
|
"""
|
||||||
|
input: CreateStakeRemoveOrderInput!
|
||||||
|
): CreateStakeRemoveOrderPayload
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -282,6 +314,18 @@ type PageInfo {
|
|||||||
startCursor: String
|
startCursor: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input PredicateInput {
|
||||||
|
"""
|
||||||
|
Equal
|
||||||
|
"""
|
||||||
|
eq: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Less than
|
||||||
|
"""
|
||||||
|
lt: Float
|
||||||
|
}
|
||||||
|
|
||||||
enum ProcessStatus {
|
enum ProcessStatus {
|
||||||
CANCELED
|
CANCELED
|
||||||
COMPLETED
|
COMPLETED
|
||||||
@@ -404,6 +448,7 @@ type Query {
|
|||||||
Returns the elements in the list that come before the specified cursor.
|
Returns the elements in the list that come before the specified cursor.
|
||||||
"""
|
"""
|
||||||
before: String
|
before: String
|
||||||
|
filter: StakeOrderFilterInput
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Returns the first _n_ elements from the list.
|
Returns the first _n_ elements from the list.
|
||||||
@@ -503,6 +548,12 @@ type StakeOrderEdge {
|
|||||||
node: StakeOrder!
|
node: StakeOrder!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input StakeOrderFilterInput {
|
||||||
|
amount: PredicateInput
|
||||||
|
poolName: PredicateInput
|
||||||
|
status: [ProcessStatus!]
|
||||||
|
}
|
||||||
|
|
||||||
type User {
|
type User {
|
||||||
email: String!
|
email: String!
|
||||||
firstName: String!
|
firstName: String!
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import cx from "classnames";
|
|
||||||
|
|
||||||
import { useCurrentUser } from "../../contexts/UserProvider";
|
import { useCurrentUser } from "../../contexts/UserProvider";
|
||||||
import type { Vault, YieldwatchResponse } from "../../types/yieldwatch";
|
import type {
|
||||||
|
Vault as VaultType,
|
||||||
|
YieldwatchResponse,
|
||||||
|
} from "../../types/yieldwatch";
|
||||||
|
import { Vault } from "./Vault";
|
||||||
|
|
||||||
const exampleVault: Partial<Vault> = {
|
const exampleVault: Partial<VaultType> = {
|
||||||
chainId: 1,
|
chainId: 1,
|
||||||
name: "Cake-Cake Staking",
|
name: "Cake-Cake Staking",
|
||||||
depositedTokens: 0,
|
depositedTokens: 0,
|
||||||
@@ -28,57 +31,7 @@ export const Dashbaord: FC = () => {
|
|||||||
<div className="grid place-items-center w-full h-5 mt-32">
|
<div className="grid place-items-center w-full h-5 mt-32">
|
||||||
<div className="max-w-3xl grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div className="max-w-3xl grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{vaults?.map((vault) => (
|
{vaults?.map((vault) => (
|
||||||
<div
|
<Vault key={vault.name} isLoading={isLoading} vault={vault} />
|
||||||
key={vault.chainId}
|
|
||||||
className="shadow-lg px-4 py-6 w-full bg-white dark:bg-gray-800 rounded-lg"
|
|
||||||
>
|
|
||||||
<p className="text-sm w-max text-gray-700 dark:text-white font-semibold border-b border-gray-200">
|
|
||||||
{vault.name}
|
|
||||||
</p>
|
|
||||||
<div className="flex items-end space-x-2 my-6">
|
|
||||||
<p
|
|
||||||
className={cx(
|
|
||||||
"text-5xl text-black dark:text-white font-bold",
|
|
||||||
isLoading
|
|
||||||
? "w-36 h-10 inline-block animate-pulse bg-gray-300 rounded"
|
|
||||||
: ""
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{!isLoading &&
|
|
||||||
(
|
|
||||||
(vault.depositedTokens ?? 0) + (vault.totalRewards ?? 0)
|
|
||||||
).toFixed(4)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="dark:text-white">
|
|
||||||
<div className="flex items-center pb-2 mb-2 text-sm space-x-12 md:space-x-24 justify-between border-b border-gray-200">
|
|
||||||
<p>Depositado</p>
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
"flex items-end text-xs",
|
|
||||||
isLoading
|
|
||||||
? "w-10 h-4 inline-block animate-pulse bg-gray-300 rounded"
|
|
||||||
: ""
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{!isLoading && vault.depositedTokens?.toFixed(4)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center text-sm space-x-12 md:space-x-24 justify-between">
|
|
||||||
<p>Ganho</p>
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
"flex items-end text-xs",
|
|
||||||
isLoading
|
|
||||||
? "w-10 h-4 inline-block animate-pulse bg-gray-300 rounded"
|
|
||||||
: ""
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{!isLoading && vault.totalRewards?.toFixed(4)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import BigNumber from "bignumber.js";
|
||||||
|
import type { ChangeEvent, FC } from "react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import cx from "classnames";
|
||||||
|
import { useRelayEnvironment } from "react-relay";
|
||||||
|
|
||||||
|
import { Modal } from "../../../../components";
|
||||||
|
import { commitCreateStakeRemoveOrderMutation } from "./commitCreateStakeRemoveOrder";
|
||||||
|
|
||||||
|
const inputBaseStyles =
|
||||||
|
"rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3";
|
||||||
|
|
||||||
|
type RemoveStakeModal = {
|
||||||
|
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
isOpen: boolean;
|
||||||
|
stakedCake: string;
|
||||||
|
poolName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RemoveStakeModal: FC<RemoveStakeModal> = ({
|
||||||
|
setIsOpen,
|
||||||
|
isOpen,
|
||||||
|
stakedCake,
|
||||||
|
poolName = "",
|
||||||
|
}) => {
|
||||||
|
const enviroment = useRelayEnvironment();
|
||||||
|
const [amountInput, setAmountInput] = useState<string>("0");
|
||||||
|
const avaliableCake = BigNumber.sum(stakedCake);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
commitCreateStakeRemoveOrderMutation(enviroment, {
|
||||||
|
poolName,
|
||||||
|
amount: amountInput,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInvestInput = ({
|
||||||
|
currentTarget: { value },
|
||||||
|
}: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newInvestAmount = new BigNumber(value);
|
||||||
|
|
||||||
|
if (
|
||||||
|
newInvestAmount.isLessThanOrEqualTo(avaliableCake) &&
|
||||||
|
newInvestAmount.isGreaterThanOrEqualTo(0)
|
||||||
|
) {
|
||||||
|
setAmountInput(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMaxButton = () => {
|
||||||
|
setAmountInput(stakedCake);
|
||||||
|
};
|
||||||
|
|
||||||
|
const amountToUnstake = new BigNumber(amountInput);
|
||||||
|
|
||||||
|
const stakeAvaliable =
|
||||||
|
amountToUnstake.isGreaterThan(0) &&
|
||||||
|
amountToUnstake.isLessThanOrEqualTo(avaliableCake);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
setIsOpen={handleClose}
|
||||||
|
title={`Remover investido em ${poolName}`}
|
||||||
|
>
|
||||||
|
<span className="mb-2">CAKE disponível: {stakedCake}</span>
|
||||||
|
<form onSubmit={onSubmit} className="bg-white py-2">
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<input
|
||||||
|
className={cx(inputBaseStyles)}
|
||||||
|
type="number"
|
||||||
|
value={amountInput}
|
||||||
|
onChange={handleInvestInput}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={amountInput === stakedCake}
|
||||||
|
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500"
|
||||||
|
onClick={handleMaxButton}
|
||||||
|
>
|
||||||
|
Max
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{avaliableCake.isEqualTo(0) && (
|
||||||
|
<span className="text-red-500 mb-1">Você não possuí saldo.</span>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className="cursor-pointer py-2 px-4 disabled:opacity-50 disabled:cursor-default bg-red-600 hover:bg-red-700 focus:ring-red-500 focus:ring-offset-red-200 text-white w-full transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg"
|
||||||
|
disabled={!stakeAvaliable}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Remover Stake
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from "relay-runtime";
|
||||||
|
export type commitCreateStakeRemoveOrderMutationVariables = {
|
||||||
|
poolName: string;
|
||||||
|
amount: string;
|
||||||
|
};
|
||||||
|
export type commitCreateStakeRemoveOrderMutationResponse = {
|
||||||
|
readonly createStakeRemoveOrder: {
|
||||||
|
readonly order: {
|
||||||
|
readonly id: string;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
export type commitCreateStakeRemoveOrderMutation = {
|
||||||
|
readonly response: commitCreateStakeRemoveOrderMutationResponse;
|
||||||
|
readonly variables: commitCreateStakeRemoveOrderMutationVariables;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
mutation commitCreateStakeRemoveOrderMutation(
|
||||||
|
$poolName: String!
|
||||||
|
$amount: String!
|
||||||
|
) {
|
||||||
|
createStakeRemoveOrder(input: {order: {poolName: $poolName, amount: $amount}}) {
|
||||||
|
order {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "amount"
|
||||||
|
},
|
||||||
|
v1 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "poolName"
|
||||||
|
},
|
||||||
|
v2 = [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "amount",
|
||||||
|
"variableName": "amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "poolName",
|
||||||
|
"variableName": "poolName"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "order"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "CreateStakeRemoveOrderPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "createStakeRemoveOrder",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "StakeOrder",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "order",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
(v1/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "commitCreateStakeRemoveOrderMutation",
|
||||||
|
"selections": (v2/*: any*/),
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "commitCreateStakeRemoveOrderMutation",
|
||||||
|
"selections": (v2/*: any*/)
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "a3a646d6f52bf3ddc29e33b8fce4661b",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "commitCreateStakeRemoveOrderMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation commitCreateStakeRemoveOrderMutation(\n $poolName: String!\n $amount: String!\n) {\n createStakeRemoveOrder(input: {order: {poolName: $poolName, amount: $amount}}) {\n order {\n id\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
(node as any).hash = '561be0497e5317997815bea692b73da9';
|
||||||
|
export default node;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { graphql } from "babel-plugin-relay/macro";
|
||||||
|
import type { Environment } from "react-relay";
|
||||||
|
import { commitMutation } from "react-relay";
|
||||||
|
|
||||||
|
import type { commitCreateStakeRemoveOrderMutationVariables } from "./__generated__/commitCreateStakeRemoveOrderMutation.graphql";
|
||||||
|
|
||||||
|
export const commitCreateStakeRemoveOrderMutation = (
|
||||||
|
environment: Environment,
|
||||||
|
variables: commitCreateStakeRemoveOrderMutationVariables
|
||||||
|
) => {
|
||||||
|
return commitMutation(environment, {
|
||||||
|
mutation: graphql`
|
||||||
|
mutation commitCreateStakeRemoveOrderMutation(
|
||||||
|
$poolName: String!
|
||||||
|
$amount: String!
|
||||||
|
) {
|
||||||
|
createStakeRemoveOrder(
|
||||||
|
input: { order: { poolName: $poolName, amount: $amount } }
|
||||||
|
) {
|
||||||
|
order {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
variables,
|
||||||
|
onCompleted: (_response) => {
|
||||||
|
window.location.href = "/orders/stake";
|
||||||
|
},
|
||||||
|
onError: (_error) => {},
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./RemoveStakeModal";
|
||||||
139
app/javascript/src/pages/Dashboard/Vault/Vault.tsx
Normal file
139
app/javascript/src/pages/Dashboard/Vault/Vault.tsx
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import type { FC } from "react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import cx from "classnames";
|
||||||
|
import { XCircleIcon } from "@heroicons/react/outline";
|
||||||
|
import { useLazyLoadQuery } from "react-relay";
|
||||||
|
import { graphql } from "babel-plugin-relay/macro";
|
||||||
|
import BigNumber from "bignumber.js";
|
||||||
|
|
||||||
|
import type { Vault as VaultType } from "../../../types/yieldwatch";
|
||||||
|
import { RemoveStakeModal } from "./RemoveStakeModal";
|
||||||
|
import type { VaultQuery } from "./__generated__/VaultQuery.graphql";
|
||||||
|
|
||||||
|
type VaultProps = {
|
||||||
|
vault: Partial<VaultType>;
|
||||||
|
isLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Vault: FC<VaultProps> = ({ vault, isLoading }) => {
|
||||||
|
const { stakeOrders } = useLazyLoadQuery<VaultQuery>(
|
||||||
|
graphql`
|
||||||
|
query VaultQuery(
|
||||||
|
$status: ProcessStatus!
|
||||||
|
$poolName: String!
|
||||||
|
$amount: Float!
|
||||||
|
) {
|
||||||
|
stakeOrders(
|
||||||
|
filter: {
|
||||||
|
status: [$status]
|
||||||
|
poolName: { eq: $poolName }
|
||||||
|
amount: { lt: $amount }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
status: "PROCESSING",
|
||||||
|
poolName: vault.name ?? "",
|
||||||
|
amount: 0,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [removeStakeModalIsOpen, setRemoveStakeModalIsOpen] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
|
||||||
|
const handleRemoveStakeModal = () => {
|
||||||
|
setRemoveStakeModalIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const alreadyOnUnstakeOrder = stakeOrders.edges.reduce((acc, current) => {
|
||||||
|
return BigNumber.sum(acc, current.node.amount);
|
||||||
|
}, new BigNumber(0));
|
||||||
|
|
||||||
|
const totalDepositedAndRewarded =
|
||||||
|
(vault.depositedTokens ?? 0) + (vault.totalRewards ?? 0);
|
||||||
|
|
||||||
|
let totalStaked = BigNumber.sum(
|
||||||
|
alreadyOnUnstakeOrder,
|
||||||
|
totalDepositedAndRewarded
|
||||||
|
);
|
||||||
|
|
||||||
|
totalStaked = totalStaked.isLessThan(0.0001) ? new BigNumber(0) : totalStaked;
|
||||||
|
|
||||||
|
const totalStakedFixed = totalStaked.toFixed(4);
|
||||||
|
const totalDeposited = (
|
||||||
|
totalStaked.isEqualTo(0) ? 0 : vault.depositedTokens
|
||||||
|
)?.toFixed(4);
|
||||||
|
|
||||||
|
const totalRewarded = (
|
||||||
|
totalStaked.isEqualTo(0) ? 0 : vault.totalRewards
|
||||||
|
)?.toFixed(4);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RemoveStakeModal
|
||||||
|
isOpen={removeStakeModalIsOpen}
|
||||||
|
setIsOpen={setRemoveStakeModalIsOpen}
|
||||||
|
stakedCake={totalStakedFixed}
|
||||||
|
poolName={vault.name}
|
||||||
|
/>
|
||||||
|
<div className="shadow-lg px-4 py-6 w-full bg-white dark:bg-gray-800 rounded-lg">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<p className="text-sm w-max text-gray-700 dark:text-white font-semibold border-b border-gray-200">
|
||||||
|
{vault.name}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button onClick={handleRemoveStakeModal} aria-label="Remover Stake">
|
||||||
|
<XCircleIcon className="h-5 w-5 text-red-500" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-end space-x-2 my-6">
|
||||||
|
<p
|
||||||
|
className={cx(
|
||||||
|
"text-5xl text-black dark:text-white font-bold",
|
||||||
|
isLoading
|
||||||
|
? "w-36 h-10 inline-block animate-pulse bg-gray-300 rounded"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{!isLoading && totalStakedFixed}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="dark:text-white">
|
||||||
|
<div className="flex items-center pb-2 mb-2 text-sm space-x-12 md:space-x-24 justify-between border-b border-gray-200">
|
||||||
|
<p>Depositado</p>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"flex items-end text-xs",
|
||||||
|
isLoading
|
||||||
|
? "w-10 h-4 inline-block animate-pulse bg-gray-300 rounded"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{!isLoading && totalDeposited}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center text-sm space-x-12 md:space-x-24 justify-between">
|
||||||
|
<p>Ganho</p>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"flex items-end text-xs",
|
||||||
|
isLoading
|
||||||
|
? "w-10 h-4 inline-block animate-pulse bg-gray-300 rounded"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{!isLoading && totalRewarded}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
222
app/javascript/src/pages/Dashboard/Vault/__generated__/VaultQuery.graphql.ts
generated
Normal file
222
app/javascript/src/pages/Dashboard/Vault/__generated__/VaultQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from "relay-runtime";
|
||||||
|
export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value";
|
||||||
|
export type VaultQueryVariables = {
|
||||||
|
status: ProcessStatus;
|
||||||
|
poolName: string;
|
||||||
|
amount: number;
|
||||||
|
};
|
||||||
|
export type VaultQueryResponse = {
|
||||||
|
readonly stakeOrders: {
|
||||||
|
readonly edges: ReadonlyArray<{
|
||||||
|
readonly node: {
|
||||||
|
readonly amount: string;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type VaultQuery = {
|
||||||
|
readonly response: VaultQueryResponse;
|
||||||
|
readonly variables: VaultQueryVariables;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
query VaultQuery(
|
||||||
|
$status: ProcessStatus!
|
||||||
|
$poolName: String!
|
||||||
|
$amount: Float!
|
||||||
|
) {
|
||||||
|
stakeOrders(filter: {status: [$status], poolName: {eq: $poolName}, amount: {lt: $amount}}) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
amount
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "amount"
|
||||||
|
},
|
||||||
|
v1 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "poolName"
|
||||||
|
},
|
||||||
|
v2 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "status"
|
||||||
|
},
|
||||||
|
v3 = [
|
||||||
|
{
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "lt",
|
||||||
|
"variableName": "amount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "eq",
|
||||||
|
"variableName": "poolName"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "poolName"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "status.0",
|
||||||
|
"variableName": "status"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ListValue",
|
||||||
|
"name": "status"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "ObjectValue",
|
||||||
|
"name": "filter"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v4 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "amount",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v2/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "VaultQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v3/*: any*/),
|
||||||
|
"concreteType": "StakeOrderConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "stakeOrders",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "StakeOrderEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "StakeOrder",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v4/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "VaultQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v3/*: any*/),
|
||||||
|
"concreteType": "StakeOrderConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "stakeOrders",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "StakeOrderEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "StakeOrder",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v4/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "6565697f7f43e955abee8a8a1eeb8e9b",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "VaultQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query VaultQuery(\n $status: ProcessStatus!\n $poolName: String!\n $amount: Float!\n) {\n stakeOrders(filter: {status: [$status], poolName: {eq: $poolName}, amount: {lt: $amount}}) {\n edges {\n node {\n amount\n id\n }\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
(node as any).hash = 'e5dced4589579717b408bc2f555b98ab';
|
||||||
|
export default node;
|
||||||
1
app/javascript/src/pages/Dashboard/Vault/index.ts
Normal file
1
app/javascript/src/pages/Dashboard/Vault/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from "./Vault";
|
||||||
@@ -11,10 +11,9 @@ import { StakeOrderModal } from "./StakeOrderModal";
|
|||||||
type PoolProps = {
|
type PoolProps = {
|
||||||
pool: PoolConfig;
|
pool: PoolConfig;
|
||||||
balance: string;
|
balance: string;
|
||||||
currencyId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Pool: FC<PoolProps> = ({ pool, balance, currencyId }) => {
|
export const Pool: FC<PoolProps> = ({ pool, balance }) => {
|
||||||
const {
|
const {
|
||||||
provider,
|
provider,
|
||||||
pancake: { router },
|
pancake: { router },
|
||||||
@@ -36,7 +35,7 @@ export const Pool: FC<PoolProps> = ({ pool, balance, currencyId }) => {
|
|||||||
const totalStaked = await getTotalStaked(provider, pool);
|
const totalStaked = await getTotalStaked(provider, pool);
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(
|
console.info(
|
||||||
`Total Staked for ${pool.stakingToken.symbol} - ${
|
`Total Staked for ${pool.stakingToken.symbol} - ${
|
||||||
pool.earningToken.symbol
|
pool.earningToken.symbol
|
||||||
}: ${JSON.stringify(totalStaked)}`
|
}: ${JSON.stringify(totalStaked)}`
|
||||||
@@ -94,7 +93,6 @@ export const Pool: FC<PoolProps> = ({ pool, balance, currencyId }) => {
|
|||||||
<StakeOrderModal
|
<StakeOrderModal
|
||||||
poolName={pool.earningToken.symbol}
|
poolName={pool.earningToken.symbol}
|
||||||
balance={balance}
|
balance={balance}
|
||||||
currencyId={currencyId}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export const PoolListing = () => {
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
currency {
|
currency {
|
||||||
id
|
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
amount
|
amount
|
||||||
@@ -31,7 +30,6 @@ export const PoolListing = () => {
|
|||||||
)?.node;
|
)?.node;
|
||||||
|
|
||||||
const balance = cakeBalance?.amount ?? "0";
|
const balance = cakeBalance?.amount ?? "0";
|
||||||
const currencyId = cakeBalance?.currency.id ?? "????";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 place-items-center w-full gap-8 py-4 -mt-16 overflow-x-hidden">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 place-items-center w-full gap-8 py-4 -mt-16 overflow-x-hidden">
|
||||||
@@ -39,12 +37,7 @@ export const PoolListing = () => {
|
|||||||
.filter((pool) => !pool.isFinished)
|
.filter((pool) => !pool.isFinished)
|
||||||
.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
|
.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
|
||||||
.map((pool) => (
|
.map((pool) => (
|
||||||
<Pool
|
<Pool key={pool.sousId} pool={pool} balance={balance} />
|
||||||
key={pool.sousId}
|
|
||||||
pool={pool}
|
|
||||||
balance={balance}
|
|
||||||
currencyId={currencyId}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,17 +10,12 @@ import { commitCreateStakeOrderMutation } from "./createStakeOrder";
|
|||||||
type Props = {
|
type Props = {
|
||||||
poolName: string;
|
poolName: string;
|
||||||
balance: string;
|
balance: string;
|
||||||
currencyId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const inputBaseStyles =
|
const inputBaseStyles =
|
||||||
"rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3";
|
"rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3";
|
||||||
|
|
||||||
export const StakeOrderModal: FC<Props> = ({
|
export const StakeOrderModal: FC<Props> = ({ poolName, balance }) => {
|
||||||
poolName,
|
|
||||||
balance,
|
|
||||||
currencyId,
|
|
||||||
}) => {
|
|
||||||
const environment = useRelayEnvironment();
|
const environment = useRelayEnvironment();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [investAmountInput, setInvestAmountInput] = useState("0");
|
const [investAmountInput, setInvestAmountInput] = useState("0");
|
||||||
@@ -34,7 +29,6 @@ export const StakeOrderModal: FC<Props> = ({
|
|||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
commitCreateStakeOrderMutation(environment, {
|
commitCreateStakeOrderMutation(environment, {
|
||||||
currencyId,
|
|
||||||
amount: investAmountInput,
|
amount: investAmountInput,
|
||||||
poolName,
|
poolName,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import { ConcreteRequest } from "relay-runtime";
|
import { ConcreteRequest } from "relay-runtime";
|
||||||
export type createStakeOrderMutationVariables = {
|
export type createStakeOrderMutationVariables = {
|
||||||
currencyId: string;
|
|
||||||
poolName: string;
|
poolName: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
};
|
};
|
||||||
@@ -24,11 +23,10 @@ export type createStakeOrderMutation = {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
mutation createStakeOrderMutation(
|
mutation createStakeOrderMutation(
|
||||||
$currencyId: ID!
|
|
||||||
$poolName: String!
|
$poolName: String!
|
||||||
$amount: String!
|
$amount: String!
|
||||||
) {
|
) {
|
||||||
createStakeOrder(input: {order: {currencyId: $currencyId, poolName: $poolName, amount: $amount}}) {
|
createStakeOrder(input: {order: {poolName: $poolName, amount: $amount}}) {
|
||||||
order {
|
order {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@@ -43,16 +41,11 @@ var v0 = {
|
|||||||
"name": "amount"
|
"name": "amount"
|
||||||
},
|
},
|
||||||
v1 = {
|
v1 = {
|
||||||
"defaultValue": null,
|
|
||||||
"kind": "LocalArgument",
|
|
||||||
"name": "currencyId"
|
|
||||||
},
|
|
||||||
v2 = {
|
|
||||||
"defaultValue": null,
|
"defaultValue": null,
|
||||||
"kind": "LocalArgument",
|
"kind": "LocalArgument",
|
||||||
"name": "poolName"
|
"name": "poolName"
|
||||||
},
|
},
|
||||||
v3 = [
|
v2 = [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": [
|
"args": [
|
||||||
@@ -65,11 +58,6 @@ v3 = [
|
|||||||
"name": "amount",
|
"name": "amount",
|
||||||
"variableName": "amount"
|
"variableName": "amount"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"kind": "Variable",
|
|
||||||
"name": "currencyId",
|
|
||||||
"variableName": "currencyId"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"kind": "Variable",
|
"kind": "Variable",
|
||||||
"name": "poolName",
|
"name": "poolName",
|
||||||
@@ -115,13 +103,12 @@ return {
|
|||||||
"fragment": {
|
"fragment": {
|
||||||
"argumentDefinitions": [
|
"argumentDefinitions": [
|
||||||
(v0/*: any*/),
|
(v0/*: any*/),
|
||||||
(v1/*: any*/),
|
(v1/*: any*/)
|
||||||
(v2/*: any*/)
|
|
||||||
],
|
],
|
||||||
"kind": "Fragment",
|
"kind": "Fragment",
|
||||||
"metadata": null,
|
"metadata": null,
|
||||||
"name": "createStakeOrderMutation",
|
"name": "createStakeOrderMutation",
|
||||||
"selections": (v3/*: any*/),
|
"selections": (v2/*: any*/),
|
||||||
"type": "Mutation",
|
"type": "Mutation",
|
||||||
"abstractKey": null
|
"abstractKey": null
|
||||||
},
|
},
|
||||||
@@ -129,22 +116,21 @@ return {
|
|||||||
"operation": {
|
"operation": {
|
||||||
"argumentDefinitions": [
|
"argumentDefinitions": [
|
||||||
(v1/*: any*/),
|
(v1/*: any*/),
|
||||||
(v2/*: any*/),
|
|
||||||
(v0/*: any*/)
|
(v0/*: any*/)
|
||||||
],
|
],
|
||||||
"kind": "Operation",
|
"kind": "Operation",
|
||||||
"name": "createStakeOrderMutation",
|
"name": "createStakeOrderMutation",
|
||||||
"selections": (v3/*: any*/)
|
"selections": (v2/*: any*/)
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "bfe4935c593947810fbb8d7a52421483",
|
"cacheID": "e845ef953b2de9dd797930c0838f30f8",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "createStakeOrderMutation",
|
"name": "createStakeOrderMutation",
|
||||||
"operationKind": "mutation",
|
"operationKind": "mutation",
|
||||||
"text": "mutation createStakeOrderMutation(\n $currencyId: ID!\n $poolName: String!\n $amount: String!\n) {\n createStakeOrder(input: {order: {currencyId: $currencyId, poolName: $poolName, amount: $amount}}) {\n order {\n id\n }\n }\n}\n"
|
"text": "mutation createStakeOrderMutation(\n $poolName: String!\n $amount: String!\n) {\n createStakeOrder(input: {order: {poolName: $poolName, amount: $amount}}) {\n order {\n id\n }\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
(node as any).hash = '036f321e28fcb4bd3e274498cd3f116a';
|
(node as any).hash = '36f248efe00b47bc1b27f597c5ab45c3';
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -10,19 +10,9 @@ export const commitCreateStakeOrderMutation = (
|
|||||||
) => {
|
) => {
|
||||||
return commitMutation(environment, {
|
return commitMutation(environment, {
|
||||||
mutation: graphql`
|
mutation: graphql`
|
||||||
mutation createStakeOrderMutation(
|
mutation createStakeOrderMutation($poolName: String!, $amount: String!) {
|
||||||
$currencyId: ID!
|
|
||||||
$poolName: String!
|
|
||||||
$amount: String!
|
|
||||||
) {
|
|
||||||
createStakeOrder(
|
createStakeOrder(
|
||||||
input: {
|
input: { order: { poolName: $poolName, amount: $amount } }
|
||||||
order: {
|
|
||||||
currencyId: $currencyId
|
|
||||||
poolName: $poolName
|
|
||||||
amount: $amount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
order {
|
order {
|
||||||
id
|
id
|
||||||
@@ -30,7 +20,7 @@ export const commitCreateStakeOrderMutation = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: { ...variables },
|
variables,
|
||||||
onCompleted: (_response) => {
|
onCompleted: (_response) => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
},
|
},
|
||||||
@@ -9,7 +9,6 @@ export type PoolListingQueryResponse = {
|
|||||||
readonly edges: ReadonlyArray<{
|
readonly edges: ReadonlyArray<{
|
||||||
readonly node: {
|
readonly node: {
|
||||||
readonly currency: {
|
readonly currency: {
|
||||||
readonly id: string;
|
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
};
|
};
|
||||||
readonly amount: string;
|
readonly amount: string;
|
||||||
@@ -30,8 +29,8 @@ query PoolListingQuery {
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
currency {
|
currency {
|
||||||
id
|
|
||||||
name
|
name
|
||||||
|
id
|
||||||
}
|
}
|
||||||
amount
|
amount
|
||||||
id
|
id
|
||||||
@@ -46,33 +45,21 @@ var v0 = {
|
|||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "id",
|
"name": "name",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v1 = {
|
v1 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"concreteType": "Currency",
|
"kind": "ScalarField",
|
||||||
"kind": "LinkedField",
|
"name": "amount",
|
||||||
"name": "currency",
|
|
||||||
"plural": false,
|
|
||||||
"selections": [
|
|
||||||
(v0/*: any*/),
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "name",
|
|
||||||
"storageKey": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v2 = {
|
v2 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "amount",
|
"name": "id",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
@@ -106,8 +93,19 @@ return {
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v1/*: any*/),
|
{
|
||||||
(v2/*: any*/)
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Currency",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "currency",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
(v1/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
@@ -151,9 +149,21 @@ return {
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Currency",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "currency",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
(v2/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
(v1/*: any*/),
|
(v1/*: any*/),
|
||||||
(v2/*: any*/),
|
(v2/*: any*/)
|
||||||
(v0/*: any*/)
|
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
@@ -166,14 +176,14 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "06c9467183eb0e89329ec630a8cc4880",
|
"cacheID": "6abf5e963429e49993af50df156f8e1c",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "PoolListingQuery",
|
"name": "PoolListingQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query PoolListingQuery {\n balances {\n edges {\n node {\n currency {\n id\n name\n }\n amount\n id\n }\n }\n }\n}\n"
|
"text": "query PoolListingQuery {\n balances {\n edges {\n node {\n currency {\n name\n id\n }\n amount\n id\n }\n }\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
(node as any).hash = '570efc1d3b5dac09303b8692d6830bb2';
|
(node as any).hash = '4fefb238e24b79198799686599255e6c';
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ class StakeOrder < ApplicationRecord
|
|||||||
validates :pool_name, presence: true
|
validates :pool_name, presence: true
|
||||||
validates :amount, presence: true
|
validates :amount, presence: true
|
||||||
|
|
||||||
|
def self.ransackable_attributes(auth_object = nil)
|
||||||
|
super & ["pool_name", "amount"]
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def notification_message
|
def notification_message
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
"lint": "eslint --ext .jsx,.js,.tsx,.ts app/javascript/",
|
"lint": "eslint --ext .jsx,.js,.tsx,.ts app/javascript/",
|
||||||
"lint:fix": "eslint --fix --ext .jsx,.js,.tsx,.ts app/javascript/",
|
"lint:fix": "eslint --fix --ext .jsx,.js,.tsx,.ts app/javascript/",
|
||||||
"tsc": "tsc --noEmit",
|
"tsc": "tsc --noEmit",
|
||||||
"relay": "relay-compiler --schema app/javascript/__generated__/schema.graphql --src app/javascript/src --extensions tsx --language typescript",
|
"relay": "relay-compiler",
|
||||||
"relay:watch": "relay-compiler --schema app/javascript/__generated__/schema.graphql --src app/javascript/src --extensions tsx --language typescript --watch"
|
"relay:watch": "yarn relay --watch"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"@babel/preset-react": "^7.14.5",
|
"@babel/preset-react": "^7.14.5",
|
||||||
"@babel/preset-typescript": "^7.14.5",
|
"@babel/preset-typescript": "^7.14.5",
|
||||||
"@headlessui/react": "^1.4.0",
|
"@headlessui/react": "^1.4.0",
|
||||||
|
"@heroicons/react": "^1.0.4",
|
||||||
"@rails/actioncable": "^6.0.0",
|
"@rails/actioncable": "^6.0.0",
|
||||||
"@rails/activestorage": "^6.0.0",
|
"@rails/activestorage": "^6.0.0",
|
||||||
"@rails/ujs": "^6.0.0",
|
"@rails/ujs": "^6.0.0",
|
||||||
@@ -61,6 +62,7 @@
|
|||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
"relay-compiler": "^11.0.2",
|
"relay-compiler": "^11.0.2",
|
||||||
"relay-compiler-language-typescript": "^14.0.0",
|
"relay-compiler-language-typescript": "^14.0.0",
|
||||||
|
"relay-config": "^11.0.2",
|
||||||
"webpack-dev-server": "^3.11.2"
|
"webpack-dev-server": "^3.11.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
relay.config.js
Normal file
6
relay.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
src: "app/javascript/src",
|
||||||
|
schema: "app/javascript/__generated__/schema.graphql",
|
||||||
|
language: "typescript",
|
||||||
|
exclude: ["**/__generated__/**"],
|
||||||
|
};
|
||||||
@@ -6,13 +6,11 @@ RSpec.describe(Mutations::CreateStakeOrder, type: :mutation) do
|
|||||||
let(:query_string) do
|
let(:query_string) do
|
||||||
<<~GQL
|
<<~GQL
|
||||||
mutation(
|
mutation(
|
||||||
$currencyId: ID!,
|
|
||||||
$amount: String!,
|
$amount: String!,
|
||||||
$poolName: String!,
|
$poolName: String!,
|
||||||
) {
|
) {
|
||||||
createStakeOrder(input: {
|
createStakeOrder(input: {
|
||||||
order: {
|
order: {
|
||||||
currencyId: $currencyId,
|
|
||||||
amount: $amount,
|
amount: $amount,
|
||||||
poolName: $poolName,
|
poolName: $poolName,
|
||||||
}
|
}
|
||||||
@@ -43,10 +41,7 @@ RSpec.describe(Mutations::CreateStakeOrder, type: :mutation) do
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
currency_global_id = GraphQL::Schema::UniqueWithinType.encode("Currency", currency.id)
|
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
"currencyId": currency_global_id,
|
|
||||||
"amount": "0.80",
|
"amount": "0.80",
|
||||||
"poolName": "CAKE/BNB",
|
"poolName": "CAKE/BNB",
|
||||||
"status": "PROCESSING",
|
"status": "PROCESSING",
|
||||||
@@ -87,10 +82,7 @@ RSpec.describe(Mutations::CreateStakeOrder, type: :mutation) do
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
currency_global_id = GraphQL::Schema::UniqueWithinType.encode("Currency", currency.id)
|
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
"currencyId": currency_global_id,
|
|
||||||
"amount": "0.80",
|
"amount": "0.80",
|
||||||
"poolName": "CAKE/BNB",
|
"poolName": "CAKE/BNB",
|
||||||
}
|
}
|
||||||
|
|||||||
112
spec/graphql/mutations/create_stake_remove_order_spec.rb
Normal file
112
spec/graphql/mutations/create_stake_remove_order_spec.rb
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
RSpec.describe(Mutations::CreateStakeRemoveOrder, type: :mutation) do
|
||||||
|
let(:query_string) do
|
||||||
|
<<~GQL
|
||||||
|
mutation(
|
||||||
|
$amount: String!,
|
||||||
|
$poolName: String!,
|
||||||
|
) {
|
||||||
|
createStakeRemoveOrder(input: {
|
||||||
|
order: {
|
||||||
|
amount: $amount,
|
||||||
|
poolName: $poolName,
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
errors {
|
||||||
|
fullMessages
|
||||||
|
fieldName
|
||||||
|
messages
|
||||||
|
path
|
||||||
|
}
|
||||||
|
order {
|
||||||
|
poolName
|
||||||
|
status
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GQL
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the user has enough balance" do
|
||||||
|
it "withdraws from his account and creates a buy order" do
|
||||||
|
currency = create(:currency)
|
||||||
|
user = create(
|
||||||
|
:user,
|
||||||
|
balances: [
|
||||||
|
build(:balance, currency: currency, amount: 0),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
"amount": "200.80",
|
||||||
|
"poolName": "CAKE/BNB",
|
||||||
|
"status": "PROCESSING",
|
||||||
|
}
|
||||||
|
|
||||||
|
context = { current_user: user }
|
||||||
|
|
||||||
|
result = XStakeSchema.execute(
|
||||||
|
query_string,
|
||||||
|
variables: variables,
|
||||||
|
context: context
|
||||||
|
).to_h.with_indifferent_access
|
||||||
|
|
||||||
|
expect(result).to(eq({
|
||||||
|
"data" => {
|
||||||
|
"createStakeRemoveOrder" => {
|
||||||
|
"errors" => nil,
|
||||||
|
"order" => {
|
||||||
|
"status" => "PROCESSING",
|
||||||
|
"amount" => "-200.8",
|
||||||
|
"poolName" => "CAKE/BNB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when it repeats the mutation with a request in `processing`" do
|
||||||
|
it "update amount from the order" do
|
||||||
|
currency = create(:currency)
|
||||||
|
user = create(
|
||||||
|
:user,
|
||||||
|
balances: [
|
||||||
|
build(:balance, currency: currency, amount: 0),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
create(:stake_order, amount: -200.8, user: user, pool_name: "CAKE/BNB", currency: currency)
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
"amount": "200.80",
|
||||||
|
"poolName": "CAKE/BNB",
|
||||||
|
}
|
||||||
|
|
||||||
|
context = { current_user: user }
|
||||||
|
|
||||||
|
result = XStakeSchema.execute(
|
||||||
|
query_string,
|
||||||
|
variables: variables,
|
||||||
|
context: context
|
||||||
|
).to_h.with_indifferent_access
|
||||||
|
|
||||||
|
expect(result).to(eq({
|
||||||
|
"data" => {
|
||||||
|
"createStakeRemoveOrder" => {
|
||||||
|
"errors" => nil,
|
||||||
|
"order" => {
|
||||||
|
"status" => "PROCESSING",
|
||||||
|
"amount" => "-401.6",
|
||||||
|
"poolName" => "CAKE/BNB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
14
yarn.lock
generated
14
yarn.lock
generated
@@ -1472,6 +1472,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.4.0.tgz#c6d424d8ab10ac925e4423d7f3cbab02c30d736a"
|
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.4.0.tgz#c6d424d8ab10ac925e4423d7f3cbab02c30d736a"
|
||||||
integrity sha512-C+FmBVF6YGvqcEI5fa2dfVbEaXr2RGR6Kw1E5HXIISIZEfsrH/yuCgsjWw5nlRF9vbCxmQ/EKs64GAdKeb8gCw==
|
integrity sha512-C+FmBVF6YGvqcEI5fa2dfVbEaXr2RGR6Kw1E5HXIISIZEfsrH/yuCgsjWw5nlRF9vbCxmQ/EKs64GAdKeb8gCw==
|
||||||
|
|
||||||
|
"@heroicons/react@^1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.4.tgz#11847eb2ea5510419d7ada9ff150a33af0ad0863"
|
||||||
|
integrity sha512-3kOrTmo8+Z8o6AL0rzN82MOf8J5CuxhRLFhpI8mrn+3OqekA6d5eb1GYO3EYYo1Vn6mYQSMNTzCWbEwUInb0cQ==
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.5.0":
|
"@humanwhocodes/config-array@^0.5.0":
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
|
||||||
@@ -3057,7 +3062,7 @@ core-util-is@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
cosmiconfig@^5.0.0:
|
cosmiconfig@^5.0.0, cosmiconfig@^5.0.5:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||||
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
|
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
|
||||||
@@ -7844,6 +7849,13 @@ relay-compiler@^11.0.2:
|
|||||||
signedsource "^1.0.0"
|
signedsource "^1.0.0"
|
||||||
yargs "^15.3.1"
|
yargs "^15.3.1"
|
||||||
|
|
||||||
|
relay-config@^11.0.2:
|
||||||
|
version "11.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/relay-config/-/relay-config-11.0.2.tgz#d1e5bbac795dfe0a414ed61c94faabdef7db99c5"
|
||||||
|
integrity sha512-j/bl04lGwZ+xSM/21KN87lPXY6t7YWkStfST63dQhJN35F6gQKZevmxVVPlEJ7Qs41AyrY1kilGBIfbEZPPdSA==
|
||||||
|
dependencies:
|
||||||
|
cosmiconfig "^5.0.5"
|
||||||
|
|
||||||
relay-runtime@11.0.2, relay-runtime@^11.0.2:
|
relay-runtime@11.0.2, relay-runtime@^11.0.2:
|
||||||
version "11.0.2"
|
version "11.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-11.0.2.tgz#c3650477d45665b9628b852b35f203e361ad55e8"
|
resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-11.0.2.tgz#c3650477d45665b9628b852b35f203e361ad55e8"
|
||||||
|
|||||||
Reference in New Issue
Block a user