@dappql/react 1.0.7 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # @dappql/react
2
+
3
+ > React hooks for [DappQL](https://github.com/dappql/core). Typed, batched smart-contract reads and writes on top of [wagmi](https://wagmi.sh) + [viem](https://viem.sh), with automatic multicall fusion across your entire component tree, per-block reactivity, iterator queries, and mutation tracking.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @dappql/react wagmi viem @tanstack/react-query
9
+ ```
10
+
11
+ Pair with the [`dappql`](https://www.npmjs.com/package/dappql) CLI to generate your typed contract modules.
12
+
13
+ ## Provider
14
+
15
+ ```tsx
16
+ import { WagmiProvider } from 'wagmi'
17
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
18
+ import { DappQLProvider } from '@dappql/react'
19
+
20
+ const queryClient = new QueryClient()
21
+
22
+ export function Root({ children }) {
23
+ return (
24
+ <WagmiProvider config={wagmiConfig}>
25
+ <QueryClientProvider client={queryClient}>
26
+ <DappQLProvider watchBlocks>{children}</DappQLProvider>
27
+ </QueryClientProvider>
28
+ </WagmiProvider>
29
+ )
30
+ }
31
+ ```
32
+
33
+ Provider options:
34
+
35
+ | Option | Purpose |
36
+ | --- | --- |
37
+ | `watchBlocks` | Refetch on every new block, makes reads reactive to chain state. |
38
+ | `simulateMutations` | Preflight every tx via `eth_call`. Aborts on revert. |
39
+ | `onMutationUpdate` | Single callback for every transaction lifecycle event, one place to drive toasts, analytics, receipts. |
40
+ | `addressResolver` | Function that resolves contract names to addresses, for registries, proxies, multi-deploy. |
41
+ | `AddressResolverComponent` | Async alternative to `addressResolver` when the resolver needs hooks. |
42
+
43
+ ## Reads
44
+
45
+ ### `useContextQuery`: the default
46
+
47
+ Batches calls across your **entire** component tree into one multicall.
48
+
49
+ ```tsx
50
+ import { Token, ToDo } from './contracts'
51
+ import { useContextQuery } from '@dappql/react'
52
+
53
+ function Dashboard({ account }) {
54
+ const { data, isLoading } = useContextQuery({
55
+ balance: Token.call.balanceOf(account),
56
+ symbol: Token.call.symbol(),
57
+ totalTasks: ToDo.call.totalTasks(),
58
+ })
59
+
60
+ if (isLoading) return <Spinner />
61
+ return <p>{data.balance.toString()} {data.symbol}</p>
62
+ }
63
+ ```
64
+
65
+ If `<Dashboard>` and `<Sidebar>` both use `useContextQuery`, their calls fuse into one RPC, not two.
66
+
67
+ ### `useQuery`: component-scoped batching
68
+
69
+ Same shape as `useContextQuery`, but scoped to this hook call. Use when you need `blockNumber`, `paused`, custom `refetchInterval`, or `batchSize` overrides.
70
+
71
+ ### `useSingleQuery` / `useSingleContextQuery`
72
+
73
+ ```tsx
74
+ const { data } = useSingleContextQuery(Token.call.balanceOf(account))
75
+ // data: bigint (inferred from the ABI)
76
+ ```
77
+
78
+ ### `useIteratorQuery`: on-chain arrays
79
+
80
+ ```tsx
81
+ import { useIteratorQuery } from '@dappql/react'
82
+
83
+ const { data } = useIteratorQuery(totalTasks, (i) => ToDo.call.taskAt(account, i))
84
+ ```
85
+
86
+ ## Writes
87
+
88
+ ```tsx
89
+ import { useMutation } from '@dappql/react'
90
+ import { ToDo } from './contracts'
91
+
92
+ function NewTask() {
93
+ const mutation = useMutation(ToDo.mutation.addItem, 'Add task')
94
+
95
+ return (
96
+ <button
97
+ disabled={mutation.isLoading}
98
+ onClick={() => mutation.send('Buy milk', 0n)}
99
+ >
100
+ {mutation.confirmation.isSuccess ? 'Added' : 'Add task'}
101
+ </button>
102
+ )
103
+ }
104
+ ```
105
+
106
+ Surface:
107
+
108
+ ```ts
109
+ mutation.send(...args) // broadcast; spread args, not array
110
+ mutation.simulate(...args) // manual preflight
111
+ mutation.estimate(...args) // gas estimate
112
+ mutation.isPending // awaiting signature
113
+ mutation.isLoading // awaiting signature OR mining
114
+ mutation.confirmation.isSuccess // receipt confirmed
115
+ mutation.reset()
116
+ ```
117
+
118
+ ## Fluent request API
119
+
120
+ Every generated call exposes a small fluent API for overrides:
121
+
122
+ ```ts
123
+ Token.call.balanceOf(account)
124
+ .at('0x...') // override deploy address
125
+ .defaultTo(0n) // default value until the call resolves
126
+ ```
127
+
128
+ ## Related packages
129
+
130
+ | Package | Purpose |
131
+ | --- | --- |
132
+ | [`dappql`](https://www.npmjs.com/package/dappql) | Codegen CLI, generates the typed contract modules you import above |
133
+ | [`@dappql/async`](https://www.npmjs.com/package/@dappql/async) | Non-React runtime, same typed calls, no React required |
134
+ | [`@dappql/codegen`](https://www.npmjs.com/package/@dappql/codegen) | Framework-agnostic codegen engine |
135
+ | [`@dappql/mcp`](https://www.npmjs.com/package/@dappql/mcp) | MCP server, live contract context for AI coding agents |
136
+
137
+ ## Full documentation
138
+
139
+ [github.com/dappql/core](https://github.com/dappql/core)
140
+
141
+ ## License
142
+
143
+ MIT
@@ -1 +1 @@
1
- {"version":3,"file":"Mutation.d.ts","sourceRoot":"","sources":["../src/Mutation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAGxD,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,YAAY,CAAA;AAE9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAEtD,iBAAS,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,EAChE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,MAAM,EAAE,YAAY,GAAG,SAAS,aAGd,IAAI,8KAYvB;AAED,iBAAS,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,EAChE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,MAAM,EAAE,YAAY,GAAG,SAAS,aAGd,IAAI,qBAYvB;AAED,iBAAS,uBAAuB,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,GAAG,SAAS;;;;;;;;;;;;;;;;;;;GAE/D;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GACD,MAAM,CAAA;AAEV;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,EACvE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,EAC/B,wBAAwB,CAAC,EAAE,eAAe,GACzC;IACD,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;IAChD,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;IACzB,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;IACpC,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,sBAAsB,GAAG,IAAI,CAAA;IAC5C,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAA;IACxD,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAC7B,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IACjD,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;CAClD,CA6HA;AAED;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,IAAI,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"Mutation.d.ts","sourceRoot":"","sources":["../src/Mutation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAGxD,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,YAAY,CAAA;AAE9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAEtD,iBAAS,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,EAChE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,MAAM,EAAE,YAAY,GAAG,SAAS,aAGd,IAAI,8KAYvB;AAED,iBAAS,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,EAChE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,MAAM,EAAE,YAAY,GAAG,SAAS,aAGd,IAAI,qBAYvB;AAED,iBAAS,uBAAuB,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,GAAG,SAAS;;;;;;;;;;;;;;;;;;;GAE/D;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GACD,MAAM,CAAA;AAEV;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,EACvE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,EAC/B,wBAAwB,CAAC,EAAE,eAAe,GACzC;IACD,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;IAChD,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;IACzB,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;IACpC,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,sBAAsB,GAAG,IAAI,CAAA;IAC5C,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAA;IACxD,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAC7B,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IACjD,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;CAClD,CA2IA;AAED;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,SAAS,GAAG,EAAE,IAAI,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA"}
package/dist/Mutation.js CHANGED
@@ -49,7 +49,7 @@ function useMutationConfirmation(hash) {
49
49
  */
50
50
  export function useMutation(config, optionsOrTransactionName) {
51
51
  const { addressResolver, onMutationUpdate, simulateMutations } = useDappQL();
52
- const { chain, address: account } = useAccount();
52
+ const { chain, address: account, connector } = useAccount();
53
53
  const tx = useWriteContract();
54
54
  const client = usePublicClient();
55
55
  const address = useMemo(() => optionsOrTransactionName && typeof optionsOrTransactionName !== 'string' && optionsOrTransactionName.address
@@ -70,6 +70,16 @@ export function useMutation(config, optionsOrTransactionName) {
70
70
  const send = useCallback((...args) => {
71
71
  const now = Date.now();
72
72
  const id = mutationInfo.address + mutationInfo.functionName + now.toString();
73
+ // Captured when the caller asks to send, and used for the write below.
74
+ //
75
+ // `writeContract` resolves the active connection inside its own mutation
76
+ // function, which runs after a yield — and after `simulate` below, which
77
+ // is awaited. A wallet event landing in either gap would otherwise sign
78
+ // with whoever is connected then, against arguments built and simulated
79
+ // for whoever was connected when the caller decided to send. Binding both
80
+ // makes wagmi fail that write instead of retargeting it.
81
+ const boundAccount = account;
82
+ const boundConnector = connector;
73
83
  if (!account || !chain?.id) {
74
84
  const error = !account ? 'No account connected' : 'Invalid chain';
75
85
  onMutationUpdate?.({
@@ -88,6 +98,8 @@ export function useMutation(config, optionsOrTransactionName) {
88
98
  address,
89
99
  chainId: chain?.id,
90
100
  args,
101
+ account: boundAccount,
102
+ connector: boundConnector,
91
103
  }, {
92
104
  onSettled(data, error) {
93
105
  const status = error ? 'error' : 'signed';
@@ -124,7 +136,7 @@ export function useMutation(config, optionsOrTransactionName) {
124
136
  else {
125
137
  sendTx();
126
138
  }
127
- }, [address, tx, config, account, chain?.id, options?.simulate, simulateMutations, client, simulate]);
139
+ }, [address, tx, config, account, connector, chain?.id, options?.simulate, simulateMutations, client, simulate]);
128
140
  const confirmation = useMutationConfirmation(tx.data);
129
141
  return useMemo(() => ({
130
142
  status: tx.status,
@@ -3,7 +3,7 @@ export declare class BlockSubscriptionManager {
3
3
  private subscribers;
4
4
  private currentBlock;
5
5
  subscribe(callback: Subscriber): () => boolean;
6
- onBlockUptated(newBlock: bigint): void;
6
+ onBlockUpdated(newBlock: bigint): void;
7
7
  }
8
8
  export declare function useBlockNumberSubscriber(): (callback: Subscriber) => () => boolean;
9
9
  export {};
@@ -13,7 +13,7 @@ export class BlockSubscriptionManager {
13
13
  }
14
14
  return () => this.subscribers.delete(callback);
15
15
  }
16
- onBlockUptated(newBlock) {
16
+ onBlockUpdated(newBlock) {
17
17
  this.currentBlock = newBlock;
18
18
  this.subscribers.forEach((sub) => sub(newBlock));
19
19
  }
@@ -24,7 +24,7 @@ export function useBlockNumberSubscriber() {
24
24
  useEffect(() => {
25
25
  return client?.watchBlockNumber({
26
26
  onBlockNumber: (blockNumber) => {
27
- manager.onBlockUptated(blockNumber);
27
+ manager.onBlockUpdated(blockNumber);
28
28
  },
29
29
  });
30
30
  }, [client, manager]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dappql/react",
3
- "version": "1.0.7",
3
+ "version": "1.0.10",
4
4
  "description": "Streamlined smart contract data fetching library for React dApps with TypeScript support",
5
5
  "author": "DappQL Team",
6
6
  "type": "module",
@@ -28,12 +28,12 @@
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
31
- "url": "git+https://github.com/dappql/monorepo.git"
31
+ "url": "git+https://github.com/dappql/core.git"
32
32
  },
33
33
  "bugs": {
34
- "url": "https://github.com/dappql/monorepo/issues"
34
+ "url": "https://github.com/dappql/core/issues"
35
35
  },
36
- "homepage": "https://github.com/dappql/monorepo#readme",
36
+ "homepage": "https://github.com/dappql/core#readme",
37
37
  "license": "MIT",
38
38
  "peerDependencies": {
39
39
  "@tanstack/react-query": ">=5.0.0",