Skip to content

Commit

Permalink
rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
jrwbabylonlab committed Dec 3, 2024
1 parent 25ae42a commit 42ffac9
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 101 deletions.
2 changes: 2 additions & 0 deletions src/app/common/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const BBN_RPC_URL = "https://rpc-dapp.devnet.babylonlabs.io";
export const BBN_LCD_URL = "https://lcd-dapp.devnet.babylonlabs.io";
16 changes: 5 additions & 11 deletions src/app/components/PersonalBalance/PersonalBalance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useState } from "react";

import { useBTCWallet } from "@/app/context/wallet/BTCWalletProvider";
import { useCosmosWallet } from "@/app/context/wallet/CosmosWalletProvider";
import { useBbnQueryClient } from "@/app/hooks/client/query/useBbnQueryClient";
import { useRewardsService } from "@/app/hooks/services/useRewardsService";
import { ubbnToBbn } from "@/utils/bbn";
import { satoshiToBtc } from "@/utils/btc";
Expand All @@ -11,12 +12,9 @@ import { StatItem } from "../Stats/StatItem";

export function PersonalBalance() {
const { getBalance: getBTCBalance, connected: btcConnected } = useBTCWallet();
const {
signingStargateClient,
connected: cosmosConnected,
bech32Address,
} = useCosmosWallet();
const { connected: cosmosConnected } = useCosmosWallet();

const { getBalance } = useBbnQueryClient();
const { getRewards } = useRewardsService();
const [rewards, setRewards] = useState<number>();
const [btcBalance, setBTCBalance] = useState<number>();
Expand All @@ -33,17 +31,13 @@ export function PersonalBalance() {
setBTCBalance(balance);
};
const fetchCosmosBalance = async () => {
const balance = await signingStargateClient?.getBalance(
bech32Address,
"ubbn",
);
const bbnAmount = Number(balance?.amount ?? 0);
const bbnAmount = await getBalance();
setCosmosBalance(bbnAmount);
};
fetchRewards();
fetchBTCBalance();
fetchCosmosBalance();
}, [getRewards, getBTCBalance, signingStargateClient, bech32Address]);
}, [getRewards, getBTCBalance, getBalance]);

if (!btcConnected || !cosmosConnected) {
return null;
Expand Down
6 changes: 3 additions & 3 deletions src/app/context/wallet/CosmosWalletProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ interface CosmosWalletContextProps {
const CosmosWalletContext = createContext<CosmosWalletContextProps>({
bech32Address: "",
connected: false,
disconnect: () => { },
open: () => { },
disconnect: () => {},
open: () => {},
signingStargateClient: undefined,
});

Expand All @@ -46,7 +46,7 @@ export const CosmosWalletProvider = ({ children }: PropsWithChildren) => {
>();

const { showError, captureError } = useError();
const { open = () => { }, connected } = useWalletConnect();
const { open = () => {}, connected } = useWalletConnect();
const bbnConnector = useChainConnector("BBN");

const cosmosDisconnect = useCallback(() => {
Expand Down
44 changes: 0 additions & 44 deletions src/app/hooks/client/query/useBbnQuery.ts

This file was deleted.

76 changes: 76 additions & 0 deletions src/app/hooks/client/query/useBbnQueryClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { incentivequery } from "@babylonlabs-io/babylon-proto-ts";
import {
QueryClient,
createProtobufRpcClient,
setupBankExtension,
} from "@cosmjs/stargate";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import { useCallback, useEffect, useState } from "react";

import { BBN_RPC_URL } from "@/app/common/rpc";
import { useCosmosWallet } from "@/app/context/wallet/CosmosWalletProvider";

/**
* Query service for Babylon which contains all the queries for
* interacting with Babylon RPC nodes
*/
export const useBbnQueryClient = () => {
const { bech32Address } = useCosmosWallet();
const [queryClient, setQueryClient] = useState<QueryClient>();

useEffect(() => {
const initQueryClient = async () => {
const tmClient = await Tendermint34Client.connect(BBN_RPC_URL);
const queryClient = QueryClient.withExtensions(tmClient);
setQueryClient(queryClient);
};

initQueryClient();
}, []);

/**
* Gets the rewards from the user's account.
* @returns {Promise<Object>} - The rewards from the user's account.
*/
const getRewards = useCallback(async (): Promise<
incentivequery.QueryRewardGaugesResponse | undefined
> => {
if (!queryClient || !bech32Address) {
return undefined;
}
const { incentive } = setupIncentiveExtension(queryClient);

const req: incentivequery.QueryRewardGaugesRequest =
incentivequery.QueryRewardGaugesRequest.fromPartial({
address: bech32Address,
});

return incentive.RewardGauges(req);
}, [queryClient, bech32Address]);

const getBalance = useCallback(async (): Promise<number> => {
if (!queryClient || !bech32Address) {
return 0;
}

const { bank } = setupBankExtension(queryClient);
const balance = await bank.balance(bech32Address, "ubbn");
return Number(balance?.amount ?? 0);
}, [queryClient, bech32Address]);

return {
getRewards,
getBalance,
};
};

// Extend the QueryClient with the Incentive module
const setupIncentiveExtension = (
base: QueryClient,
): {
incentive: incentivequery.QueryClientImpl;
} => {
const rpc = createProtobufRpcClient(base);
const incentiveQueryClient = new incentivequery.QueryClientImpl(rpc);
return { incentive: incentiveQueryClient };
};
44 changes: 7 additions & 37 deletions src/app/hooks/client/query/useBbnTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback } from "react";

import { useCosmosWallet } from "@/app/context/wallet/CosmosWalletProvider";
import { useSigningStargateClient } from "./useSigningStargateClient";

export interface BbnGasFee {
amount: { denom: string; amount: string }[];
Expand All @@ -12,7 +12,7 @@ export interface BbnGasFee {
* interacting with Babylon RPC nodes
*/
export const useBbnTransaction = () => {
const { signingStargateClient, bech32Address } = useCosmosWallet();
const { simulate, signAndBroadcast } = useSigningStargateClient();

/**
* Estimates the gas fee for a transaction.
Expand All @@ -21,16 +21,7 @@ export const useBbnTransaction = () => {
*/
const estimateBbnGasFee = useCallback(
async <T>(msg: { typeUrl: string; value: T }): Promise<BbnGasFee> => {
if (!signingStargateClient || !bech32Address) {
throw new Error("Wallet not connected");
}

// estimate gas
const gasEstimate = await signingStargateClient.simulate(
bech32Address,
[msg],
`estimate transaction fee for ${msg.typeUrl}`,
);
const gasEstimate = await simulate(msg);
// TODO: The gas calculation need to be improved
// https://github.com/babylonlabs-io/simple-staking/issues/320
const gasWanted = Math.ceil(gasEstimate * 1.5);
Expand All @@ -39,7 +30,7 @@ export const useBbnTransaction = () => {
gas: gasWanted.toString(),
};
},
[signingStargateClient, bech32Address],
[simulate],
);

/**
Expand All @@ -48,34 +39,13 @@ export const useBbnTransaction = () => {
* @returns {Promise<Object>} - The transaction hash and gas used.
*/
const sendBbnTx = useCallback(
async <T extends object>(msg: {
typeUrl: string;
value: T;
}): Promise<{ txHash: string; gasUsed: string }> => {
if (!signingStargateClient || !bech32Address) {
throw new Error("Wallet not connected");
}

async <T extends object>(msg: { typeUrl: string; value: T }) => {
// estimate gas
const fee = await estimateBbnGasFee(msg);

// sign it
const res = await signingStargateClient.signAndBroadcast(
bech32Address,
[msg],
fee,
);
if (res.code !== 0) {
throw new Error(
`Failed to send ${msg.typeUrl} transaction, code: ${res.code}, txHash: ${res.transactionHash}`,
);
}
return {
txHash: res.transactionHash,
gasUsed: res.gasUsed.toString(),
};
await signAndBroadcast(msg, fee);
},
[signingStargateClient, bech32Address, estimateBbnGasFee],
[estimateBbnGasFee, signAndBroadcast],
);

return {
Expand Down
74 changes: 74 additions & 0 deletions src/app/hooks/client/query/useSigningStargateClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { StdFee } from "@cosmjs/stargate";
import { useCallback } from "react";

import { useCosmosWallet } from "@/app/context/wallet/CosmosWalletProvider";

/**
* Hook for signing and broadcasting transactions with the Cosmos wallet
*/
export const useSigningStargateClient = () => {
const { signingStargateClient, bech32Address } = useCosmosWallet();

/**
* Simulates a transaction to estimate the gas fee
* @param msg - The transaction message
* @returns The gas fee
*/
const simulate = useCallback(
<T>(msg: { typeUrl: string; value: T }): Promise<number> => {
if (!signingStargateClient || !bech32Address) {
throw new Error("Wallet not connected");
}

// estimate gas
return signingStargateClient.simulate(
bech32Address,
[msg],
`estimate transaction fee for ${msg.typeUrl}`,
);
},
[signingStargateClient, bech32Address],
);

/**
* Signs and broadcasts a transaction
* @param msg - The transaction message
* @param fee - The gas fee
* @returns The transaction hash and gas used
*/
const signAndBroadcast = useCallback(
async <T>(
msg: {
typeUrl: string;
value: T;
},
fee: StdFee,
): Promise<{
txHash: string;
gasUsed: string;
}> => {
if (!signingStargateClient || !bech32Address) {
throw new Error("Wallet not connected");
}

const res = await signingStargateClient.signAndBroadcast(
bech32Address,
[msg],
fee,
);

if (res.code !== 0) {
throw new Error(
`Failed to send ${msg.typeUrl} transaction, code: ${res.code}, txHash: ${res.transactionHash}`,
);
}
return {
txHash: res.transactionHash,
gasUsed: res.gasUsed.toString(),
};
},
[signingStargateClient, bech32Address],
);

return { simulate, signAndBroadcast };
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCallback } from "react";
import { useCosmosWallet } from "@/app/context/wallet/CosmosWalletProvider";
import { BBN_REGISTRY_TYPE_URLS } from "@/utils/wallet/bbnRegistry";

import { useBbnQuery } from "../client/query/useBbnQuery";
import { useBbnQueryClient } from "../client/query/useBbnQueryClient";
import { useBbnTransaction } from "../client/query/useBbnTransaction";

const REWARD_GAUGE_KEY_BTC_DELEGATION = "btc_delegation";
Expand All @@ -16,7 +16,7 @@ export const useRewardsService = () => {
signingStargateClient,
} = useCosmosWallet();

const { getRewards: getBbnRewards } = useBbnQuery();
const { getRewards: getBbnRewards } = useBbnQueryClient();
const { estimateBbnGasFee, sendBbnTx } = useBbnTransaction();

/**
Expand Down Expand Up @@ -72,8 +72,7 @@ export const useRewardsService = () => {

const msg = createWithdrawRewardMsg(bech32Address);

const { txHash } = await sendBbnTx(msg);
console.log("successfully claimed rewards with txHash", txHash);
await sendBbnTx(msg);
}, [bech32Address, signingStargateClient, sendBbnTx]);

return {
Expand Down
7 changes: 5 additions & 2 deletions src/config/wallet/babylon.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// Temporary solution until we have a stable chain registry

import { BBN_LCD_URL, BBN_RPC_URL } from "@/app/common/rpc";

// The values here shall match from https://rpc.devnet.babylonlabs.io/genesis?
export const bbnDevnet = {
chainId: "devnet-7",
chainName: "Babylon Devnet 7",
chainSymbolImageUrl:
"https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/bbn-dev/chain.png",
rpc: "https://rpc-dapp.devnet.babylonlabs.io",
rest: "https://lcd-dapp.devnet.babylonlabs.io",
rpc: BBN_RPC_URL,
rest: BBN_LCD_URL,
nodeProvider: {
name: "Babylonlabs",
email: "[email protected]",
Expand Down

0 comments on commit 42ffac9

Please sign in to comment.