Skip to content

Commit

Permalink
Update credits format (#896)
Browse files Browse the repository at this point in the history
* Update credits format

* format
  • Loading branch information
broody committed Oct 21, 2024
1 parent db14cd2 commit e6644dd
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 23 deletions.
34 changes: 17 additions & 17 deletions packages/keychain/src/components/Funding/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,35 @@ import { CreditsIcon, EthereumIcon } from "@cartridge/ui";
import { HStack, Spacer, Text, VStack } from "@chakra-ui/react";
import { CurrencyBase, CurrencyQuote, usePriceQuery } from "generated/graphql";
import { useBalance } from "hooks/token";
import { useMemo } from "react";
import { formatEther } from "viem";

type BalanceProps = {
showBalances: ("credits" | "eth" | "strk")[];
};

function formatEthBalance(ethBalance: bigint): string {
const formattedBalance = parseFloat(formatEther(ethBalance));
if (ethBalance === 0n) {
function formatTokenBalance(balance: bigint): string {
const formattedBalance = parseFloat(formatEther(balance));
if (formattedBalance === 0) {
return "0.00";
}

return formattedBalance < 0.01
? `~${formattedBalance.toFixed(2)}`
: formattedBalance.toFixed(2);
}

function formatUsdBalance(balance: bigint, price: number) {
return parseFloat(formatEther(balance)) * price;
}

export function Balance({ showBalances }: BalanceProps) {
const { ethBalance, creditsBalance } = useBalance();

const priceQuery = usePriceQuery({
quote: CurrencyQuote.Eth,
base: CurrencyBase.Usd,
});
const price = priceQuery.data?.price;

const usdBalance = useMemo(() => {
if (!price || !ethBalance) {
return 0;
}

return parseFloat(formatEther(ethBalance)) * parseFloat(price.amount);
}, [ethBalance, price]);
const price = parseFloat(priceQuery.data?.price?.amount || "");

return (
<VStack w="full" borderRadius="base" overflow="hidden" spacing="1px">
Expand All @@ -61,8 +57,10 @@ export function Balance({ showBalances }: BalanceProps) {
>
<HStack>
<CreditsIcon fontSize={20} />
<Text>{creditsBalance?.toFixed(2)}</Text>
<Text color="text.secondary">${creditsBalance?.toFixed(2)}</Text>
<Text>{formatTokenBalance(creditsBalance)}</Text>
<Text color="text.secondary">
${formatUsdBalance(creditsBalance, 1).toFixed(2)}
</Text>
</HStack>
<Spacer />
<HStack color="text.secondary">
Expand All @@ -83,8 +81,10 @@ export function Balance({ showBalances }: BalanceProps) {
>
<HStack>
<EthereumIcon fontSize={20} />
<Text>{formatEthBalance(ethBalance)}</Text>
<Text color="text.secondary">${usdBalance?.toFixed(2)}</Text>
<Text>{formatTokenBalance(ethBalance)}</Text>
<Text color="text.secondary">
${formatUsdBalance(ethBalance, price).toFixed(2)}
</Text>
</HStack>
<Spacer />
<HStack color="text.secondary">
Expand Down
152 changes: 150 additions & 2 deletions packages/keychain/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export type Account = Node & {
controllers?: Maybe<Array<Controller>>;
createdAt: Scalars["Time"];
credentials: Credentials;
credits: Scalars["Int"];
credits: Scalars["BigInt"];
id: Scalars["ID"];
membership: AccountTeamConnection;
name?: Maybe<Scalars["String"]>;
Expand Down Expand Up @@ -383,6 +383,133 @@ export type Credentials = {
webauthn?: Maybe<Array<WebauthnCredential>>;
};

export type CreditsHistory = Node & {
__typename?: "CreditsHistory";
accountID: Scalars["String"];
createdAt: Scalars["Time"];
id: Scalars["ID"];
stripePayment?: Maybe<StripePayments>;
/** Transaction hash for debit transactions */
transactionHash?: Maybe<Scalars["String"]>;
/** Type of transaction: credit or debit */
transactionType: CreditsHistoryTransactionType;
updatedAt: Scalars["Time"];
};

/** A connection to a list of items. */
export type CreditsHistoryConnection = {
__typename?: "CreditsHistoryConnection";
/** A list of edges. */
edges?: Maybe<Array<Maybe<CreditsHistoryEdge>>>;
/** Information to aid in pagination. */
pageInfo: PageInfo;
/** Identifies the total count of items in the connection. */
totalCount: Scalars["Int"];
};

/** An edge in a connection. */
export type CreditsHistoryEdge = {
__typename?: "CreditsHistoryEdge";
/** A cursor for use in pagination. */
cursor: Scalars["Cursor"];
/** The item at the end of the edge. */
node?: Maybe<CreditsHistory>;
};

/** Ordering options for CreditsHistory connections */
export type CreditsHistoryOrder = {
/** The ordering direction. */
direction?: OrderDirection;
/** The field by which to order CreditsHistories. */
field: CreditsHistoryOrderField;
};

/** Properties by which CreditsHistory connections can be ordered. */
export enum CreditsHistoryOrderField {
CreatedAt = "CREATED_AT",
}

/** CreditsHistoryTransactionType is enum for the field transaction_type */
export enum CreditsHistoryTransactionType {
Credit = "credit",
Debit = "debit",
}

/**
* CreditsHistoryWhereInput is used for filtering CreditsHistory objects.
* Input was generated by ent.
*/
export type CreditsHistoryWhereInput = {
/** account_id field predicates */
accountID?: InputMaybe<Scalars["String"]>;
accountIDContains?: InputMaybe<Scalars["String"]>;
accountIDContainsFold?: InputMaybe<Scalars["String"]>;
accountIDEqualFold?: InputMaybe<Scalars["String"]>;
accountIDGT?: InputMaybe<Scalars["String"]>;
accountIDGTE?: InputMaybe<Scalars["String"]>;
accountIDHasPrefix?: InputMaybe<Scalars["String"]>;
accountIDHasSuffix?: InputMaybe<Scalars["String"]>;
accountIDIn?: InputMaybe<Array<Scalars["String"]>>;
accountIDLT?: InputMaybe<Scalars["String"]>;
accountIDLTE?: InputMaybe<Scalars["String"]>;
accountIDNEQ?: InputMaybe<Scalars["String"]>;
accountIDNotIn?: InputMaybe<Array<Scalars["String"]>>;
and?: InputMaybe<Array<CreditsHistoryWhereInput>>;
/** created_at field predicates */
createdAt?: InputMaybe<Scalars["Time"]>;
createdAtGT?: InputMaybe<Scalars["Time"]>;
createdAtGTE?: InputMaybe<Scalars["Time"]>;
createdAtIn?: InputMaybe<Array<Scalars["Time"]>>;
createdAtLT?: InputMaybe<Scalars["Time"]>;
createdAtLTE?: InputMaybe<Scalars["Time"]>;
createdAtNEQ?: InputMaybe<Scalars["Time"]>;
createdAtNotIn?: InputMaybe<Array<Scalars["Time"]>>;
/** stripe_payment edge predicates */
hasStripePayment?: InputMaybe<Scalars["Boolean"]>;
hasStripePaymentWith?: InputMaybe<Array<StripePaymentsWhereInput>>;
/** id field predicates */
id?: InputMaybe<Scalars["ID"]>;
idGT?: InputMaybe<Scalars["ID"]>;
idGTE?: InputMaybe<Scalars["ID"]>;
idIn?: InputMaybe<Array<Scalars["ID"]>>;
idLT?: InputMaybe<Scalars["ID"]>;
idLTE?: InputMaybe<Scalars["ID"]>;
idNEQ?: InputMaybe<Scalars["ID"]>;
idNotIn?: InputMaybe<Array<Scalars["ID"]>>;
not?: InputMaybe<CreditsHistoryWhereInput>;
or?: InputMaybe<Array<CreditsHistoryWhereInput>>;
/** transaction_hash field predicates */
transactionHash?: InputMaybe<Scalars["String"]>;
transactionHashContains?: InputMaybe<Scalars["String"]>;
transactionHashContainsFold?: InputMaybe<Scalars["String"]>;
transactionHashEqualFold?: InputMaybe<Scalars["String"]>;
transactionHashGT?: InputMaybe<Scalars["String"]>;
transactionHashGTE?: InputMaybe<Scalars["String"]>;
transactionHashHasPrefix?: InputMaybe<Scalars["String"]>;
transactionHashHasSuffix?: InputMaybe<Scalars["String"]>;
transactionHashIn?: InputMaybe<Array<Scalars["String"]>>;
transactionHashIsNil?: InputMaybe<Scalars["Boolean"]>;
transactionHashLT?: InputMaybe<Scalars["String"]>;
transactionHashLTE?: InputMaybe<Scalars["String"]>;
transactionHashNEQ?: InputMaybe<Scalars["String"]>;
transactionHashNotIn?: InputMaybe<Array<Scalars["String"]>>;
transactionHashNotNil?: InputMaybe<Scalars["Boolean"]>;
/** transaction_type field predicates */
transactionType?: InputMaybe<CreditsHistoryTransactionType>;
transactionTypeIn?: InputMaybe<Array<CreditsHistoryTransactionType>>;
transactionTypeNEQ?: InputMaybe<CreditsHistoryTransactionType>;
transactionTypeNotIn?: InputMaybe<Array<CreditsHistoryTransactionType>>;
/** updated_at field predicates */
updatedAt?: InputMaybe<Scalars["Time"]>;
updatedAtGT?: InputMaybe<Scalars["Time"]>;
updatedAtGTE?: InputMaybe<Scalars["Time"]>;
updatedAtIn?: InputMaybe<Array<Scalars["Time"]>>;
updatedAtLT?: InputMaybe<Scalars["Time"]>;
updatedAtLTE?: InputMaybe<Scalars["Time"]>;
updatedAtNEQ?: InputMaybe<Scalars["Time"]>;
updatedAtNotIn?: InputMaybe<Array<Scalars["Time"]>>;
};

export enum CurrencyBase {
Usd = "USD",
}
Expand Down Expand Up @@ -1305,6 +1432,7 @@ export type StripePayments = Node & {
id: Scalars["ID"];
liveMode: Scalars["Boolean"];
paymentIntentID: Scalars["String"];
paymentIntentStatus?: Maybe<StripePaymentsPaymentIntentStatus>;
referenceID?: Maybe<Scalars["String"]>;
updatedAt: Scalars["Time"];
userID: Scalars["String"];
Expand All @@ -1323,6 +1451,17 @@ export enum StripePaymentsOrderField {
CreatedAt = "CREATED_AT",
}

/** StripePaymentsPaymentIntentStatus is enum for the field payment_intent_status */
export enum StripePaymentsPaymentIntentStatus {
Canceled = "canceled",
Processing = "processing",
RequiresAction = "requires_action",
RequiresCapture = "requires_capture",
RequiresConfirmation = "requires_confirmation",
RequiresPaymentMethod = "requires_payment_method",
Succeeded = "succeeded",
}

/**
* StripePaymentsWhereInput is used for filtering StripePayments objects.
* Input was generated by ent.
Expand Down Expand Up @@ -1375,6 +1514,15 @@ export type StripePaymentsWhereInput = {
paymentIntentIDLTE?: InputMaybe<Scalars["String"]>;
paymentIntentIDNEQ?: InputMaybe<Scalars["String"]>;
paymentIntentIDNotIn?: InputMaybe<Array<Scalars["String"]>>;
/** payment_intent_status field predicates */
paymentIntentStatus?: InputMaybe<StripePaymentsPaymentIntentStatus>;
paymentIntentStatusIn?: InputMaybe<Array<StripePaymentsPaymentIntentStatus>>;
paymentIntentStatusIsNil?: InputMaybe<Scalars["Boolean"]>;
paymentIntentStatusNEQ?: InputMaybe<StripePaymentsPaymentIntentStatus>;
paymentIntentStatusNotIn?: InputMaybe<
Array<StripePaymentsPaymentIntentStatus>
>;
paymentIntentStatusNotNil?: InputMaybe<Scalars["Boolean"]>;
/** reference_id field predicates */
referenceID?: InputMaybe<Scalars["String"]>;
referenceIDContains?: InputMaybe<Scalars["String"]>;
Expand Down Expand Up @@ -1602,7 +1750,7 @@ export type AccountInfoQuery = {
__typename?: "AccountConnection";
edges?: Array<{
__typename?: "AccountEdge";
node?: { __typename?: "Account"; id: string; credits: number } | null;
node?: { __typename?: "Account"; id: string; credits: any } | null;
} | null> | null;
} | null;
};
Expand Down
1 change: 1 addition & 0 deletions packages/keychain/src/generated/introspection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const result: PossibleTypesResultData = {
"Account",
"AccountTeam",
"Controller",
"CreditsHistory",
"Deployment",
"DeploymentLog",
"File",
Expand Down
6 changes: 2 additions & 4 deletions packages/keychain/src/hooks/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function useBalance() {
const { controller } = useConnection();
const [isFetching, setIsFetching] = useState(true);
const [ethBalance, setEthBalance] = useState<bigint>(0n);
const [creditsBalance, setCreditsBalance] = useState<number>(0);
const [creditsBalance, setCreditsBalance] = useState<bigint>(0n);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error>();

Expand All @@ -21,9 +21,7 @@ export function useBalance() {
enabled: false,
onSuccess: async (data: AccountInfoQuery) => {
try {
// credits are retrieved as positive integers dominated in cents
const credits = data.accounts?.edges?.[0]?.node?.credits / 100;
setCreditsBalance(credits ?? 0);
setCreditsBalance(data.accounts?.edges?.[0]?.node?.credits ?? 0);
} catch (e) {
setError(e);
}
Expand Down

0 comments on commit e6644dd

Please sign in to comment.