Coder Social home page Coder Social logo

apibara / starknet-react Goto Github PK

View Code? Open in Web Editor NEW
327.0 6.0 121.0 12.15 MB

A collection of React providers and hooks for StarkNet

Home Page: https://starknet-react.com

License: MIT License

JavaScript 1.97% TypeScript 78.24% Nix 0.15% HTML 0.09% CSS 0.72% MDX 18.83%
starknet react ethereum l2 hooks react-hooks typescript

starknet-react's Introduction

Starknet React

@starknet-react/core Release Status MIT LICENSE

Starknet React is a collection of React hooks for Starknet. It is inspired by wagmi, powered by starknet.js.

Documentation

Documentation, including demos, is available online.

Getting Started

  1. Add @starknet-react/chains and @starknet-react/core to your dependencies.
pnpm add @starknet-react/chains @starknet-react/core

You also need to add get-starknet-core and starknet to your dependencies.

pnpm add get-starknet-core starknet
  1. Wrap your app with StarknetConfig
import { sepolia } from "@starknet-react/chains";
import {
  StarknetConfig,
  publicProvider,
  argent,
  braavos,
} from "@starknet-react/core";

function App() {
  const chains = [sepolia];
  const provider = publicProvider();
  const connectors = [braavos(), argent()];

  return (
    <StarknetConfig chains={chains} provider={provider} connectors={connectors}>
      <YourApp />
    </StarknetConfig>
  );
}
  1. Access the hooks from your components.
import { useAccount } from "@starknet-react/core";

function YourComponent() {
  const { address } = useAccount();

  return <div>gm {address}</div>;
}

License

This library is licensed under the MIT license.

starknet-react's People

Contributors

0xads avatar 0xchqrles avatar aliezsss4 avatar arcticae avatar avimak avatar clementjuventin avatar davelange avatar devpeek avatar dhruvkelawala avatar evolveart avatar florian-bellotti avatar fracek avatar github-actions[bot] avatar iddriss avatar irisdv avatar ivanludvig avatar laki997 avatar micksabox avatar nmalzieu avatar notv4l avatar okhaimie-dev avatar rootulp avatar schwepps avatar swaggymarie avatar tarrencev avatar teddynotbear avatar ugur-eren avatar vkzrx avatar whatthedev-eth avatar yohantz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

starknet-react's Issues

Transaction status changed notification

Some apps show notifications when the transaction status changes. The library should provide a mechanism for developers to register a callback invoked every time a transaction status changes.

Use multicall in `useStarkNetCall`

The hook should batch together all registered calls and send only one multicall request, then deduplex the output back to the original caller.

Match `wagmi` API

The new version of wagmi changed their API and now it's closer to the API in starknet-react.
From a discussion with @Pet3ris we started thinking about aligning our API to wagmi's since now the differences are minuscule.

The changes will be:

  • Rename hooks to follow wagmi's names
  • Rename hooks return values to match wagmi's. Most return values already match them
  • Change the hooks parameters to have positional arguments over keyword arguments like we do now
  • Add shims to map the current api with the new api so that the transition will be smooth

The semantics of the library will not change

Add unit tests

Hooks should be tested, in the past we had issues caused by the root provider fetching blocks after unmount. We should re-introduce tests to the project.

ConnectorNotFoundError

after running

npx create-next-app@latest --example https://github.com/auclantis/starknet-react/tree/main/examples/starknet-react-next

I tried to use the connect button and received ConnectorNotFoundError on the chrome console.

when I console log the error output from useStarknet, I'd get "could not activate Starknet" any idea what I'm missing here?

useStarknetCall always returns undefined

Hello team!
I have a local web app I am developing, pointing to Goerli with the latest starknet-react package (as of this morning) and the latest ArgentX setup.

In a page I am able to successfully invoke the mint on this NFT contract I deployed. But on another page I am failing to call a function, the totalSupply or name for example.

export default function ChannelList() {
  const { account } = useStarknet()
  const { data: channelsCount, loading, error, refresh } = useStarknetCall({ contract: useChannelContract(), method: 'totalSupply' })
  const [shouldRefresh, setShouldRefresh] = useState(true)

  console.log(`channelsCount: ${channelsCount}, loading: ${loading}, error: ${error}`)

  useEffect(() => {
    if (!account || !shouldRefresh) return
    setShouldRefresh(false)
    refresh()
    console.log('>>> refresh')
  }, [account, shouldRefresh, refresh])
  
  return (... )
}

In the console logs I see that the hook is loading then stops, but the data returned is always undefined.

channelsCount: undefined, loading: true, error: undefined
>>> refresh
channelsCount: undefined, loading: false, error: undefined
channelsCount: undefined, loading: false, error: undefined

I even open another page, reload, connect the wallet, then navigate to this one, so I am sure that when this component loads the first time the account is connected correctly.

Any idea why this issue?

Auto connect fails to connect in production builds

Do you have any thoughts around supporting auto connect? It would support reconnecting when a connection has already been approved previously. Currently it seems most people do a hard connect, which prompts the user as soon as they land on a page, which I think is an anti-pattern.

Transactions not updating on Goerli

The transactions are being polled but the state is not updated to the correct status - likely due to the transaction hash being contained within the transaction object on Goerli

const entry = state.transactions.findEntry(
      (tx) => tx.transactionHash === action.transactionResponse.transaction_hash
    )

image

Call / Invoke from Account Contract

Hello,

Could you please add an example that shows how to call a function from the account contract such that the get_caller_address() doesn't return 0?

Thanks

Update example abi

The abi from starknet-compile --abi is an array, while the example uses a json object. It should be updated.

`useStarknetCall` set `loading` to `false` before the data is actually loaded

In the useEffect of the useStarknetCall hook, we call dispatch({ type: 'set_last_updated_at', blockHash: block.block_hash }) without waiting the refresh to finalize.
Which leads to set loading (and maybe lastUpdatedAt) to early.

refresh()
dispatch({ type: 'set_last_updated_at', blockHash: block.block_hash })

  • In think we should only allow the dispatch types set_call_response and set_call_error to be able to set the loading property.
  • Also, maybe we should only set the lastUpdatedAt property when the new data are loaded properly.

Custom default provider

Should be able to customize the default provider used if Argent-X is not connected.

Proposed API:

<StarknetProvider
  defaultProvider={new Provider({ baseUrl: 'http://localhost:5000' })}>
</StarknetProvider>

`useStarknetCall` breaks if `useContract` is called before starknet provider loaded

Problem

I ran into the following situation:

I have some code that invokes the useStarknetCall hook right after the useContract hook.

let useContractParams = ReactStarknet.UseContract.Parameters.make(
  ~abi=Abi.taskRegistry,
  ~address=registryAddress,
  ()
)
let {contract} = ReactStarknet.useContract(useContractParams)
let useStarknetCallParams = ReactStarknet.UseStarknetCall.Parameters.make(
  ~contract=contract -> Belt.Option.getWithDefault(%raw("undefined")), 
  ~method="invocations",
  ~args=[task.int_address],
  ()
)
let {data, loading, error, refresh} = ReactStarknet.useStarknetCall(useStarknetCallParams)

There's no real magic in this code as it translates to the following JS:

var match = Core.useContract(useContractParams);
var contract = match.contract;
var useStarknetCallParams = {
  contract: Belt_Option.getWithDefault(contract, undefined),
  method: "invocations",
  args: [task.int_address]
};
var match$1 = Core.useStarknetCall(useStarknetCallParams);

I noticed an issue where if the contract is not yet loaded when the useCallback is called inside of the useStarknetCall hook, then the hook never refreshes it's call to StarkNet.

I had to add the following hook to the code to make it work and make the address compose:

Shortcut fix

React.useEffect1(() => {
  if Belt.Option.isSome(contract) {
    refresh()
  }

  None
}, [contract])

Which translates to the following JS:

var refresh = match$1.refresh;
React.useEffect((function () {
        if (Belt_Option.isSome(contract)) {
          Curry._1(refresh, undefined);
        }
        
      }), [contract]);

Possible fix

I wonder if it's important enough given useContract and useStarknetCall would typically be called in this sequence, to bake this logic or some form of it into the hook itself.

I can see that this issue does not arise during in the demo program despite the hooks being called in short succession.

NOTE When I use the trick above, there are still some wasted requests that get created without a contract_address being specified (this may be a starknet.js issue also).

`get-starknet` breaks ArgentX wallet integration

It seems that the latest version mandates using get-starknet as opposed to the connectors approach which was used before. While it's great that users can now choose their preferred wallet, unfortunately, the popup is not showing to some of our users (including myself) on Chrome; even if they have ArgentX installed. It works fine on the Brave browser.

Any idea what could be causing the inconsistency in behavior?

Allow to disable autorefresh when using `useStarknetCall`

I have a use case where the data of a contract will never change.
For this reason I want to prevent my app to refresh those data and I can only do it using starknet.js

As auto-refresh is a great feature, we should give the possibility to disabled this auto refresh.
Maybe

  • with an option to the useStarknetCall hook
  • by creating a specific hook
  • or maybe by leveraging on the new hook from this issue #104?

Check user connected network after connecting wallet

At the moment there seems to be no support in checking which network the user is connected to (e.g. Goeril or mainnet), i.e. the chainId.

It would be nice if we could possibly add some new features (e.g. hooks) for checking this - similar to what we have for chainId in wagmi for EVM chains.

This is crucial because when mainnet launch we would not want the users to sign the message on the wrong network to cause any inconvenience or financial loss.

Add options to invoke

I'd like to set { max_fee: 0 } on an invoke call. As far as I understand, this is a third options argument to contract.invoke, which this package currently does not support

getInstalledInjectedConnectors() may be empty on page load but not empty a bit later

On pxls.wtf we had the following issue: sometimes the users couldn't log because there were no connectors.
I found that it happened when the user was reloading the page (command R on chrome).
At that point, the getInstalledInjectedConnectors() that gets called at the very beginning of my Next.js app was empty!

Right now, I fixed it the hacky way:
https://github.com/nmalzieu/pxls-frontend/blob/main/pages/_app.tsx#L111-L129

However, I wonder:

  • could we detect that the installed connectors available on the page have changed?
  • should we really check this just once, at the very beginning of a Next.js app as done in the example or should we have a way to reload this before trying to connect
  • is there a reason why this happened to me only when doing a "reload" of the page and not when I was opening the same page in a new tab?

Should connectors be their in their own package?

Web3 React distributes connectors in their own package, while wagmi comes battery included. At the time of writing there is only one connector (Argent X) so it makes sense to include it by default.

What should we do in the future when more connectors become available?

Possible violation of types when using `useStarknet`

I'm observing the following object when connecting via useStarknet:

image

This seems to be in violation of the types seen here:

export interface StarknetState {

export interface StarknetState {
  account?: string
  connect: (connector: Connector) => void
  library: ProviderInterface
  connectors: Connector[]
  error?: Error
}

Should this mean that connectors etc. need to be marked as ??

Mainnet support

Someone mentioned that the library is not working with StarkNet mainnet. We should investigate and fix this.

Improve connector abstraction

At the moment the connector abstraction is very bare bone, consisting only of the InjectedConnector class (and the proposed testing connector in #54). Now we have a new wallet (see #77) and so it makes sense to improve what is available.

As a React library we have a few of design goals:

  1. Give maximum control to developers when it comes to the UI and UX of their application. Embedding a modal is sub-optimal IMHO, ready-made wallet pickers should be developed on top of this library and not the other way round.
  2. Support future non-injected wallets like Wallet Connect.
  3. Improve discoverability, so for example show wallets that the user has not installed but the developer wants to push.
  4. Support all kind of injected wallets, without the developer having to manually add them.

Point 3 and 4 are at odds so there's going to be tradeoffs.

not working with create-react-app ?

I I'm trying to use this library in a create-react-app app

I have this error :

Uncaught TypeError: (0 , superstruct_1.string) is not a function
    at Object../node_modules/starknet/dist/utils/typedData/types.js (types.js:27:1)
    at Object.options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at Object../node_modules/starknet/dist/utils/typedData/utils.js (utils.js:5:1)
    at Object.options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at Object../node_modules/starknet/dist/utils/typedData/index.js (index.js:42:1)
    at Object.options.factory (react refresh:6:1)

Example and template should be two different projects

PR #143 is failing to build because they added the new hook to the example, which uses the published version of the package.

The solution is to:

  • have the example package use the workspace version of the core package
  • have a separate template project called create-starknet-app. The project works like create-next-app to quickly setup a starknet application from different templates.

undefined address when using braavos

Hey there,

We noticed an issue happening with Braavos (it worked fine with argent-x). After reloading the page, the multicall signing panel from braavos doesn't open when clicking on the button which calls the execute. The 'error' printed was Cannot read properties of undefined (reading 'address'). Braavos team told us this could be because the connector was not injected properly (we hardcoded it) or there is a problem in the starknet-execute. We tried to log the account in hooks/execute.js and it was undefined which is strange because window.starknet_braavos was defined. When changing the account value to window.starknet_braavos, it seems to work correctly.

Have a great day,
Thomas

Support account's execute

This is different from #6. The account interface exposes an execute method to invoke multiple external functions in one transaction.

The proposed interface is:

const { execute, loading, error } = useStarknetExecute()

Where execute is:

execute: ({ calls: CallArgs, metadata?: any }) => Promise<AddTransactionResponse | undefined>
type CallArgs = { args?: T, contract?: Contract, method?: string }

Example

const { token } = useTokenContract()
const { other } = useOtherContract()

const { account } = useStarknet()
const { execute } = useStarknetExecute()

const [amount, setAmount] = useState(0)

// ...

execute({
  metadata: { message: 'Approve token and swap' },
  calls: [
    { contract: token, method: 'approve', args: amount && account ? [amount, account] : undefined },
    { contract: other, method: 'swap', args: amount && account ? [amount, account /*, more data here */] : undefined },
  ]
})

Like invoke, execute checks that all calls arguments are defined before making the call.

Mock connector for testing

We should make it as easy as possible for users to test their code. The mock connector should simulate a real connector (e.g. InjectedConnector) and expose two additional methods: accept() and reject() to accept and reject user requests (connect, submit, etc).

Introduce hooks for low-level contract calls and invocations

There are some use cases which may mandate using the low-level starknet.js operations callContract and invokeFunction. However, today, no hook api exists for them. This is particularly useful in StarkNet where we don't need the full contract signature to call a function.

Examples:

  • Rapid prototyping (e.g., only need to call 1 function without providing abi)
  • Low-level interactions (e.g., trading/MEV contracts in ethereum mainnet)
  • Security testing of contracts

Hook to get transaction status

We should add a new hook to get a transaction by its hash.

const {
  data,
  isLoading,
  error,
  isError,
  refetch
} = useTransaction({ hash })

Replace combination of `useEffect` + `setState` by `useMemo`

I take the example of useContract which use this combination.

It would give better performance and more readability to use useMemo instead.

Plus, we will not have to wait for setState to be called to be able to use the contract.
When using useContract, we have to deal with the possibility that the contract is undefined, which will not be the case when using useMemo.

Here is a little post which explain this : https://stackoverflow.com/a/56029184

UseCallContract response type loses type information for result

The call contract response from starknet.js returns an array of strings: https://github.com/0xs34n/starknet.js/blob/cd88fc8747897002b48c48da94c4da60ba739e87/src/types/api.ts#L145.

export type CallContractResponse = {
  result: string[];
};

However, the corresponding type in starknet-react is an array of any. Could this be restricted to an array of strings?

Eth contract: bug with hooks, but not with the other syntax (ethContract.approve(...) for example)

  const { data:approveData, approveLoading, error:approveError, reset:approveReset, invoke:approve } = useStarknetInvoke({ ethContract, method: 'approve'})

  // It doesn't work
  useEffect(() => {
    ethContract && approve({ args: ['0x6806c42960e739918af543b733e76eb4f52a99402ec00e57794cb26cb3a6723', [100000000, 0]] })
  }, [ethContract, approve])
  // It doesn't work
  ethContract && approve({ args: ['0x6806c42960e739918af543b733e76eb4f52a99402ec00e57794cb26cb3a6723', [100000000, 0]] })
  
  // It works
  ethContract && ethContract.approve('0x6806c42960e739918af543b733e76eb4f52a99402ec00e57794cb26cb3a6723', [100000000, 0])

(when it doesn't work, absolutely nothing happens, no error)

Here is the eth contract : https://goerli.voyager.online/contract/0x4bb0f7af15a5469be4a571c8660d9aaf39e7e67f27f774702d75e77141ef90#writeContract

image

Here is the eth contract ABI :
https://pastebin.com/YxyfivFr

I also tried :
image

Hook arguments and return values are not composable

I'm running into situations where an output of one call needs to be composed as the input to another contract call. Unfortunately, it seems that current argument types are based on arrays of strings and current output types have more type information (for example returning BN.js types).

I wonder if it would make sense to decide on a default in-js representation for felts and other types and using it consistently?

Perhaps related to this: #98.

Add a message signing hook

Implement a message signing hook based on wagmi's useSignTypedData.

  const { data, isError, isLoading, isSuccess, signTypedData } =
    useSignTypedData({
      domain,
      types,
      value,
    })

Related to #105 since we want to match the APIs.

Improve rendering amount using some hooks

Hello there,

I have an issue regarding the number of renders for component using some hooks.

Some of them (like useStarknetCall or useStarknetBlock) automatically refresh their data when a new block occures.
The problem is that even when there are no new blocks, it causes a render of all components (and by extension children) using those hooks.

I created a repository to reproduce the problem, you can find it on the branch "too-many-rerender".
We will see the difference between the number of rendering and the number of real new blocks.

I know that with React, a lot of elements are memoized (callbacks, state, computed data, ...) but in some cases it can be a problem.
Especially when I used those hooks in a context/provider on top of the app, then it causes the try to rerender the whole tree.
And as you may guess, I don't want to explicitly memoize all my components.

I didn't investigate much, but maybe something could be improved with useStarknetBlock where it seems the data property change even if the block is not new.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.