Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add use send tokens and use send ibc tokens hook #38

Merged
merged 6 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions packages/graz/src/actions/account.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { SigningCosmWasmClientOptions } from "@cosmjs/cosmwasm-stargate";
import type { Coin } from "@cosmjs/proto-signing";
import { GasPrice } from "@cosmjs/stargate";
import type { Key } from "@keplr-wallet/types";

Expand Down Expand Up @@ -86,31 +85,6 @@ export async function disconnect(clearRecentChain = false): Promise<void> {
return Promise.resolve();
}

export async function getBalances(bech32Address: string): Promise<Coin[]> {
const { activeChain, signingClients } = useGrazStore.getState();

if (!activeChain || !signingClients) {
throw new Error("No connected account detected");
}

const { defaultSigningClient } = useGrazStore.getState();
const balances = await Promise.all(
activeChain.currencies.map(async (item) => {
return signingClients[defaultSigningClient].getBalance(bech32Address, item.coinMinimalDenom);
}),
);

return balances;
}

export async function getStakedBalances(bech32Address: string): Promise<Coin | null> {
const { clients } = useGrazStore.getState();
if (!clients?.stargate) {
throw new Error("Stargate client is not ready");
}
return clients.stargate.getBalanceStaked(bech32Address);
}

export function reconnect(): void {
const { activeChain } = useGrazStore.getState();
if (activeChain) void connect(activeChain);
Expand Down
100 changes: 100 additions & 0 deletions packages/graz/src/actions/methods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { Coin } from "@cosmjs/proto-signing";
import type { DeliverTxResponse, StdFee } from "@cosmjs/stargate";
import type { Height } from "cosmjs-types/ibc/core/client/v1/client";

import { useGrazStore } from "../store";

export async function getBalances(bech32Address: string): Promise<Coin[]> {
const { activeChain, signingClients } = useGrazStore.getState();

if (!activeChain || !signingClients) {
throw new Error("No connected account detected");
}

const { defaultSigningClient } = useGrazStore.getState();
const balances = await Promise.all(
activeChain.currencies.map(async (item) => {
return signingClients[defaultSigningClient].getBalance(bech32Address, item.coinMinimalDenom);
}),
);

return balances;
}

export async function getStakedBalances(bech32Address: string): Promise<Coin | null> {
const { clients } = useGrazStore.getState();
if (!clients?.stargate) {
throw new Error("Stargate client is not ready");
}
return clients.stargate.getBalanceStaked(bech32Address);
}

// https://cosmos.github.io/cosmjs/latest/stargate/classes/SigningStargateClient.html#sendTokens
export interface SendTokensArgs {
senderAddress?: string;
recipientAddress: string;
amount: Coin[];
fee: number | StdFee | "auto";
memo?: string;
}

export async function sendTokens({
senderAddress,
recipientAddress,
amount,
fee,
memo,
}: SendTokensArgs): Promise<DeliverTxResponse> {
const { signingClients, defaultSigningClient } = useGrazStore.getState();
if (!signingClients) {
throw new Error("No connected account detected");
}
if (!senderAddress) {
throw new Error("senderAddress is not defined");
}
return signingClients[defaultSigningClient].sendTokens(senderAddress, recipientAddress, amount, fee, memo);
}

// https://cosmos.github.io/cosmjs/latest/stargate/classes/SigningStargateClient.html#sendIbcTokens
export interface SendIbcTokensArgs {
senderAddress?: string;
recipientAddress: string;
transferAmount: Coin;
sourcePort: string;
sourceChannel: string;
timeoutHeight?: Height;
timeoutTimestamp?: number;
fee: number | StdFee | "auto";
memo: string;
}

export async function sendIbcTokens({
senderAddress,
recipientAddress,
transferAmount,
sourcePort,
sourceChannel,
timeoutHeight,
timeoutTimestamp,
fee,
memo,
}: SendIbcTokensArgs) {
const { signingClients } = useGrazStore.getState();
if (!signingClients?.stargate) {
throw new Error("Stargate signing client is not ready");
}
if (!senderAddress) {
throw new Error("senderAddress is not defined");
}
return signingClients.stargate.sendIbcTokens(
senderAddress,
recipientAddress,
transferAmount,
sourcePort,
sourceChannel,
timeoutHeight,
timeoutTimestamp,
fee,
memo,
);
}
3 changes: 2 additions & 1 deletion packages/graz/src/hooks/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { useEffect } from "react";
import shallow from "zustand/shallow";

import type { ConnectArgs } from "../actions/account";
import { connect, disconnect, getBalances, getStakedBalances, reconnect } from "../actions/account";
import { connect, disconnect, reconnect } from "../actions/account";
import { getBalances, getStakedBalances } from "../actions/methods";
import { useGrazStore } from "../store";
import type { MutationEventArgs } from "../types/hooks";
import { useCheckWallet } from "./wallet";
Expand Down
88 changes: 88 additions & 0 deletions packages/graz/src/hooks/methods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useMutation } from "@tanstack/react-query";

import type { SendIbcTokensArgs, SendTokensArgs } from "../actions/methods";
import { sendIbcTokens, sendTokens } from "../actions/methods";
import type { MutationEventArgs } from "../types/hooks";
import { useAccount } from "./account";

/**
* graz mutation hook to send tokens. Note: if `senderAddress` undefined, it will use current connected account address.
*
* @example
* ```ts
* import { useSendTokens } from "graz";
*
* // basic example
* const { sendTokens } = useSendTokens();
*
* sendTokens({
* // ...args
* })
* ```
*
* @see {@link sendTokens}
*/
export function useSendTokens({ onError, onLoading, onSuccess }: MutationEventArgs = {}) {
const { data: account } = useAccount();
const accountAddress = account?.bech32Address;

const queryKey = ["USE_SEND_TOKENS", onError, onLoading, onSuccess, accountAddress];
const mutation = useMutation(
queryKey,
(args: SendTokensArgs) => sendTokens({ senderAddress: accountAddress, ...args }),
{
onError: (err, txResponse) => Promise.resolve(onError?.(err, txResponse)),
onMutate: onLoading,
onSuccess: (txResponse) => Promise.resolve(onSuccess?.(txResponse)),
},
);

return {
error: mutation.error,
isLoading: mutation.isLoading,
isSuccess: mutation.isSuccess,
sendTokens: mutation.mutate,
sendTokensAsync: mutation.mutateAsync,
status: mutation.status,
};
}
/**
* graz mutation hook to send IBC tokens. Note: if `senderAddress` undefined, it will use current connected account address.
*
*
* @example
* ```ts
* import { useSendIbcTokens } from "graz";
*
* // basic example
* const { sendIbcTokens } = useSendIbcTokens();
*
* sendIbcTokens({
* // ...args
* })
* ```
*/
export function useSendIbcTokens({ onError, onLoading, onSuccess }: MutationEventArgs = {}) {
const { data: account } = useAccount();
const accountAddress = account?.bech32Address;

const queryKey = ["USE_SEND_IBC_TOKENS", onError, onLoading, onSuccess, accountAddress];
const mutation = useMutation(
queryKey,
(args: SendIbcTokensArgs) => sendIbcTokens({ senderAddress: accountAddress, ...args }),
{
onError: (err, txResponse) => Promise.resolve(onError?.(err, txResponse)),
onMutate: onLoading,
onSuccess: (txResponse) => Promise.resolve(onSuccess?.(txResponse)),
},
);

return {
error: mutation.error,
isLoading: mutation.isLoading,
isSuccess: mutation.isSuccess,
sendIbcTokens: mutation.mutate,
sendIbcTokensAsync: mutation.mutateAsync,
status: mutation.status,
};
}
1 change: 1 addition & 0 deletions packages/graz/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from "./chains";
export * from "./hooks/account";
export * from "./hooks/chains";
export * from "./hooks/clients";
export * from "./hooks/methods";
export * from "./hooks/wallet";
export * from "./provider";
export * from "./provider/events";
Expand Down