Skip to content

Commit 24b5fce

Browse files
Move tokens context to utils
1 parent 3986505 commit 24b5fce

File tree

11 files changed

+85
-90
lines changed

11 files changed

+85
-90
lines changed

packages/keychain/src/components/DeployController.tsx

+24-26
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ import { Fees } from "./Fees";
2525
import { ControllerError } from "@/utils/connection";
2626
import { TransactionSummary } from "@/components/transaction/TransactionSummary";
2727
import { Link } from "react-router-dom";
28-
import { useFeeToken } from "@/hooks/tokens";
29-
import { getChainName } from "@cartridge/utils";
28+
import { getChainName, useFeeToken } from "@cartridge/utils";
3029

3130
export function DeployController({
3231
onClose,
@@ -51,28 +50,28 @@ export function DeployController({
5150
const feeEstimate: FeeEstimate | undefined = ctrlError?.data?.fee_estimate;
5251
const estimateFee: EstimateFee | undefined = feeEstimate
5352
? {
54-
gas_consumed: BigInt(feeEstimate.gas_consumed),
55-
overall_fee: BigInt(feeEstimate.overall_fee),
56-
gas_price: BigInt(feeEstimate.gas_price),
57-
unit: feeEstimate.unit,
58-
suggestedMaxFee: BigInt(feeEstimate.overall_fee),
59-
data_gas_consumed: BigInt(
60-
feeEstimate.data_gas_consumed ? feeEstimate.data_gas_consumed : "0x0",
61-
),
62-
data_gas_price: BigInt(
63-
feeEstimate.data_gas_price ? feeEstimate.data_gas_price : "0x0",
64-
),
65-
resourceBounds: {
66-
l1_gas: {
67-
max_amount: feeEstimate.overall_fee,
68-
max_price_per_unit: feeEstimate.gas_price,
69-
},
70-
l2_gas: {
71-
max_amount: feeEstimate.overall_fee,
72-
max_price_per_unit: feeEstimate.gas_price,
73-
},
53+
gas_consumed: BigInt(feeEstimate.gas_consumed),
54+
overall_fee: BigInt(feeEstimate.overall_fee),
55+
gas_price: BigInt(feeEstimate.gas_price),
56+
unit: feeEstimate.unit,
57+
suggestedMaxFee: BigInt(feeEstimate.overall_fee),
58+
data_gas_consumed: BigInt(
59+
feeEstimate.data_gas_consumed ? feeEstimate.data_gas_consumed : "0x0",
60+
),
61+
data_gas_price: BigInt(
62+
feeEstimate.data_gas_price ? feeEstimate.data_gas_price : "0x0",
63+
),
64+
resourceBounds: {
65+
l1_gas: {
66+
max_amount: feeEstimate.overall_fee,
67+
max_price_per_unit: feeEstimate.gas_price,
7468
},
75-
}
69+
l2_gas: {
70+
max_amount: feeEstimate.overall_fee,
71+
max_price_per_unit: feeEstimate.gas_price,
72+
},
73+
},
74+
}
7675
: undefined;
7776

7877
useEffect(() => {
@@ -273,9 +272,8 @@ function ExplorerLink({
273272

274273
return (
275274
<Link
276-
to={`https://${
277-
chainId === constants.StarknetChainId.SN_SEPOLIA ? "sepolia." : ""
278-
}starkscan.co/tx/${txHash}`}
275+
to={`https://${chainId === constants.StarknetChainId.SN_SEPOLIA ? "sepolia." : ""
276+
}starkscan.co/tx/${txHash}`}
279277
target="_blank"
280278
className="flex items-center gap-1 text-sm text-foreground-400 underline"
281279
>

packages/keychain/src/components/Fees.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { useEffect, useState } from "react";
22
import { Spinner } from "@cartridge/ui-next";
3+
import { ERC20, useFeeToken } from "@cartridge/utils";
34
import { EstimateFee } from "starknet";
4-
5-
import { convertTokenAmountToUSD, useFeeToken } from "@/hooks/tokens";
5+
import { convertTokenAmountToUSD } from "@/hooks/tokens";
66
import { ErrorAlert } from "./ErrorAlert";
7-
import { ERC20 } from "./provider/tokens";
87

98
export function Fees({
109
isLoading: isEstimating,

packages/keychain/src/components/funding/Balance.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import {
66
CardTitle,
77
CoinsIcon,
88
} from "@cartridge/ui-next";
9-
import { useCreditBalance } from "@cartridge/utils";
9+
import { useCreditBalance, useFeeToken, } from "@cartridge/utils";
1010
import { useController } from "@/hooks/controller";
1111
import {
1212
formatBalance,
1313
convertTokenAmountToUSD,
14-
useFeeToken,
1514
} from "@/hooks/tokens";
1615

1716
export enum BalanceType {

packages/keychain/src/components/funding/Deposit.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ import {
2929
Separator,
3030
LayoutHeader,
3131
} from "@cartridge/ui-next";
32+
import { useFeeToken } from "@cartridge/utils";
3233
import { useConnection } from "@/hooks/connection";
3334
import { ErrorAlert } from "../ErrorAlert";
3435
import { AmountSelection } from "./AmountSelection";
3536
import { Balance, BalanceType } from "./Balance";
3637
import { toast } from "sonner";
3738
import { DEFAULT_AMOUNT } from "./constants";
38-
import { convertUSDToTokenAmount, useFeeToken } from "@/hooks/tokens";
39+
import { convertUSDToTokenAmount } from "@/hooks/tokens";
3940

4041
type DepositProps = {
4142
onComplete?: (deployHash?: string) => void;

packages/keychain/src/components/provider/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PropsWithChildren, useCallback, useMemo } from "react";
22
import { QueryClient, QueryClientProvider } from "react-query";
33
import { useConnectionValue } from "@/hooks/connection";
4+
import { TokensProvider } from "@cartridge/utils";
45
import { CartridgeAPIProvider } from "@cartridge/utils/api/cartridge";
56
import { ENDPOINT } from "@/utils/graphql";
67
import { PostHogProvider } from "./posthog";
@@ -11,7 +12,6 @@ import { sepolia, mainnet } from "@starknet-react/chains";
1112
import { constants, num } from "starknet";
1213
import { BrowserRouter } from "react-router-dom";
1314
import { ConnectionContext } from "./connection";
14-
import { TokensProvider } from "./tokens";
1515

1616
export function Provider({ children }: PropsWithChildren) {
1717
const connection = useConnectionValue();
@@ -47,7 +47,7 @@ export function Provider({ children }: PropsWithChildren) {
4747
defaultChainId={defaultChainId}
4848
provider={jsonRpcProvider({ rpc })}
4949
>
50-
<TokensProvider>
50+
<TokensProvider provider={connection.controller?.provider}>
5151
<PostHogProvider>{children}</PostHogProvider>
5252
</TokensProvider>
5353
</StarknetConfig>

packages/keychain/src/hooks/tokens.tsx

-35
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,3 @@
1-
import { useContext } from "react";
2-
import {
3-
TokensContext,
4-
TokensContextValue,
5-
} from "@/components/provider/tokens";
6-
import { getChecksumAddress } from "starknet";
7-
8-
export function useTokens(): TokensContextValue {
9-
const context = useContext(TokensContext);
10-
if (!context) {
11-
throw new Error("useTokens must be used within a TokensProvider");
12-
}
13-
14-
return context;
15-
}
16-
17-
export function useToken(address: string) {
18-
const { tokens, isLoading, error } = useTokens();
19-
const token = tokens[getChecksumAddress(address)];
20-
return {
21-
token,
22-
isLoading,
23-
error,
24-
};
25-
}
26-
27-
export function useFeeToken() {
28-
const { feeToken, isLoading, error } = useTokens();
29-
return {
30-
token: feeToken,
31-
isLoading,
32-
error,
33-
};
34-
}
35-
361
export function formatBalance(
372
amount: bigint,
383
decimals = 18,

packages/utils/src/context/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./posthog";
2+
export * from "./tokens";

packages/keychain/src/components/provider/tokens.tsx packages/utils/src/context/tokens.tsx

+19-17
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ import {
66
useEffect,
77
useCallback,
88
} from "react";
9-
import { useConnection } from "@/hooks/connection";
10-
import { ERC20 as ERC20Contract } from "@cartridge/utils";
9+
import { ERC20Contract } from "@cartridge/utils";
1110
import {
1211
Price,
1312
TokenPair,
1413
usePriceByAddressesQuery,
1514
} from "@cartridge/utils/api/cartridge";
1615
import { useQuery } from "react-query";
17-
import { getChecksumAddress } from "starknet";
16+
import { getChecksumAddress, Provider } from "starknet";
1817

1918
const DEFAULT_TOKENS = [
2019
{
@@ -68,27 +67,30 @@ export interface TokensContextValue {
6867
export const TokensContext = createContext<TokensContextValue>({
6968
tokens: {},
7069
isLoading: false,
71-
registerPair: () => {},
70+
registerPair: () => { },
7271
});
7372

7473
interface TokensProviderProps extends PropsWithChildren {
7574
tokens?: ERC20Metadata[];
7675
refetchInterval?: number;
7776
feeToken?: string;
77+
provider?: Provider;
78+
address?: string;
7879
}
7980

8081
export function TokensProvider({
8182
children,
8283
tokens: tokensArg = DEFAULT_TOKENS,
8384
feeToken = DEFAULT_FEE_TOKEN,
8485
refetchInterval = 30000,
86+
provider,
87+
address,
8588
}: TokensProviderProps) {
86-
const { controller } = useConnection();
8789
const [tokens, setTokens] = useState<Record<string, ERC20>>({});
8890
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
8991

9092
useEffect(() => {
91-
if (!controller) {
93+
if (!provider || !address) {
9294
return;
9395
}
9496

@@ -104,7 +106,7 @@ export function TokensProvider({
104106
const normalizedAddress = getChecksumAddress(address);
105107
const contract = new ERC20Contract({
106108
address: normalizedAddress,
107-
provider: controller.provider,
109+
provider,
108110
});
109111

110112
acc[normalizedAddress] = {
@@ -126,7 +128,7 @@ export function TokensProvider({
126128
Object.keys(initialTokens).forEach(async (address) => {
127129
try {
128130
const balance = await initialTokens[address].contract.balanceOf(
129-
controller.address(),
131+
address,
130132
);
131133

132134
setTokens((prev) => ({
@@ -140,17 +142,17 @@ export function TokensProvider({
140142
console.error("Error getting balance for:", address, error);
141143
}
142144
});
143-
}, [controller, tokensArg]);
145+
}, [address, tokensArg, provider]);
144146

145147
const { error: balanceError, isLoading: isLoadingBalances } = useQuery(
146-
["token-balances", controller?.address(), Object.keys(tokens)],
148+
["token-balances", address, Object.keys(tokens)],
147149
async () => {
148-
if (!controller) return;
150+
if (!address) return;
149151

150152
const updatedTokens = { ...tokens };
151153
await Promise.all(
152154
Object.values(updatedTokens).map(async (token) => {
153-
const balance = await token.contract.balanceOf(controller.address());
155+
const balance = await token.contract.balanceOf(address);
154156
updatedTokens[token.address] = {
155157
...token,
156158
balance,
@@ -164,7 +166,7 @@ export function TokensProvider({
164166
}
165167
},
166168
{
167-
enabled: !!controller && Object.keys(tokens).length > 0,
169+
enabled: !!address && Object.keys(tokens).length > 0,
168170
refetchInterval,
169171
retry: false,
170172
},
@@ -202,19 +204,19 @@ export function TokensProvider({
202204

203205
const registerPair = useCallback(
204206
async (address: string) => {
205-
if (!controller) return;
207+
if (!provider) return;
206208

207209
const normalizedAddress = getChecksumAddress(address);
208210
if (tokens[normalizedAddress]) return;
209211

210212
const newTokens = { ...tokens };
211213
const contract = new ERC20Contract({
212214
address: normalizedAddress,
213-
provider: controller.provider,
215+
provider,
214216
});
215217

216218
try {
217-
const balance = await contract.balanceOf(controller.address());
219+
const balance = await contract.balanceOf(address);
218220
await contract.init();
219221
const metadata = contract.metadata();
220222

@@ -233,7 +235,7 @@ export function TokensProvider({
233235
console.error(`Failed to load token ${normalizedAddress}:`, error);
234236
}
235237
},
236-
[controller, tokens],
238+
[address, tokens, provider],
237239
);
238240

239241
const value = useMemo(

packages/utils/src/erc20.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ import {
88
uint256,
99
} from "starknet";
1010

11-
export type ERC20Metadata = {
11+
type ERC20Metadata = {
1212
name: string;
1313
logoUrl?: string;
1414
symbol: string;
1515
decimals: number;
1616
address: string;
17-
instance: ERC20;
1817
};
1918

2019
export const ETH_CONTRACT_ADDRESS = getChecksumAddress(
@@ -24,7 +23,7 @@ export const STRK_CONTRACT_ADDRESS = getChecksumAddress(
2423
"0x04718f5a0Fc34cC1AF16A1cdee98fFB20C31f5cD61D6Ab07201858f4287c938D",
2524
);
2625

27-
export class ERC20 {
26+
export class ERC20Contract {
2827
private address: string;
2928
private logoUrl?: string;
3029
private provider: Provider;
@@ -77,7 +76,6 @@ export class ERC20 {
7776
symbol: this.symbol,
7877
decimals: this.decimals,
7978
logoUrl: this.logoUrl,
80-
instance: this,
8179
};
8280
}
8381

packages/utils/src/hooks/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from "./api";
22
export * from "./balance";
33
export * from "./countervalue";
44
export * from "./posthog";
5+
export * from "./tokens";

packages/utils/src/hooks/tokens.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useContext } from "react";
2+
import { TokensContext, TokensContextValue } from "../context/tokens";
3+
import { getChecksumAddress } from "starknet";
4+
5+
export function useTokens(): TokensContextValue {
6+
const context = useContext(TokensContext);
7+
if (!context) {
8+
throw new Error("useTokens must be used within a TokensProvider");
9+
}
10+
11+
return context;
12+
}
13+
14+
export function useToken(address: string) {
15+
const { tokens, isLoading, error } = useTokens();
16+
const token = tokens[getChecksumAddress(address)];
17+
return {
18+
token,
19+
isLoading,
20+
error,
21+
};
22+
}
23+
24+
export function useFeeToken() {
25+
const { feeToken, isLoading, error } = useTokens();
26+
return {
27+
token: feeToken,
28+
isLoading,
29+
error,
30+
};
31+
}

0 commit comments

Comments
 (0)