Introduction @ic-reactor/react for React Developers

Yes, I still have many places to use the idea you provided to me, and I will change my code. I am asking you for other doubts. :rose:

No problem at all! :blush: Feel free to ask any other questions you have.

1 Like

image
image
console.log(address);There’s no reaction here.There’s no reaction here. I see your example is that you can just initialize it and return the value.
I can’t get the value for my btcAddress. Why do I have to use the call method to get the value?

If the method is an update call, refetchOnMount and refetchInterval will not work!
Its because of safety, you should call it manually. BTW when you deal with such a task, you dont need hook for that just call it once, then pass the result into the component!

Something like this would be a better solution in this situation:

const CkbtcAddress = ({ userPrincipal }: { userPrincipal: Principal }) => {
  const { call, data, loading } = useCKBTCMinterMethod({
    functionName: "get_btc_address",
    args: [{ owner: [userPrincipal], subaccount: [] }],
  })

  useEffect(() => {
    call()
  }, [])

  return loading ? (
    "Getting BTC address..."
  ) : (
    <div>
      <p>BTC Address: {data}</p>
      {/* other components related to BTC address */}
    </div>
  )
}

And:

const CkbtcUpdateBalance = ({ userPrincipal }: { userPrincipal: Principal }) => {
  const { call, data, loading } = useCKBTCMinterMethod({
    functionName: "update_balance",
    args: [{ owner: [userPrincipal], subaccount: [] }],
  })

  useEffect(() => {
    call()
  }, [])

  return loading ? (
    "Updating balance..."
  ) : (
    <div>
      <p>UTXOs: {jsonToString(data)}</p>
      {/* other components related to updating balance */}
    </div>
  )
}
1 Like

I’ve created a new example called ckBTC Wallet! This example demonstrates how to integrate with the ckBTC ledger and minter to retrieve BTC.

Check out the demo video:

You can find the source code on GitHub:

ckBTC Wallet Code

Key Component: MinterRetrieveBTC

This hooks handles the retrieval of BTC by interacting with the ckBTC ledger and minter. Here are the main parts of the component:

  const { call: refetchBalance, data: balance, loading: balanceLoading } = useCKBTCLedgerMethod({
    functionName: "icrc1_balance_of",
    args: [{ owner: userPrincipal, subaccount: [] }],
  })

  const { call: refetchAllowance, data: allowance, loading: allowanceLoading } = useCKBTCLedgerMethod({
    functionName: "icrc2_allowance",
    args: [
      {
        account: { owner: userPrincipal, subaccount: [] },
        spender: { owner: minterCanisterId, subaccount: [] },
      },
    ],
  })

  const { call: retreiveBtc, data: retreiveBtcResult, error: retreiveBtcError, loading: retreiveBtcLoading } = useCKBTCMinterMethod({
    functionName: "retrieve_btc_with_approval",
    onSuccess: () => {
      refetchBalance()
      refetchAllowance()
    },
  })

  const { call: approve, loading: approveLoading, data: approveResult } = useCKBTCLedgerMethod({
    functionName: "icrc2_approve",
    onSuccess: () => {
      refetchAllowance()
      const amount = BigInt(amountRef.current?.value || "0")
      const address = addressRef.current?.value || ""
      retreiveBtc([{ amount, address, from_subaccount: [] }])
    },
  })

  const onSubmit = (event: React.FormEvent) => {
    event.preventDefault()
    const amount = BigInt(amountRef.current?.value || "0")
    approve([{ spender: { owner: minterCanisterId, subaccount: [] }, amount, fee: [], memo: [], created_at_time: [], from_subaccount: [], expected_allowance: [], expires_at: [] }])
  }

This component demonstrates how to:

  • Fetch and display the ckBTC balance.
  • Retrieve the allowance given to the minter.
  • Approve and retrieve BTC using the provided address and amount.

Feel free to explore and adapt the code to your needs. Happy coding!

2 Likes

Hey buddy, I have a problem, one of my Canister calls can be called directly with Plug, but I think using ic-reactor calls will fail on load.
This is my canister dashboard:https://dashboard.internetcomputer.org/canister/ypzti-4aaaa-aaaam-ab5ia-cai
Here’s a screenshot of the error:

Seems like you didn’t attach the Candid file into the canister, as you can see on the dashboard there is no method to call! if you have the candid file just import it inside javascript and pass the idlFactory into the actor initialization!

This is the context example:

import { createActorContext } from "@ic-reactor/react"
import { backend, canisterId, idlFactory } from "declarations/candid"

export type Backend = typeof backend

export const {
  ActorProvider: NoteActorProvider,
  useQueryCall: useNoteQueryCall,
  useUpdateCall: useNoteUpdateCall,
  useMethod: useNoteMethod,
} = createActorContext<Backend>({
  idlFactory, // this is important part
  canisterId,
})

or on the provider:

<NoteActorProvider
  withDevtools
  idlFactory={idlFactory} // this is important part
  canisterId="xeka7-ryaaa-aaaal-qb57a-cai"
  loadingComponent={<div>Loading Note Actor...</div>}
>
  <Notes publicKey={publicKey} />
  <AddNote publicKey={publicKey} />
</NoteActorProvider>
1 Like

hi,How should I customize the loading page?
image
And when I set it here it does override it but there’s a problem.
image
image

Yes, You be able to pass loading component into your ActorProvider and CandidAdapterProvider. Please refer to the documentation for more details.

The error you’re encountering is due to the parser. When you pass the withParser prop, it uses the local version. Therefore, you should install ic-reactor/parser, which includes a Wasm file that converts Candid files into JavaScript and more.

Alternatively, you can remove the withParser prop, and it will use the candid-ui canister from the network.

image
Does my CandidAdapterProvider’s loadingComponent have to work with withParser? He will not take effect now.

How is this not exported?
image
I now need to dynamically create actors using something like plug below.
image

Just pass the loadingComponent inside ActorProvider:

<ActorProvider loadingComponent={<>Loading...</>}>

Its exported!

import { useInitializeActor } from "@ic-reactor/react"

and can be used like this:

  const initializeActor = useInitializeActor()

// use it inside useEffect
  useEffect(() => {
    initializeActor(idlFactory)
  }, [initializeActor])

// or inside button
<button onClick={()=> initializeActor(idlFactory) >Initialize Actor</button>

I’m not sure how u can use plug here!

1 Like

Thanks, my version is not updated. Previously using 1.7.6 without exporting this.

1 Like

Just wanted to say thanks for this.

Been using these tools for our project (findeck.io - very much a WIP) and this entire library (we are using the react hooks a lot) is awesome!

Thank you so much for the kind words! I’m really glad to hear that you’re finding the library useful for your project. I checked out findeck.io—awesome looking website! Looking forward to seeing how it evolves. If you ever need any help or have feedback, feel free to reach out!

1 Like

Very cool! Can’t believe I’m only seeing this now.

Could you wrap this in IdentityKit so every app has a standard-conformed “Connect wallet” button with all wallets (and those that will come in the future)?

Thanks! I’m glad you like it! :blush: That’s a great idea—wrapping it in IdentityKit for a standardized “Connect Wallet” button would make it even more seamless across apps. I’ll definitely look into integrating that feature to support all current and future wallets.

If you’re interested, we could explore a possible collaboration to make this even better. Let me know if that sounds good to you!

1 Like