graz-sh / graz Goto Github PK
View Code? Open in Web Editor NEWReact hooks for Cosmos 🪐
Home Page: https://graz.sh/
License: MIT License
React hooks for Cosmos 🪐
Home Page: https://graz.sh/
License: MIT License
It's related with a wallet integration question.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
I've been working on add vectis extension into graz library but I found some limitations.
First limitation is wallet interface only is compatible with the Keplr one.
https://github.com/strangelove-ventures/graz/blob/dev/packages/graz/src/types/wallet.ts#L26
Second limitation is about adaptersI don't see any documentation or code where they are being used. I guess these adapters solve the interface issue.
A clear and concise description of what you want to happen.
It would be great instead of define the wallet inside graz library, receive the wallets externally (using these adapters) and fit to the interface.
A clear and concise description of any alternative solutions or features you've considered.
...
Add any other context or screenshots about the feature request here.
Integration commit: nymlab@48d3a55
Any kind of help would be really useful to complete the integration.
graz cannot connect to multiple chains, it switched the connection
graz can connect to multiple chains at the same time
If we already suggest chain and connect and then remove the chain from keplr it will return a runtime error that client can't handle
How to reproduce:
We need to inform our user, that leap wallet not support suggest chain, in jsdoc and website documentation
Example:
from
export const useBalances = (bech32Address?: string): UseQueryResult<Coin[]> => {
const { data: account } = useAccount();
const address = bech32Address || account?.bech32Address;
const queryKey = ["USE_BALANCES", address] as const;
const query = useQuery(queryKey, ({ queryKey: [, _address] }) => getBalances(_address!), {
enabled: Boolean(address),
refetchOnMount: false,
refetchOnReconnect: true,
refetchOnWindowFocus: false,
});
return query;
};
to
export const useBalances = (bech32Address?: string): UseQueryResult<Coin[]> => {
const { signingClients } = useGrazSessionStore.getState();
const { data: account } = useAccount();
const address = bech32Address || account?.bech32Address;
const queryKey = ["USE_BALANCES", address] as const;
const query = useQuery(queryKey, ({ queryKey: [, _address] }) => getBalances(_address!), {
enabled: Boolean(address) || Boolean(signingClients),
refetchOnMount: false,
refetchOnReconnect: true,
refetchOnWindowFocus: false,
});
return query;
};
Would be nice to also include a non signing cosmwasm client (CosmwasmClient) that can be used without connecting a wallet e.g. to purely load data before connecting. This allows dApps to have a read only view prior to wallet connection.
Add a documentation for how to add a new wallet integration to graz package
I try to implement this, but I got this typescript error
const { sendTokensAsync, isLoading } = useSendTokens({
onError: (err, args: SendTokensArgs) => {
return toast({
status: "error",
title: "Send token fail",
description: `Failed send token to ${args.recipientAddress}`,
});
},
});
Originally posted by @joshuanatanielnm in #43 (comment)
Add graz example inside docs site
Currently thinking what if graz does not have any query client provider and let the user define it?
Some of our users needs to access the store since chrome extensions can't use react stuff in service worker
Upon duplicating the code in the example project, graz does not auto-open the Keplr or Leap mobile app as expected, via WalletConnect, upon calling SigningCosmWasmClient.execute
.
In the case of Keplr, the Chrome Android browser does not toggle into the mobile Keplr app. I and others who have tested must manually toggle into Keplr to approve the pending transaction.
When selecting Leap + WalletConnect on Android, the web app just opens up Leap in the Google Play store instead of going into the actual Leap app to approve the connection.
I can see that the mobile browser performs what looks like 2 requests in the background, as the loading bar seems to activate, but the app just stays on the current page while the Keplr app fails to launch.
We're running a Next.js v12 app. Nothing special. To reproduce, just do the boilerplate graz setup and try executing a contract via Keplr+WalletConnect or Leap.
Would like to be able to connect an XDEFI wallet
add queryOptions
to every hook parameter and spread it to the useQuery
options
https://docs.ibc.domains/ibc_domains_sdk.html
Add IBC domains hooks
useIbcDomains
Add support for signArbitrary
method that follows cosmos ADR36
A method to sign arbitrary data similar to cosmos-kit
https://github.com/cosmology-tech/cosmos-kit/blob/162e087be99508a4bd560f7ffdd45d11a51a4801/wallets/keplr-extension/src/extension/client.ts#L148
I've tried to get access to the client/signer directly but can't find a way to get access to similar method.
TLDR: I cannot instantiate a contract using useInstantiateContract
or useSigningClients
because it keeps calling cosmWasm.instantiate
with auto gas and no gas price somewhere in the back, disregarding my configuration and client options.
Related issue: #7
I'm getting the following error regarding gas price when trying to instantiate a contract.
ContractCreate.tsx:23 Error: Gas price must be set in the client options when auto gas is used.
at assertDefined (assert.ts:10:11)
at _SigningCosmWasmClient.signAndBroadcast (signingcosmwasmclient.ts:548:7)
at _SigningCosmWasmClient.instantiate (signingcosmwasmclient.ts:321:31)
at lt3 (index.mjs:1:28075)
at Object.mutationFn (index.mjs:1:41853)
at Object.fn (mutation.ts:179:31)
at run3 (retryer.ts:147:31)
at createRetryer (retryer.ts:204:5)
at executeMutation (mutation.ts:174:22)
at Mutation.execute (mutation.ts:216:26)
This is strange, since gas price was already configured in the chain:
export const customChains = defineChains({
chainName: {
gas: {
price: "1000000",
denom: "udenom",
},
...
});
configureGraz({
defaultChain: customChains.chainName,
});
Here's what I tried with useInstantiateContract:
export default function ContractCreate() {
const { instantiateContract } = useInstantiateContract({
codeId: 5,
onSuccess: ({ contractAddress }) => console.log("Address: ", contractAddress),
});
const handleClick = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const label = (event.currentTarget.elements.namedItem("label") as HTMLInputElement).value;
const program = (event.currentTarget.elements.namedItem("program") as HTMLTextAreaElement).value;
const msg = { program: btoa(program) };
const options = { admin: ADMIN_ADDRESS };
instantiateContract({ msg, options, label, });
};
return (
<div>
<h3>Create Contract</h3>
<form onSubmit={handleClick}>
<label htmlFor="program">program</label>
<textarea id="program" />
<label htmlFor="label">label</label>
<input id="label" type="text" />
<button type="submit">Create Contract</button>
</form>
</div>
);
}
I then tried with cosmWasm from useSigningClients:
export default function ContractCreate() {
const { signer } = useOfflineSigners();
const signingClientsArgs = {
cosmWasmSignerOptions: {
gasPrice: GasPrice.fromString("0.012udenom"),
},
rpc: "https://api.somewhere.network:443/rpc",
offlineSignerAuto: signer!,
};
const { data } = useSigningClients(signer ? signingClientsArgs : undefined);
const { cosmWasm } = data || {};
const handleClick = (event: React.FormEvent<HTMLFormElement>) => {
if (!cosmWasm) return;
event.preventDefault();
const label = (event.currentTarget.elements.namedItem("label") as HTMLInputElement).value;
const program = (event.currentTarget.elements.namedItem("program") as HTMLTextAreaElement).value;
const msg = { program: btoa(program) };
const options = { admin: ADMIN_ADDRESS };
cosmWasm.instantiate(ADMIN_ADDRESS, 5, msg, label, 1000000, options);
};
return (
<div>
<h3>Create Contract</h3>
<form onSubmit={handleClick}>
<label htmlFor="program">program</label>
<textarea id="program" />
<label htmlFor="label">label</label>
<input id="label" type="text" />
<button type="submit">Create Contract</button>
</form>
</div>
);
}
and getting the same error
assert.ts:10 Uncaught (in promise) Error: Gas price must be set in the client options when auto gas is used.
at assertDefined (assert.ts:10:11)
at _SigningCosmWasmClient.signAndBroadcast (signingcosmwasmclient.ts:548:7)
at _SigningCosmWasmClient.instantiate (signingcosmwasmclient.ts:321:31)
at handleClick (LawStoneCreate.tsx:61:14)
at HTMLUnknownElement.callCallback2 (react-dom.development.js:4164:14)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:16)
at invokeGuardedCallback (react-dom.development.js:4277:31)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:25)
at executeDispatch (react-dom.development.js:9041:3)
at processDispatchQueueItemsInOrder (react-dom.development.js:9073:7)
Note that I also called cosmWasm.instantiate
with fee 1000000
instead of auto
, yet still get the same error
add walletType:WalletType
to onSuccess
on useConnect
and useConnectAndSuggest
return
When you have leap wallet extension installed but not keplr, useCheckWallet(WalletType.KEPLR)
return true and getWallet(WalletType.KEPLR)
works (and should not) using Leap so it opens Leap modal
Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
useCheckWallet(WalletType.KEPLR)
should return false and getWallet(WalletType.KEPLR)
should throw an error.
Please complete the following device information.
Desktop
hooks/useStakedBalances
, actions/getStakedBalances
naming is missleading because from the stargate
client is called getBalanceStaked
notice that our naming is balances
when it should be just balance
and it just returns one Coin
Create a migration guide documentation from cosmos kit to graz.
I followed the tutorial setup using cosmos-frontend and graz, but on clicking "connect wallet" it gives the said error.
I wish to connect with the cosmos public testnet (theta) instead.
hey, I have an issue: when I use imports from graz/dist is doesn't work. I've checked every lib but I think the problem is here. Also when I'm trying to build project on production (you can see https://gutenberg.tools/) the variable isConnected doesn't work on prod but works on localhost (you can try to clone the repo https://github.com/diekuche/gutenberg and run it). I guess the problem is in node modules that I can't import in components via graz.
A clear and concise description of what the bug is.
window.keplr is not initialised
...
Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
...
If applicable, add screenshots to help explain your problem.
...
Please complete the following device information.
Desktop
Smartphone
Add any other context about the problem here.
...
Just curious: a) where the name comes from and b) whether there's appetite for changing it, or considering alternatives.
These hooks could really lower the barrier to entry for building front-end stuff in Cosmos, but the name isn't doing it any favours re: discoverability. Even prefixing react-
onto the library name per React conventions could be helpful, maybe?? Nit-picky, but wanted to have the discussion!
The Keplr TX window (to approve or deny) of course opens a new window, this forces a state refresh and often leads to local state being overriden. It feels like this refresh is too oppressive when compared with other setups.
To reproduce:
There are some changes that haven't documented
Currently when we connect, _reconnect
set to true
, We need to make this optionable.
Possible solutions:
autoReconnect
params inside connect
autoReconnect
to configureGraz
and GrazProvider
optionsAdd switch light/dark mode in starter template
Package throws the following error when trying to import on a vite react project:
_stream_readable.js:48 Uncaught ReferenceError: global is not defined
at node_modules/readable-stream/lib/_stream_readable.js (_stream_readable.js:48:21)
at __require2 (chunk-Q7D65HC4.js?v=6a1b80ec:18:50)
at node_modules/readable-stream/readable-browser.js (readable-browser.js:1:28)
at __require2 (chunk-Q7D65HC4.js?v=6a1b80ec:18:50)
at node_modules/hash-base/index.js (index.js:3:17)
at __require2 (chunk-Q7D65HC4.js?v=6a1b80ec:18:50)
at node_modules/md5.js/index.js (index.js:3:16)
at __require2 (chunk-Q7D65HC4.js?v=6a1b80ec:18:50)
at node_modules/create-hash/browser.js (browser.js:3:11)
at __require2 (chunk-Q7D65HC4.js?v=6a1b80ec:18:50)
node_modules/readable-stream/lib/_stream_readable.js @ _stream_readable.js:48
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/readable-stream/readable-browser.js @ readable-browser.js:1
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/hash-base/index.js @ index.js:3
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/md5.js/index.js @ index.js:3
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/create-hash/browser.js @ browser.js:3
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/bip39/src/index.js @ index.js:3
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@cosmjs/launchpad/node_modules/@cosmjs/crypto/build/bip39.js @ bip39.ts:2
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@cosmjs/launchpad/node_modules/@cosmjs/crypto/build/index.js @ index.ts:1
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@cosmjs/launchpad/build/address.js @ address.ts:1
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@cosmjs/launchpad/build/index.js @ index.ts:4
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@keplr-wallet/cosmos/build/adr-36/amino.js @ amino.ts:1
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@keplr-wallet/cosmos/build/adr-36/index.js @ index.ts:1
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@keplr-wallet/cosmos/build/stargate/wrapper/index.js @ index.ts:4
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@keplr-wallet/cosmos/build/stargate/index.js @ index.ts:3
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
node_modules/@keplr-wallet/cosmos/build/index.js @ index.ts:5
__require2 @ chunk-Q7D65HC4.js?v=6a1b80ec:18
(anonymous) @ index.mjs:1
Steps to reproduce the behavior:
No error
Please complete the following device information.
Desktop
Vite might not have a polyfier/babel transfomer for global
.
Do this after #70
Whenever you connect a wallet (e.g. via Keplr), Graz is clearly creating an unnecessary number of RPC clients internally, probably via CosmWasmClient.connect
. If you look at network activity in the browser, you'll notice at least 4 concurrent requests to the RPC provider, targeting its "status" endpoint, which is what the CosmWasmClient.connect
method automatically does each time it is called. This is not good. Depending on the RPC provider, this can trigger an HTTP 429 rate limit error. Instead, you guys really ought to manage a singleton client and make use of the batch RPC client available in cosmjs.
...
Steps to reproduce the behavior:
There should be only one request to the "status" method globally.
A clear and concise description of what you expected to happen.
...
I succeed to use Leap Metamask snap with Cosmos Hub, Osmosis and other mainnet chains, but if I use one from a testnet, it did not work. I got "Invalid chainId error".
Steps to reproduce the behavior:
_app.tsx
fileChainInfo
is generated (yarn graz generate -g
), import testnetChains
from "graz/chains"
grazOptions={{ defaultChain: testnetChains.okp4testnet }}
in GrazProvider
Expect Connection with Leap Metamask Snap to work with any testnet as well as with any mainnet.
Try with any available network from testnetChains
It's common for React-based Dapps to want to interact with CosmWasm smart contracts on chains that support them. It would be great to manage these interactions—queries and mutations—with graz.
A set of hooks:
useInstantiateContract
—a mutator to instantiate a smart contract with a message provided by the caller.useExecuteContract
—a mutator to execute a smart contract, passing it a message provided by the caller.useContractQueryRaw
and useContractQuery
(not yet sketched)—Hooks to query the state stored within a smart contract.Ideally, these hooks use react-query
to give users caching support, like the other hooks present in graz.
In the MVP we built of our Dapp, we've used cosmjs directly to query and transact with CosmWasm smart contracts. This, unfortunately, required us to use another state manager (Redux) to avoid constant refetching of data. We also wound up re-creating many of the abstractions provided by react-query
and graz
to provider the developer experience we wanted.
As you can see, we've already sketched out potential implementations for execute
and instantiate
, but we want to make sure this is a community effort and in line with the thinking/spirit of the graz project, so we wanted to open discussion here to make sure we're all on the same page. Big fan of what you're doing with graz, and we plan on using it extensively in our dapp(s).
Having a contribution guide would help new contributors and existing maintainers to keep tabs on how to maintain this project.
Creating a CONTRIBUTING.md
file on the root project which describes the contribution guide.
-
-
sup bros! we have another issue about connecting with graz.
A clear and concise description of what the bug is.
...
Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
...
If applicable, add screenshots to help explain your problem.
...
Please complete the following device information.
macOS, safari, chrome,brave
Desktop
Smartphone (haven't tried)
Add any other context about the problem here.
...
/example/vite
/example/default
package.json
and pnpm-workspace.yaml
update workspace to example/*
Currently We are not exposing auto reconnect. We already have it on "store", We can expose it through configureGraz
or GrazProvider
It currently uses the signer from keplr.getOfflineSigner(chainId)
when it should use keplr.getOfflineSignerAuto(chainId)
, maybe this should be specified by a flag as I am unsure if it breaks other bindings?
when i use graz cli -g to generate list of chains there's an error in compiler about 8-ball chain
A clear and concise description of what the bug is.
when I change 8ball to eightball on localhost, I guess everything works
...
Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
...
If applicable, add screenshots to help explain your problem.
...
Please complete the following device information.
Desktop
Smartphone
Add any other context about the problem here.
...
When using "auto" gas with the cosmwasm client it errors saying the gas prices must be set in the client config if using auto.
Error: Gas price must be set in the client options when auto gas is used.
Steps to reproduce:
try {
await client?.execute(
account.bech32Address || '',
config.CONTRACT_ADDRESS,
{ delete_template: { id } },
'auto'
);
} catch (err) {
console.log(err);
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.