Skip to content

Commit

Permalink
docs: document hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
fracek committed Feb 5, 2022
1 parent eeb9269 commit 0f30559
Show file tree
Hide file tree
Showing 34 changed files with 288 additions and 771 deletions.
6 changes: 6 additions & 0 deletions .changeset/afraid-insects-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@starknet-react/core': minor
'website': minor
---

Change hooks interface
14 changes: 8 additions & 6 deletions packages/core/src/hooks/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,26 @@ function starknetCallReducer(state: State, action: Action): State {
return state
}

interface UseStarknetCallArgs {
contract?: Contract
method?: string
args?: Args
}

export interface UseStarknetCall {
data?: Args
loading: boolean
error?: string
refresh: () => void
}

export function useStarknetCall(
contract: Contract | undefined,
method: string | undefined,
args: Args | undefined
): UseStarknetCall {
export function useStarknetCall({ contract, method, args }: UseStarknetCallArgs): UseStarknetCall {
const [state, dispatch] = useReducer(starknetCallReducer, {
loading: true,
lastUpdatedAt: '',
})

const block = useStarknetBlock()
const { data: block } = useStarknetBlock()

const callContract = useCallback(async () => {
if (contract && method && args) {
Expand Down
16 changes: 11 additions & 5 deletions packages/core/src/hooks/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ import { useEffect, useState } from 'react'
import { Abi, Contract } from 'starknet'
import { useStarknet } from '../providers/starknet'

export function useContract(
abi: Abi[] | undefined,
address: string | undefined
): Contract | undefined {
interface UseContractArgs {
abi?: Abi[]
address?: string
}

interface UseContract {
contract?: Contract
}

export function useContract({ abi, address }: UseContractArgs): UseContract {
const [contract, setContract] = useState<Contract | undefined>(undefined)
const { library } = useStarknet()

Expand All @@ -15,5 +21,5 @@ export function useContract(
}
}, [abi, address, library])

return contract
return { contract }
}
10 changes: 6 additions & 4 deletions packages/core/src/hooks/invoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ function starknetInvokeReducer(state: State, action: Action): State {
return state
}

interface UseStarknetInvokeArgs {
contract?: Contract
method?: string
}

export interface UseStarknetInvoke {
data?: Args
loading: boolean
Expand All @@ -65,10 +70,7 @@ export interface UseStarknetInvoke {
invoke: (args: Args) => Promise<AddTransactionResponse | undefined>
}

export function useStarknetInvoke(
contract: Contract | undefined,
method: string | undefined
): UseStarknetInvoke {
export function useStarknetInvoke({ contract, method }: UseStarknetInvokeArgs): UseStarknetInvoke {
const [state, dispatch] = useReducer(starknetInvokeReducer, {
loading: false,
})
Expand Down
10 changes: 8 additions & 2 deletions packages/core/src/providers/block/context.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { createContext, useContext } from 'react'
import { GetBlockResponse } from 'starknet'

export const StarknetBlockContext = createContext<GetBlockResponse | undefined>(undefined)
export interface StarknetBlock {
data?: GetBlockResponse
loading?: boolean
error?: string
}

export const StarknetBlockContext = createContext<StarknetBlock>(undefined)

export function useStarknetBlock(): GetBlockResponse | undefined {
export function useStarknetBlock(): StarknetBlock {
return useContext(StarknetBlockContext)
}
19 changes: 16 additions & 3 deletions packages/core/src/providers/block/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@ export function StarknetBlockProvider({
const { library } = useStarknet()

const [block, setBlock] = useState<GetBlockResponse | undefined>(undefined)
const [loading, setLoading] = useState<boolean | undefined>(undefined)
const [error, setError] = useState<string | undefined>(undefined)

const fetchBlock = useCallback(() => {
if (library) {
library.getBlock().then(setBlock)
setLoading(true)
library
.getBlock()
.then(setBlock)
.catch(() => {
setError('failed fetching block')
})
.finally(() => setLoading(false))
}
}, [library])
}, [library, setLoading, setError, setBlock])

useEffect(() => {
fetchBlock()
Expand All @@ -32,5 +41,9 @@ export function StarknetBlockProvider({
return () => clearInterval(intervalId)
}, [fetchBlock, interval])

return <StarknetBlockContext.Provider value={block}>{children}</StarknetBlockContext.Provider>
return (
<StarknetBlockContext.Provider value={{ data: block, loading, error }}>
{children}
</StarknetBlockContext.Provider>
)
}
4 changes: 2 additions & 2 deletions packages/core/test/hooks/call.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('useStarknetCall', () => {
)

const { result, waitForValueToChange } = renderHook(
() => useStarknetCall(contract, 'counter', {}),
() => useStarknetCall({ contract, method: 'counter', args: {} }),
{ wrapper }
)

Expand All @@ -30,7 +30,7 @@ describe('useStarknetCall', () => {
refresh()
})

await waitForValueToChange(() => result.current.data)
await waitForValueToChange(() => result.current.data, { timeout: 10000 })

expect(result.current.data.count).toBeDefined()
expect(result.current.error).toBeUndefined()
Expand Down
12 changes: 7 additions & 5 deletions packages/core/test/hooks/contract.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ describe('useContract', () => {
const wrapper = ({ children }) => <StarknetProvider>{children}</StarknetProvider>

it('returns the connected Contract', async () => {
const { result } = renderHook(() => useContract(CounterAbi as Abi[], address), { wrapper })
const { result } = renderHook(() => useContract({ abi: CounterAbi as Abi[], address }), {
wrapper,
})
expect(result.current).not.toBeUndefined()
expect(result.current.connectedTo).toEqual(address)
expect(result.current.contract.connectedTo).toEqual(address)
})

it('updates the Contract if address changes', async () => {
const { result, rerender } = renderHook(
({ address }) => useContract(CounterAbi as Abi[], address),
({ address }) => useContract({ abi: CounterAbi as Abi[], address }),
{
wrapper,
initialProps: {
Expand All @@ -27,12 +29,12 @@ describe('useContract', () => {
}
)

expect(result.current).toBeUndefined()
expect(result.current.contract).toBeUndefined()

act(() => {
rerender({ address, children: undefined })
})

expect(result.current).not.toBeUndefined()
expect(result.current.contract).toBeDefined()
})
})
4 changes: 2 additions & 2 deletions packages/core/test/hooks/invoke.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('useStarknetInvoke', () => {
)

const { result, waitForValueToChange } = renderHook(
() => useStarknetInvoke(contract, 'incrementCounter'),
() => useStarknetInvoke({ contract, method: 'incrementCounter' }),
{ wrapper }
)

Expand All @@ -28,7 +28,7 @@ describe('useStarknetInvoke', () => {
result.current.invoke({ amount: '0x1' })
})

await waitForValueToChange(() => result.current.data)
await waitForValueToChange(() => result.current.data, { timeout: 10000 })

expect(result.current.data.code).toEqual('TRANSACTION_RECEIVED')
expect(result.current.error).toBeUndefined()
Expand Down
16 changes: 10 additions & 6 deletions packages/core/test/providers/block.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ describe('useStarknetBlock', () => {
<StarknetBlockProvider>{children}</StarknetBlockProvider>
</StarknetProvider>
)
const { result, waitForNextUpdate } = renderHook(() => useStarknetBlock(), { wrapper })
expect(result.current).toBeUndefined()
// wait up to one minute for a block
await waitForNextUpdate({ timeout: 60000 })
expect(result.current.timestamp).toBeGreaterThan(0)
expect(result.current.block_hash).not.toBeUndefined()
const { result, waitForValueToChange } = renderHook(() => useStarknetBlock(), { wrapper })

expect(result.current.data).toBeUndefined()
expect(result.current.loading).toBeTruthy()

await waitForValueToChange(() => result.current.data, { timeout: 10000 })

expect(result.current.data.timestamp).toBeGreaterThan(0)
expect(result.current.data.block_hash).not.toBeUndefined()
expect(result.current.loading).toBeFalsy()
})
})
4 changes: 2 additions & 2 deletions packages/core/test/providers/starknet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react'
import { renderHook } from '@testing-library/react-hooks'
import { useStarknet, StarknetProvider } from '../../src'

describe('useStarknetBlock', () => {
it('returns the current block', async () => {
describe('useStarknet', () => {
it('returns the current account', async () => {
const wrapper = ({ children }) => <StarknetProvider>{children}</StarknetProvider>
const { result } = renderHook(() => useStarknet(), { wrapper })
const { account, hasStarknet } = result.current
Expand Down
25 changes: 25 additions & 0 deletions website/docs/hooks/block.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
sidebar_position: 2
---

# useStarknetBlock

Hook to access the current StarkNet block.

```typescript
import { useStarknetBlock } from '@starknet-react/core'

const { data, loading, error } = useStarknetBlock()
```

## Return Values

```typescript
{
data?: GetBlockResponse
loading?: boolean
error?: string
}
```

Where `GetBlockResponse` is from starknet.js.
34 changes: 34 additions & 0 deletions website/docs/hooks/call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
sidebar_position: 4
---

# useStarknetCall

Hook to fetch data from a StarkNet contract. The data is automatically refreshed at every block.

```typescript
import { useStarknetCall } from '@starknet-react/core'

const { data, loading, error, refresh } = useStarknetCall({ contract, method, args })
```

## Parameters

```typescript
{
contract?: Contract
method?: string
args?: Args
}
```

## Return Values

```typescript
{
data?: Args
loading: boolean
error?: string
refresh: () => void
}
```
34 changes: 34 additions & 0 deletions website/docs/hooks/contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
sidebar_position: 3
---

# useContract

Hook to build a `Contract` instance from its ABI and address.

```typescript
import { useContract } from '@starknet-react/core'

const { contract } = useContract({ abi, address })
```

## Parameters

```typescript
{
abi?: Abi[]
address?: string
}
```

Where `Abi` is from starknet.js.

## Return Values

```typescript
{
contract?: Contract
}
```

A contract is returned only if both `abi` and `address` are defined.
34 changes: 34 additions & 0 deletions website/docs/hooks/invoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
sidebar_position: 5
---

# useStarknetInvoke

Hook to create a function that invokes a contract method and track the transaction status.

```typescript
import { useStarknetInvoke } from '@starknet-react/core'

const { data, loading, error, reset, invoke } = useStarknetInvoke({ contract, method })
```

## Parameters

```typescript
{
contract?: Contract
method?: string
}
```

## Return Values

```typescript
data?: Args
loading: boolean
error?: string
reset: () => void
invoke: (args: Args) => Promise<AddTransactionResponse | undefined>
```

Where `Args` and `AddTransactionResponse` are from starknet.js.
Loading

0 comments on commit 0f30559

Please sign in to comment.