@mycelium-ip/react 0.1.0-alpha.0
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 +952 -0
- package/dist/hooks/derivative/useCreateDerivativeLink.d.ts +30 -0
- package/dist/hooks/derivative/useCreateDerivativeLink.d.ts.map +1 -0
- package/dist/hooks/derivative/useCreateDerivativeLink.js +45 -0
- package/dist/hooks/derivative/useUpdateDerivativeLicense.d.ts +30 -0
- package/dist/hooks/derivative/useUpdateDerivativeLicense.d.ts.map +1 -0
- package/dist/hooks/derivative/useUpdateDerivativeLicense.js +44 -0
- package/dist/hooks/entity/useCreateEntity.d.ts +28 -0
- package/dist/hooks/entity/useCreateEntity.d.ts.map +1 -0
- package/dist/hooks/entity/useCreateEntity.js +42 -0
- package/dist/hooks/entity/useUpdateEntityControllers.d.ts +28 -0
- package/dist/hooks/entity/useUpdateEntityControllers.d.ts.map +1 -0
- package/dist/hooks/entity/useUpdateEntityControllers.js +42 -0
- package/dist/hooks/grant/useCreateLicenseGrant.d.ts +29 -0
- package/dist/hooks/grant/useCreateLicenseGrant.d.ts.map +1 -0
- package/dist/hooks/grant/useCreateLicenseGrant.js +43 -0
- package/dist/hooks/grant/useRevokeLicenseGrant.d.ts +28 -0
- package/dist/hooks/grant/useRevokeLicenseGrant.d.ts.map +1 -0
- package/dist/hooks/grant/useRevokeLicenseGrant.js +42 -0
- package/dist/hooks/internal/useMyceliumClient.d.ts +15 -0
- package/dist/hooks/internal/useMyceliumClient.d.ts.map +1 -0
- package/dist/hooks/internal/useMyceliumClient.js +18 -0
- package/dist/hooks/internal/useMyceliumConnection.d.ts +14 -0
- package/dist/hooks/internal/useMyceliumConnection.d.ts.map +1 -0
- package/dist/hooks/internal/useMyceliumConnection.js +17 -0
- package/dist/hooks/internal/useMyceliumContext.d.ts +14 -0
- package/dist/hooks/internal/useMyceliumContext.d.ts.map +1 -0
- package/dist/hooks/internal/useMyceliumContext.js +22 -0
- package/dist/hooks/internal/useMyceliumWallet.d.ts +14 -0
- package/dist/hooks/internal/useMyceliumWallet.d.ts.map +1 -0
- package/dist/hooks/internal/useMyceliumWallet.js +17 -0
- package/dist/hooks/ip/useCreateIp.d.ts +29 -0
- package/dist/hooks/ip/useCreateIp.d.ts.map +1 -0
- package/dist/hooks/ip/useCreateIp.js +43 -0
- package/dist/hooks/ip/useTransferIp.d.ts +28 -0
- package/dist/hooks/ip/useTransferIp.d.ts.map +1 -0
- package/dist/hooks/ip/useTransferIp.js +42 -0
- package/dist/hooks/license/useCreateLicense.d.ts +28 -0
- package/dist/hooks/license/useCreateLicense.d.ts.map +1 -0
- package/dist/hooks/license/useCreateLicense.js +42 -0
- package/dist/hooks/license/useRevokeLicense.d.ts +27 -0
- package/dist/hooks/license/useRevokeLicense.d.ts.map +1 -0
- package/dist/hooks/license/useRevokeLicense.js +41 -0
- package/dist/hooks/license/useUpdateLicense.d.ts +28 -0
- package/dist/hooks/license/useUpdateLicense.d.ts.map +1 -0
- package/dist/hooks/license/useUpdateLicense.js +42 -0
- package/dist/hooks/metadata/useCreateEntityMetadata.d.ts +30 -0
- package/dist/hooks/metadata/useCreateEntityMetadata.d.ts.map +1 -0
- package/dist/hooks/metadata/useCreateEntityMetadata.js +45 -0
- package/dist/hooks/metadata/useCreateIpMetadata.d.ts +31 -0
- package/dist/hooks/metadata/useCreateIpMetadata.d.ts.map +1 -0
- package/dist/hooks/metadata/useCreateIpMetadata.js +46 -0
- package/dist/hooks/metadata/useCreateMetadataSchema.d.ts +29 -0
- package/dist/hooks/metadata/useCreateMetadataSchema.d.ts.map +1 -0
- package/dist/hooks/metadata/useCreateMetadataSchema.js +43 -0
- package/dist/hooks/queries/queryKeys.d.ts +45 -0
- package/dist/hooks/queries/queryKeys.d.ts.map +1 -0
- package/dist/hooks/queries/queryKeys.js +44 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/provider/MyceliumIpProvider.d.ts +56 -0
- package/dist/provider/MyceliumIpProvider.d.ts.map +1 -0
- package/dist/provider/MyceliumIpProvider.js +76 -0
- package/dist/provider/context.d.ts +22 -0
- package/dist/provider/context.d.ts.map +1 -0
- package/dist/provider/context.js +6 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/wallet.d.ts +54 -0
- package/dist/types/wallet.d.ts.map +1 -0
- package/dist/types/wallet.js +1 -0
- package/dist/utils/transaction.d.ts +40 -0
- package/dist/utils/transaction.d.ts.map +1 -0
- package/dist/utils/transaction.js +82 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,952 @@
|
|
|
1
|
+
# @mycelium-ip/react
|
|
2
|
+
|
|
3
|
+
React hooks for the Mycelium IP protocol. This package provides a wallet-agnostic React integration built on top of TanStack Query.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Wallet-agnostic** — Works with any wallet (Solana Wallet Adapter, Privy, embedded wallets)
|
|
8
|
+
- **TanStack Query powered** — Built-in caching, loading states, and automatic cache invalidation
|
|
9
|
+
- **Next.js compatible** — Works with client components out of the box
|
|
10
|
+
- **TypeScript first** — Full type safety with comprehensive TypeScript definitions
|
|
11
|
+
- **Minimal abstraction** — Thin wrapper over `@mycelium-ip/core-sdk`
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm
|
|
17
|
+
npm install @mycelium-ip/react @mycelium-ip/core-sdk
|
|
18
|
+
|
|
19
|
+
# yarn
|
|
20
|
+
yarn add @mycelium-ip/react @mycelium-ip/core-sdk
|
|
21
|
+
|
|
22
|
+
# pnpm
|
|
23
|
+
pnpm add @mycelium-ip/react @mycelium-ip/core-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Peer Dependencies
|
|
27
|
+
|
|
28
|
+
Make sure you have the following peer dependencies installed:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @solana/web3.js @tanstack/react-query react
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Connection } from "@solana/web3.js";
|
|
38
|
+
import { MyceliumIpProvider, useCreateEntity } from "@mycelium-ip/react";
|
|
39
|
+
|
|
40
|
+
// 1. Wrap your app with the provider
|
|
41
|
+
function App() {
|
|
42
|
+
const connection = new Connection("https://api.devnet.solana.com");
|
|
43
|
+
const wallet = useYourWalletAdapter(); // See Wallet Integration section
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<MyceliumIpProvider connection={connection} wallet={wallet}>
|
|
47
|
+
<CreateEntityButton />
|
|
48
|
+
</MyceliumIpProvider>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 2. Use hooks in your components
|
|
53
|
+
function CreateEntityButton() {
|
|
54
|
+
const { mutate, isPending, isSuccess } = useCreateEntity();
|
|
55
|
+
|
|
56
|
+
const handleCreate = () => {
|
|
57
|
+
mutate({
|
|
58
|
+
handle: new TextEncoder().encode("my-entity"),
|
|
59
|
+
additionalControllers: [],
|
|
60
|
+
signatureThreshold: 1,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<button onClick={handleCreate} disabled={isPending}>
|
|
66
|
+
{isPending ? "Creating..." : "Create Entity"}
|
|
67
|
+
</button>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Wallet Integration
|
|
73
|
+
|
|
74
|
+
The SDK is completely wallet-agnostic. You provide a wallet object implementing the `MyceliumWallet` interface, allowing integration with any wallet provider.
|
|
75
|
+
|
|
76
|
+
### MyceliumWallet Interface
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface MyceliumWallet {
|
|
80
|
+
/** The public key of the connected wallet (null if not connected) */
|
|
81
|
+
publicKey: PublicKey | null;
|
|
82
|
+
|
|
83
|
+
/** Signs a single transaction */
|
|
84
|
+
signTransaction<T extends Transaction | VersionedTransaction>(
|
|
85
|
+
transaction: T,
|
|
86
|
+
): Promise<T>;
|
|
87
|
+
|
|
88
|
+
/** Signs multiple transactions (optional) */
|
|
89
|
+
signAllTransactions?<T extends Transaction | VersionedTransaction>(
|
|
90
|
+
transactions: T[],
|
|
91
|
+
): Promise<T[]>;
|
|
92
|
+
|
|
93
|
+
/** Signs an arbitrary message (optional) */
|
|
94
|
+
signMessage?(message: Uint8Array): Promise<Uint8Array>;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Solana Wallet Adapter
|
|
99
|
+
|
|
100
|
+
If you're using [`@solana/wallet-adapter-react`](https://github.com/solana-labs/wallet-adapter):
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
"use client";
|
|
104
|
+
|
|
105
|
+
import { useWallet } from "@solana/wallet-adapter-react";
|
|
106
|
+
import { useConnection } from "@solana/wallet-adapter-react";
|
|
107
|
+
import { MyceliumIpProvider, type MyceliumWallet } from "@mycelium-ip/react";
|
|
108
|
+
import { useMemo } from "react";
|
|
109
|
+
|
|
110
|
+
function MyceliumProvider({ children }: { children: React.ReactNode }) {
|
|
111
|
+
const { connection } = useConnection();
|
|
112
|
+
const { publicKey, signTransaction, signAllTransactions, signMessage } =
|
|
113
|
+
useWallet();
|
|
114
|
+
|
|
115
|
+
// Adapt Wallet Adapter to MyceliumWallet interface
|
|
116
|
+
const wallet = useMemo<MyceliumWallet>(
|
|
117
|
+
() => ({
|
|
118
|
+
publicKey,
|
|
119
|
+
signTransaction: signTransaction!,
|
|
120
|
+
signAllTransactions,
|
|
121
|
+
signMessage,
|
|
122
|
+
}),
|
|
123
|
+
[publicKey, signTransaction, signAllTransactions, signMessage],
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Don't render provider until wallet is connected
|
|
127
|
+
if (!publicKey || !signTransaction) {
|
|
128
|
+
return <>{children}</>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<MyceliumIpProvider connection={connection} wallet={wallet}>
|
|
133
|
+
{children}
|
|
134
|
+
</MyceliumIpProvider>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Privy Embedded Wallet
|
|
140
|
+
|
|
141
|
+
If you're using [`@privy-io/react-auth`](https://docs.privy.io/) with Solana embedded wallets:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
"use client";
|
|
145
|
+
|
|
146
|
+
import { useSolanaWallets } from "@privy-io/react-auth/solana";
|
|
147
|
+
import { usePrivy } from "@privy-io/react-auth";
|
|
148
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
149
|
+
import { MyceliumIpProvider, type MyceliumWallet } from "@mycelium-ip/react";
|
|
150
|
+
import { useMemo } from "react";
|
|
151
|
+
|
|
152
|
+
function MyceliumPrivyProvider({ children }: { children: React.ReactNode }) {
|
|
153
|
+
const { ready, authenticated } = usePrivy();
|
|
154
|
+
const { wallets } = useSolanaWallets();
|
|
155
|
+
|
|
156
|
+
// Get the embedded wallet (or first available wallet)
|
|
157
|
+
const embeddedWallet =
|
|
158
|
+
wallets.find((w) => w.walletClientType === "privy") ?? wallets[0];
|
|
159
|
+
|
|
160
|
+
const connection = useMemo(
|
|
161
|
+
() => new Connection(process.env.NEXT_PUBLIC_SOLANA_RPC_URL!),
|
|
162
|
+
[],
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// Adapt Privy wallet to MyceliumWallet interface
|
|
166
|
+
const wallet = useMemo<MyceliumWallet | null>(() => {
|
|
167
|
+
if (!embeddedWallet?.address) return null;
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
publicKey: new PublicKey(embeddedWallet.address),
|
|
171
|
+
signTransaction: async (transaction) => {
|
|
172
|
+
return embeddedWallet.signTransaction(transaction);
|
|
173
|
+
},
|
|
174
|
+
signAllTransactions: async (transactions) => {
|
|
175
|
+
// Privy supports batch signing
|
|
176
|
+
const signed = [];
|
|
177
|
+
for (const tx of transactions) {
|
|
178
|
+
signed.push(await embeddedWallet.signTransaction(tx));
|
|
179
|
+
}
|
|
180
|
+
return signed;
|
|
181
|
+
},
|
|
182
|
+
signMessage: async (message) => {
|
|
183
|
+
const signature = await embeddedWallet.signMessage(message);
|
|
184
|
+
return signature;
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}, [embeddedWallet]);
|
|
188
|
+
|
|
189
|
+
// Wait for Privy to be ready and user to be authenticated
|
|
190
|
+
if (!ready || !authenticated || !wallet) {
|
|
191
|
+
return <>{children}</>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<MyceliumIpProvider connection={connection} wallet={wallet}>
|
|
196
|
+
{children}
|
|
197
|
+
</MyceliumIpProvider>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export default MyceliumPrivyProvider;
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Complete Privy Setup Example
|
|
205
|
+
|
|
206
|
+
Here's a complete example showing how to set up Privy with Mycelium in a Next.js App Router application:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
// app/providers.tsx
|
|
210
|
+
"use client";
|
|
211
|
+
|
|
212
|
+
import { PrivyProvider } from "@privy-io/react-auth";
|
|
213
|
+
import { toSolanaWalletConnectors } from "@privy-io/react-auth/solana";
|
|
214
|
+
import MyceliumPrivyProvider from "./MyceliumPrivyProvider";
|
|
215
|
+
|
|
216
|
+
const solanaConnectors = toSolanaWalletConnectors({
|
|
217
|
+
shouldAutoConnect: true,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
221
|
+
return (
|
|
222
|
+
<PrivyProvider
|
|
223
|
+
appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID!}
|
|
224
|
+
config={{
|
|
225
|
+
appearance: {
|
|
226
|
+
theme: "dark",
|
|
227
|
+
},
|
|
228
|
+
embeddedWallets: {
|
|
229
|
+
solana: {
|
|
230
|
+
createOnLogin: "users-without-wallets",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
externalWallets: {
|
|
234
|
+
solana: {
|
|
235
|
+
connectors: solanaConnectors,
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
}}
|
|
239
|
+
>
|
|
240
|
+
<MyceliumPrivyProvider>{children}</MyceliumPrivyProvider>
|
|
241
|
+
</PrivyProvider>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
// app/layout.tsx
|
|
248
|
+
import { Providers } from "./providers";
|
|
249
|
+
|
|
250
|
+
export default function RootLayout({
|
|
251
|
+
children,
|
|
252
|
+
}: {
|
|
253
|
+
children: React.ReactNode;
|
|
254
|
+
}) {
|
|
255
|
+
return (
|
|
256
|
+
<html lang="en">
|
|
257
|
+
<body>
|
|
258
|
+
<Providers>{children}</Providers>
|
|
259
|
+
</body>
|
|
260
|
+
</html>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Provider
|
|
266
|
+
|
|
267
|
+
### MyceliumIpProvider
|
|
268
|
+
|
|
269
|
+
The provider initializes the SDK and must wrap your application (or the part that uses Mycelium hooks).
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
<MyceliumIpProvider
|
|
273
|
+
connection={connection}
|
|
274
|
+
wallet={wallet}
|
|
275
|
+
queryClient={queryClient} // optional
|
|
276
|
+
options={{
|
|
277
|
+
confirmation: "confirmed",
|
|
278
|
+
devtools: true,
|
|
279
|
+
}}
|
|
280
|
+
>
|
|
281
|
+
<App />
|
|
282
|
+
</MyceliumIpProvider>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Props
|
|
286
|
+
|
|
287
|
+
| Prop | Type | Required | Description |
|
|
288
|
+
| ------------- | --------------------------- | -------- | ----------------------------------------------------------------------- |
|
|
289
|
+
| `connection` | `Connection` | Yes | Solana RPC connection |
|
|
290
|
+
| `wallet` | `MyceliumWallet` | Yes | Wallet implementing the MyceliumWallet interface |
|
|
291
|
+
| `queryClient` | `QueryClient` | No | Existing TanStack Query client. If omitted, a default client is created |
|
|
292
|
+
| `options` | `MyceliumIpProviderOptions` | No | Provider configuration options |
|
|
293
|
+
|
|
294
|
+
### Options
|
|
295
|
+
|
|
296
|
+
| Option | Type | Default | Description |
|
|
297
|
+
| -------------- | ------------ | ------------- | ---------------------------------------------------------------------------- |
|
|
298
|
+
| `confirmation` | `Commitment` | `"confirmed"` | Transaction confirmation level (`"processed"`, `"confirmed"`, `"finalized"`) |
|
|
299
|
+
| `devtools` | `boolean` | `false` | Enable TanStack Query devtools |
|
|
300
|
+
|
|
301
|
+
## Hooks Reference
|
|
302
|
+
|
|
303
|
+
All mutation hooks return TanStack Query's `UseMutationResult`, providing:
|
|
304
|
+
|
|
305
|
+
- `mutate` / `mutateAsync` — Execute the mutation
|
|
306
|
+
- `isPending` — Loading state
|
|
307
|
+
- `isSuccess` / `isError` — Result states
|
|
308
|
+
- `data` — Transaction result (signature)
|
|
309
|
+
- `error` — Error object if failed
|
|
310
|
+
- `reset` — Reset mutation state
|
|
311
|
+
|
|
312
|
+
### Entity Hooks
|
|
313
|
+
|
|
314
|
+
#### useCreateEntity
|
|
315
|
+
|
|
316
|
+
Creates a new entity in the protocol.
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
import { useCreateEntity } from "@mycelium-ip/react";
|
|
320
|
+
|
|
321
|
+
function CreateEntity() {
|
|
322
|
+
const { mutate, isPending } = useCreateEntity();
|
|
323
|
+
|
|
324
|
+
const handleCreate = () => {
|
|
325
|
+
mutate({
|
|
326
|
+
handle: new TextEncoder().encode("my-organization"),
|
|
327
|
+
additionalControllers: [], // Additional PublicKeys that can control this entity
|
|
328
|
+
signatureThreshold: 1, // Required signatures for multi-sig
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
return <button onClick={handleCreate}>Create Entity</button>;
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### useUpdateEntityControllers
|
|
337
|
+
|
|
338
|
+
Updates the controllers and signature threshold of an entity.
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
import { useUpdateEntityControllers } from "@mycelium-ip/react";
|
|
342
|
+
|
|
343
|
+
function UpdateControllers({ entityPubkey }: { entityPubkey: PublicKey }) {
|
|
344
|
+
const { mutate } = useUpdateEntityControllers();
|
|
345
|
+
|
|
346
|
+
const handleUpdate = () => {
|
|
347
|
+
mutate({
|
|
348
|
+
entity: entityPubkey,
|
|
349
|
+
newControllers: [controller1, controller2],
|
|
350
|
+
newThreshold: 2,
|
|
351
|
+
});
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
return <button onClick={handleUpdate}>Update Controllers</button>;
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### IP Hooks
|
|
359
|
+
|
|
360
|
+
#### useCreateIp
|
|
361
|
+
|
|
362
|
+
Creates a new IP (Intellectual Property) asset.
|
|
363
|
+
|
|
364
|
+
```tsx
|
|
365
|
+
import { useCreateIp } from "@mycelium-ip/react";
|
|
366
|
+
|
|
367
|
+
function CreateIp({ entityPubkey }: { entityPubkey: PublicKey }) {
|
|
368
|
+
const { mutate, isPending } = useCreateIp();
|
|
369
|
+
|
|
370
|
+
const handleCreate = () => {
|
|
371
|
+
mutate({
|
|
372
|
+
registrantEntity: entityPubkey,
|
|
373
|
+
content: new TextEncoder().encode("ipfs://QmXxx..."), // Content identifier
|
|
374
|
+
treasuryTokenAccount: treasuryAccount, // Protocol treasury token account
|
|
375
|
+
payerTokenAccount: payerAccount, // Payer's token account for fees
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
return <button onClick={handleCreate}>Register IP</button>;
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
#### useTransferIp
|
|
384
|
+
|
|
385
|
+
Transfers ownership of an IP to another entity.
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
import { useTransferIp } from "@mycelium-ip/react";
|
|
389
|
+
|
|
390
|
+
function TransferIp({ ipPubkey, currentOwner, newOwner }: Props) {
|
|
391
|
+
const { mutate } = useTransferIp();
|
|
392
|
+
|
|
393
|
+
const handleTransfer = () => {
|
|
394
|
+
mutate({
|
|
395
|
+
ip: ipPubkey,
|
|
396
|
+
currentOwnerEntity: currentOwner,
|
|
397
|
+
newOwnerEntity: newOwner,
|
|
398
|
+
});
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
return <button onClick={handleTransfer}>Transfer IP</button>;
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### License Hooks
|
|
406
|
+
|
|
407
|
+
#### useCreateLicense
|
|
408
|
+
|
|
409
|
+
Creates a license for an IP.
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
import { useCreateLicense } from "@mycelium-ip/react";
|
|
413
|
+
|
|
414
|
+
function CreateLicense({ ipPubkey, entityPubkey }: Props) {
|
|
415
|
+
const { mutate } = useCreateLicense();
|
|
416
|
+
|
|
417
|
+
const handleCreate = () => {
|
|
418
|
+
mutate({
|
|
419
|
+
originIp: ipPubkey,
|
|
420
|
+
ownerEntity: entityPubkey,
|
|
421
|
+
derivativesAllowed: true, // Whether derivatives can be created under this license
|
|
422
|
+
});
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
return <button onClick={handleCreate}>Create License</button>;
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
#### useUpdateLicense
|
|
430
|
+
|
|
431
|
+
Updates an existing license.
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
import { useUpdateLicense } from "@mycelium-ip/react";
|
|
435
|
+
|
|
436
|
+
function UpdateLicense({ ipPubkey, entityPubkey }: Props) {
|
|
437
|
+
const { mutate } = useUpdateLicense();
|
|
438
|
+
|
|
439
|
+
const handleUpdate = () => {
|
|
440
|
+
mutate({
|
|
441
|
+
originIp: ipPubkey,
|
|
442
|
+
authorityEntity: entityPubkey,
|
|
443
|
+
derivativesAllowed: false,
|
|
444
|
+
});
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
return <button onClick={handleUpdate}>Update License</button>;
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
#### useRevokeLicense
|
|
452
|
+
|
|
453
|
+
Revokes a license.
|
|
454
|
+
|
|
455
|
+
```tsx
|
|
456
|
+
import { useRevokeLicense } from "@mycelium-ip/react";
|
|
457
|
+
|
|
458
|
+
function RevokeLicense({ ipPubkey, entityPubkey }: Props) {
|
|
459
|
+
const { mutate } = useRevokeLicense();
|
|
460
|
+
|
|
461
|
+
const handleRevoke = () => {
|
|
462
|
+
mutate({
|
|
463
|
+
originIp: ipPubkey,
|
|
464
|
+
authorityEntity: entityPubkey,
|
|
465
|
+
});
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
return <button onClick={handleRevoke}>Revoke License</button>;
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Grant Hooks
|
|
473
|
+
|
|
474
|
+
#### useCreateLicenseGrant
|
|
475
|
+
|
|
476
|
+
Creates a license grant for another entity.
|
|
477
|
+
|
|
478
|
+
```tsx
|
|
479
|
+
import { useCreateLicenseGrant } from "@mycelium-ip/react";
|
|
480
|
+
|
|
481
|
+
function CreateGrant({ ipPubkey, authorityEntity, granteeEntity }: Props) {
|
|
482
|
+
const { mutate } = useCreateLicenseGrant();
|
|
483
|
+
|
|
484
|
+
const handleGrant = () => {
|
|
485
|
+
mutate({
|
|
486
|
+
originIp: ipPubkey,
|
|
487
|
+
authorityEntity: authorityEntity,
|
|
488
|
+
granteeEntity: granteeEntity,
|
|
489
|
+
expiration: Math.floor(Date.now() / 1000) + 86400 * 365, // 1 year from now
|
|
490
|
+
});
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
return <button onClick={handleGrant}>Grant License</button>;
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
#### useRevokeLicenseGrant
|
|
498
|
+
|
|
499
|
+
Revokes a license grant.
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
import { useRevokeLicenseGrant } from "@mycelium-ip/react";
|
|
503
|
+
|
|
504
|
+
function RevokeGrant({ ipPubkey, authorityEntity, granteeEntity }: Props) {
|
|
505
|
+
const { mutate } = useRevokeLicenseGrant();
|
|
506
|
+
|
|
507
|
+
const handleRevoke = () => {
|
|
508
|
+
mutate({
|
|
509
|
+
originIp: ipPubkey,
|
|
510
|
+
authorityEntity: authorityEntity,
|
|
511
|
+
granteeEntity: granteeEntity,
|
|
512
|
+
});
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
return <button onClick={handleRevoke}>Revoke Grant</button>;
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Derivative Hooks
|
|
520
|
+
|
|
521
|
+
#### useCreateDerivativeLink
|
|
522
|
+
|
|
523
|
+
Creates a derivative link between two IPs.
|
|
524
|
+
|
|
525
|
+
```tsx
|
|
526
|
+
import { useCreateDerivativeLink } from "@mycelium-ip/react";
|
|
527
|
+
|
|
528
|
+
function CreateDerivative({ parentIp, childIp, childOwner }: Props) {
|
|
529
|
+
const { mutate } = useCreateDerivativeLink();
|
|
530
|
+
|
|
531
|
+
const handleCreate = () => {
|
|
532
|
+
mutate({
|
|
533
|
+
parentIp: parentIp,
|
|
534
|
+
childIp: childIp,
|
|
535
|
+
childOwnerEntity: childOwner,
|
|
536
|
+
licenseGrant: grantPubkey,
|
|
537
|
+
license: licensePubkey,
|
|
538
|
+
});
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
return <button onClick={handleCreate}>Link Derivative</button>;
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
#### useUpdateDerivativeLicense
|
|
546
|
+
|
|
547
|
+
Updates the license on a derivative link.
|
|
548
|
+
|
|
549
|
+
```tsx
|
|
550
|
+
import { useUpdateDerivativeLicense } from "@mycelium-ip/react";
|
|
551
|
+
|
|
552
|
+
function UpdateDerivativeLicense({ parentIp, childIp, childOwner }: Props) {
|
|
553
|
+
const { mutate } = useUpdateDerivativeLicense();
|
|
554
|
+
|
|
555
|
+
const handleUpdate = () => {
|
|
556
|
+
mutate({
|
|
557
|
+
parentIp: parentIp,
|
|
558
|
+
childIp: childIp,
|
|
559
|
+
childOwnerEntity: childOwner,
|
|
560
|
+
newLicenseGrant: newGrantPubkey,
|
|
561
|
+
newLicense: newLicensePubkey,
|
|
562
|
+
});
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
return <button onClick={handleUpdate}>Update Derivative License</button>;
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Metadata Hooks
|
|
570
|
+
|
|
571
|
+
#### useCreateMetadataSchema
|
|
572
|
+
|
|
573
|
+
Creates a new metadata schema.
|
|
574
|
+
|
|
575
|
+
```tsx
|
|
576
|
+
import { useCreateMetadataSchema } from "@mycelium-ip/react";
|
|
577
|
+
|
|
578
|
+
function CreateSchema() {
|
|
579
|
+
const { mutate } = useCreateMetadataSchema();
|
|
580
|
+
|
|
581
|
+
const handleCreate = () => {
|
|
582
|
+
mutate({
|
|
583
|
+
id: new TextEncoder().encode("artwork-schema"),
|
|
584
|
+
version: 1,
|
|
585
|
+
data: new TextEncoder().encode(
|
|
586
|
+
JSON.stringify({
|
|
587
|
+
type: "object",
|
|
588
|
+
properties: {
|
|
589
|
+
title: { type: "string" },
|
|
590
|
+
artist: { type: "string" },
|
|
591
|
+
},
|
|
592
|
+
}),
|
|
593
|
+
),
|
|
594
|
+
cid: new TextEncoder().encode("ipfs://QmSchema..."),
|
|
595
|
+
});
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
return <button onClick={handleCreate}>Create Schema</button>;
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
#### useCreateEntityMetadata
|
|
603
|
+
|
|
604
|
+
Creates metadata for an entity.
|
|
605
|
+
|
|
606
|
+
```tsx
|
|
607
|
+
import { useCreateEntityMetadata } from "@mycelium-ip/react";
|
|
608
|
+
|
|
609
|
+
function CreateEntityMetadata({ entityPubkey, schemaPubkey }: Props) {
|
|
610
|
+
const { mutate } = useCreateEntityMetadata();
|
|
611
|
+
|
|
612
|
+
const handleCreate = () => {
|
|
613
|
+
mutate({
|
|
614
|
+
entity: entityPubkey,
|
|
615
|
+
schema: schemaPubkey,
|
|
616
|
+
revision: 1,
|
|
617
|
+
data: new TextEncoder().encode(JSON.stringify({ name: "My Org" })),
|
|
618
|
+
cid: new TextEncoder().encode("ipfs://QmMetadata..."),
|
|
619
|
+
});
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
return <button onClick={handleCreate}>Add Metadata</button>;
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
#### useCreateIpMetadata
|
|
627
|
+
|
|
628
|
+
Creates metadata for an IP.
|
|
629
|
+
|
|
630
|
+
```tsx
|
|
631
|
+
import { useCreateIpMetadata } from "@mycelium-ip/react";
|
|
632
|
+
|
|
633
|
+
function CreateIpMetadata({ ipPubkey, entityPubkey, schemaPubkey }: Props) {
|
|
634
|
+
const { mutate } = useCreateIpMetadata();
|
|
635
|
+
|
|
636
|
+
const handleCreate = () => {
|
|
637
|
+
mutate({
|
|
638
|
+
ip: ipPubkey,
|
|
639
|
+
ownerEntity: entityPubkey,
|
|
640
|
+
schema: schemaPubkey,
|
|
641
|
+
revision: 1,
|
|
642
|
+
data: new TextEncoder().encode(
|
|
643
|
+
JSON.stringify({
|
|
644
|
+
title: "My Artwork",
|
|
645
|
+
artist: "Anonymous",
|
|
646
|
+
}),
|
|
647
|
+
),
|
|
648
|
+
cid: new TextEncoder().encode("ipfs://QmIpMetadata..."),
|
|
649
|
+
});
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
return <button onClick={handleCreate}>Add IP Metadata</button>;
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### Accessor Hooks
|
|
657
|
+
|
|
658
|
+
These hooks provide access to the underlying SDK and context values.
|
|
659
|
+
|
|
660
|
+
```tsx
|
|
661
|
+
import {
|
|
662
|
+
useMyceliumClient,
|
|
663
|
+
useMyceliumConnection,
|
|
664
|
+
useMyceliumWallet,
|
|
665
|
+
useMyceliumContext,
|
|
666
|
+
} from "@mycelium-ip/react";
|
|
667
|
+
|
|
668
|
+
function MyComponent() {
|
|
669
|
+
// Get the core SDK client for direct access
|
|
670
|
+
const client = useMyceliumClient();
|
|
671
|
+
|
|
672
|
+
// Get the Solana connection
|
|
673
|
+
const connection = useMyceliumConnection();
|
|
674
|
+
|
|
675
|
+
// Get the wallet
|
|
676
|
+
const wallet = useMyceliumWallet();
|
|
677
|
+
|
|
678
|
+
// Get everything at once
|
|
679
|
+
const { client, connection, wallet, confirmation } = useMyceliumContext();
|
|
680
|
+
}
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
## Transaction Results
|
|
684
|
+
|
|
685
|
+
All mutation hooks return a `TransactionResult` on success:
|
|
686
|
+
|
|
687
|
+
```typescript
|
|
688
|
+
interface TransactionResult {
|
|
689
|
+
signature: string; // The transaction signature
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### Handling Results
|
|
694
|
+
|
|
695
|
+
```tsx
|
|
696
|
+
function CreateEntityWithFeedback() {
|
|
697
|
+
const { mutate, isPending, isSuccess, isError, data, error } =
|
|
698
|
+
useCreateEntity();
|
|
699
|
+
|
|
700
|
+
const handleCreate = () => {
|
|
701
|
+
mutate(
|
|
702
|
+
{
|
|
703
|
+
handle: new TextEncoder().encode("my-entity"),
|
|
704
|
+
additionalControllers: [],
|
|
705
|
+
signatureThreshold: 1,
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
onSuccess: (result) => {
|
|
709
|
+
console.log("Transaction signature:", result.signature);
|
|
710
|
+
// Show success toast, redirect, etc.
|
|
711
|
+
},
|
|
712
|
+
onError: (error) => {
|
|
713
|
+
console.error("Transaction failed:", error.message);
|
|
714
|
+
// Show error toast
|
|
715
|
+
},
|
|
716
|
+
},
|
|
717
|
+
);
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
return (
|
|
721
|
+
<div>
|
|
722
|
+
<button onClick={handleCreate} disabled={isPending}>
|
|
723
|
+
{isPending ? "Creating..." : "Create Entity"}
|
|
724
|
+
</button>
|
|
725
|
+
{isSuccess && <p>Success! Signature: {data.signature}</p>}
|
|
726
|
+
{isError && <p>Error: {error.message}</p>}
|
|
727
|
+
</div>
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
### Async/Await Pattern
|
|
733
|
+
|
|
734
|
+
```tsx
|
|
735
|
+
async function handleCreateEntity() {
|
|
736
|
+
const { mutateAsync } = useCreateEntity();
|
|
737
|
+
|
|
738
|
+
try {
|
|
739
|
+
const result = await mutateAsync({
|
|
740
|
+
handle: new TextEncoder().encode("my-entity"),
|
|
741
|
+
additionalControllers: [],
|
|
742
|
+
signatureThreshold: 1,
|
|
743
|
+
});
|
|
744
|
+
console.log("Created with signature:", result.signature);
|
|
745
|
+
} catch (error) {
|
|
746
|
+
console.error("Failed to create entity:", error);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
## Query Keys
|
|
752
|
+
|
|
753
|
+
The SDK exports `queryKeys` for custom cache invalidation or building custom queries:
|
|
754
|
+
|
|
755
|
+
```tsx
|
|
756
|
+
import { queryKeys, useMyceliumClient } from "@mycelium-ip/react";
|
|
757
|
+
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
758
|
+
|
|
759
|
+
// Available query keys
|
|
760
|
+
queryKeys.all; // ["mycelium"]
|
|
761
|
+
queryKeys.entities(); // ["mycelium", "entities"]
|
|
762
|
+
queryKeys.entity(id); // ["mycelium", "entities", id]
|
|
763
|
+
queryKeys.ips(); // ["mycelium", "ips"]
|
|
764
|
+
queryKeys.ip(id); // ["mycelium", "ips", id]
|
|
765
|
+
queryKeys.licenses(); // ["mycelium", "licenses"]
|
|
766
|
+
queryKeys.license(id); // ["mycelium", "licenses", id]
|
|
767
|
+
queryKeys.grants(); // ["mycelium", "grants"]
|
|
768
|
+
queryKeys.grant(id); // ["mycelium", "grants", id]
|
|
769
|
+
queryKeys.metadata(); // ["mycelium", "metadata"]
|
|
770
|
+
queryKeys.derivatives(); // ["mycelium", "derivatives"]
|
|
771
|
+
queryKeys.derivative(id); // ["mycelium", "derivatives", id]
|
|
772
|
+
|
|
773
|
+
// Manual cache invalidation
|
|
774
|
+
function RefreshButton() {
|
|
775
|
+
const queryClient = useQueryClient();
|
|
776
|
+
|
|
777
|
+
return (
|
|
778
|
+
<button
|
|
779
|
+
onClick={() =>
|
|
780
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.ips() })
|
|
781
|
+
}
|
|
782
|
+
>
|
|
783
|
+
Refresh IPs
|
|
784
|
+
</button>
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
## Advanced Usage
|
|
790
|
+
|
|
791
|
+
### Custom QueryClient
|
|
792
|
+
|
|
793
|
+
Provide your own QueryClient for custom caching behavior:
|
|
794
|
+
|
|
795
|
+
```tsx
|
|
796
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
797
|
+
import { MyceliumIpProvider } from "@mycelium-ip/react";
|
|
798
|
+
|
|
799
|
+
const queryClient = new QueryClient({
|
|
800
|
+
defaultOptions: {
|
|
801
|
+
queries: {
|
|
802
|
+
staleTime: 1000 * 60 * 10, // 10 minutes
|
|
803
|
+
gcTime: 1000 * 60 * 60, // 1 hour
|
|
804
|
+
retry: 3,
|
|
805
|
+
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
|
|
806
|
+
},
|
|
807
|
+
mutations: {
|
|
808
|
+
retry: 1,
|
|
809
|
+
},
|
|
810
|
+
},
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
function App() {
|
|
814
|
+
return (
|
|
815
|
+
<MyceliumIpProvider
|
|
816
|
+
connection={connection}
|
|
817
|
+
wallet={wallet}
|
|
818
|
+
queryClient={queryClient}
|
|
819
|
+
>
|
|
820
|
+
<YourApp />
|
|
821
|
+
</MyceliumIpProvider>
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### TypeScript Types
|
|
827
|
+
|
|
828
|
+
All parameter types are re-exported from `@mycelium-ip/core-sdk`:
|
|
829
|
+
|
|
830
|
+
```typescript
|
|
831
|
+
import type {
|
|
832
|
+
CreateEntityParams,
|
|
833
|
+
CreateIpParams,
|
|
834
|
+
CreateLicenseParams,
|
|
835
|
+
CreateLicenseGrantParams,
|
|
836
|
+
// ... etc
|
|
837
|
+
} from "@mycelium-ip/core-sdk";
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
### Next.js App Router
|
|
841
|
+
|
|
842
|
+
The provider is already marked with `"use client"`. In Next.js App Router, create a client component for the provider:
|
|
843
|
+
|
|
844
|
+
```tsx
|
|
845
|
+
// app/providers.tsx
|
|
846
|
+
"use client";
|
|
847
|
+
|
|
848
|
+
import { MyceliumIpProvider } from "@mycelium-ip/react";
|
|
849
|
+
// ... wallet setup
|
|
850
|
+
|
|
851
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
852
|
+
// ... setup logic
|
|
853
|
+
return (
|
|
854
|
+
<MyceliumIpProvider connection={connection} wallet={wallet}>
|
|
855
|
+
{children}
|
|
856
|
+
</MyceliumIpProvider>
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
```tsx
|
|
862
|
+
// app/layout.tsx
|
|
863
|
+
import { Providers } from "./providers";
|
|
864
|
+
|
|
865
|
+
export default function RootLayout({
|
|
866
|
+
children,
|
|
867
|
+
}: {
|
|
868
|
+
children: React.ReactNode;
|
|
869
|
+
}) {
|
|
870
|
+
return (
|
|
871
|
+
<html>
|
|
872
|
+
<body>
|
|
873
|
+
<Providers>{children}</Providers>
|
|
874
|
+
</body>
|
|
875
|
+
</html>
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
## API Reference
|
|
881
|
+
|
|
882
|
+
### Exports
|
|
883
|
+
|
|
884
|
+
```typescript
|
|
885
|
+
// Provider
|
|
886
|
+
export { MyceliumIpProvider } from "@mycelium-ip/react";
|
|
887
|
+
export type {
|
|
888
|
+
MyceliumIpProviderProps,
|
|
889
|
+
MyceliumIpProviderOptions,
|
|
890
|
+
MyceliumContextValue,
|
|
891
|
+
} from "@mycelium-ip/react";
|
|
892
|
+
|
|
893
|
+
// Wallet type
|
|
894
|
+
export type { MyceliumWallet } from "@mycelium-ip/react";
|
|
895
|
+
|
|
896
|
+
// Transaction utilities
|
|
897
|
+
export {
|
|
898
|
+
executeTransaction,
|
|
899
|
+
executeTransactionWithInstructions,
|
|
900
|
+
} from "@mycelium-ip/react";
|
|
901
|
+
export type { TransactionResult } from "@mycelium-ip/react";
|
|
902
|
+
|
|
903
|
+
// Query keys
|
|
904
|
+
export { queryKeys } from "@mycelium-ip/react";
|
|
905
|
+
|
|
906
|
+
// Accessor hooks
|
|
907
|
+
export {
|
|
908
|
+
useMyceliumClient,
|
|
909
|
+
useMyceliumConnection,
|
|
910
|
+
useMyceliumWallet,
|
|
911
|
+
useMyceliumContext,
|
|
912
|
+
} from "@mycelium-ip/react";
|
|
913
|
+
|
|
914
|
+
// Entity hooks
|
|
915
|
+
export {
|
|
916
|
+
useCreateEntity,
|
|
917
|
+
useUpdateEntityControllers,
|
|
918
|
+
} from "@mycelium-ip/react";
|
|
919
|
+
|
|
920
|
+
// IP hooks
|
|
921
|
+
export { useCreateIp, useTransferIp } from "@mycelium-ip/react";
|
|
922
|
+
|
|
923
|
+
// License hooks
|
|
924
|
+
export {
|
|
925
|
+
useCreateLicense,
|
|
926
|
+
useUpdateLicense,
|
|
927
|
+
useRevokeLicense,
|
|
928
|
+
} from "@mycelium-ip/react";
|
|
929
|
+
|
|
930
|
+
// Grant hooks
|
|
931
|
+
export {
|
|
932
|
+
useCreateLicenseGrant,
|
|
933
|
+
useRevokeLicenseGrant,
|
|
934
|
+
} from "@mycelium-ip/react";
|
|
935
|
+
|
|
936
|
+
// Derivative hooks
|
|
937
|
+
export {
|
|
938
|
+
useCreateDerivativeLink,
|
|
939
|
+
useUpdateDerivativeLicense,
|
|
940
|
+
} from "@mycelium-ip/react";
|
|
941
|
+
|
|
942
|
+
// Metadata hooks
|
|
943
|
+
export {
|
|
944
|
+
useCreateMetadataSchema,
|
|
945
|
+
useCreateEntityMetadata,
|
|
946
|
+
useCreateIpMetadata,
|
|
947
|
+
} from "@mycelium-ip/react";
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
## License
|
|
951
|
+
|
|
952
|
+
MIT
|