@qubic.ts/react 0.1.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.
Files changed (44) hide show
  1. package/fixtures/next-boundary/client-node-leak.tsx +5 -0
  2. package/fixtures/next-boundary/client-ok.tsx +8 -0
  3. package/fixtures/next-boundary/server-ok.ts +5 -0
  4. package/package.json +47 -0
  5. package/scripts/verify-next-boundary.mjs +63 -0
  6. package/src/browser.ts +27 -0
  7. package/src/contract-types.ts +309 -0
  8. package/src/contracts-types.typecheck.ts +85 -0
  9. package/src/hooks/contract-hooks.test.tsx +312 -0
  10. package/src/hooks/read-hooks.test.tsx +339 -0
  11. package/src/hooks/send-hooks.test.tsx +247 -0
  12. package/src/hooks/use-balance.ts +27 -0
  13. package/src/hooks/use-contract-mutation.ts +50 -0
  14. package/src/hooks/use-contract-query.ts +71 -0
  15. package/src/hooks/use-contract.ts +231 -0
  16. package/src/hooks/use-last-processed-tick.ts +21 -0
  17. package/src/hooks/use-send-and-confirm.ts +19 -0
  18. package/src/hooks/use-send.ts +21 -0
  19. package/src/hooks/use-tick-info.ts +16 -0
  20. package/src/hooks/use-transactions.ts +97 -0
  21. package/src/index.ts +67 -0
  22. package/src/node.ts +21 -0
  23. package/src/providers/query-provider.test.tsx +25 -0
  24. package/src/providers/query-provider.tsx +13 -0
  25. package/src/providers/sdk-provider.test.tsx +54 -0
  26. package/src/providers/sdk-provider.tsx +83 -0
  27. package/src/providers/wallet-provider.test.tsx +82 -0
  28. package/src/providers/wallet-provider.tsx +209 -0
  29. package/src/query/keys.ts +9 -0
  30. package/src/typecheck-stubs/contracts.d.ts +77 -0
  31. package/src/typecheck-stubs/sdk.d.ts +254 -0
  32. package/src/vault/browser.ts +52 -0
  33. package/src/vault/node.ts +39 -0
  34. package/src/vault/runtime-boundary.test.ts +22 -0
  35. package/src/wallet/metamask-snap.test.ts +73 -0
  36. package/src/wallet/metamask-snap.ts +121 -0
  37. package/src/wallet/types.ts +55 -0
  38. package/src/wallet/utils.ts +14 -0
  39. package/src/wallet/vault.test.ts +98 -0
  40. package/src/wallet/vault.ts +70 -0
  41. package/src/wallet/walletconnect.test.ts +141 -0
  42. package/src/wallet/walletconnect.ts +218 -0
  43. package/tsconfig.json +14 -0
  44. package/tsconfig.typecheck.json +12 -0
@@ -0,0 +1,5 @@
1
+ "use client";
2
+
3
+ import { openNodeVault } from "@qubic.ts/react/node";
4
+
5
+ export const nodeOnlyReference = openNodeVault;
@@ -0,0 +1,8 @@
1
+ "use client";
2
+
3
+ import { useTickInfo } from "@qubic.ts/react/browser";
4
+
5
+ export function ClientOk() {
6
+ useTickInfo();
7
+ return null;
8
+ }
@@ -0,0 +1,5 @@
1
+ import { openNodeVault } from "@qubic.ts/react/node";
2
+
3
+ export async function serverAction(path: string, passphrase: string) {
4
+ return openNodeVault({ path, passphrase });
5
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@qubic.ts/react",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./src/index.ts",
8
+ "import": "./src/index.ts",
9
+ "default": "./src/index.ts"
10
+ },
11
+ "./browser": {
12
+ "types": "./src/browser.ts",
13
+ "import": "./src/browser.ts",
14
+ "default": "./src/browser.ts"
15
+ },
16
+ "./node": {
17
+ "types": "./src/node.ts",
18
+ "import": "./src/node.ts",
19
+ "default": "./src/node.ts"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "dependencies": {
24
+ "@metamask/providers": "^22.1.1",
25
+ "@tanstack/react-query": "^5.90.19",
26
+ "@walletconnect/sign-client": "^2.22.4",
27
+ "@walletconnect/types": "^2.22.4",
28
+ "@qubic.ts/contracts": "^0.1.0",
29
+ "@qubic.ts/core": "^0.1.0",
30
+ "@qubic.ts/sdk": "^0.1.0",
31
+ "react": "^18.3.1",
32
+ "react-dom": "^18.3.1"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "^18.3.27",
36
+ "@types/react-dom": "^18.3.7",
37
+ "@types/react-test-renderer": "^18.3.1",
38
+ "react-test-renderer": "^18.3.1"
39
+ },
40
+ "scripts": {
41
+ "build": "echo \"qubic-ts-react build pending\"",
42
+ "typecheck": "bunx tsc -p tsconfig.typecheck.json --noEmit",
43
+ "verify:next": "bun ./scripts/verify-next-boundary.mjs",
44
+ "check": "bun run typecheck && bun run test && bun run verify:next",
45
+ "test": "bun test ./src/**/*.test.ts ./src/**/*.test.tsx"
46
+ }
47
+ }
@@ -0,0 +1,63 @@
1
+ import { mkdtempSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+
5
+ const fixtureDir = resolve(process.cwd(), "fixtures/next-boundary");
6
+ const outRoot = mkdtempSync(join(tmpdir(), "qubic-ts-react-next-boundary-"));
7
+
8
+ try {
9
+ await assertBuildSuccess("client-ok.tsx", "browser");
10
+ await assertBuildSuccess("server-ok.ts", "node");
11
+ await assertBuildFailure("client-node-leak.tsx", "browser");
12
+ console.log("Next boundary fixture passed.");
13
+ } finally {
14
+ rmSync(outRoot, { recursive: true, force: true });
15
+ }
16
+
17
+ async function assertBuildSuccess(entryFile, target) {
18
+ let result;
19
+ try {
20
+ result = await Bun.build({
21
+ entrypoints: [resolve(fixtureDir, entryFile)],
22
+ outdir: resolve(outRoot, `${entryFile}.${target}`),
23
+ target,
24
+ format: "esm",
25
+ splitting: false,
26
+ sourcemap: "none",
27
+ minify: false,
28
+ });
29
+ } catch (error) {
30
+ throw new Error(`Expected build to succeed for ${entryFile} (${target})\n${String(error)}`);
31
+ }
32
+
33
+ if (!result.success) {
34
+ throw new Error(
35
+ [
36
+ `Expected build to succeed for ${entryFile} (${target})`,
37
+ ...result.logs.map((log) => log.message),
38
+ ].join("\n"),
39
+ );
40
+ }
41
+ }
42
+
43
+ async function assertBuildFailure(entryFile, target) {
44
+ try {
45
+ const result = await Bun.build({
46
+ entrypoints: [resolve(fixtureDir, entryFile)],
47
+ outdir: resolve(outRoot, `${entryFile}.${target}`),
48
+ target,
49
+ format: "esm",
50
+ splitting: false,
51
+ sourcemap: "none",
52
+ minify: false,
53
+ });
54
+
55
+ if (result.success) {
56
+ throw new Error(`Expected build to fail for ${entryFile} (${target})`);
57
+ }
58
+ return;
59
+ } catch {
60
+ // Build failed as expected.
61
+ return;
62
+ }
63
+ }
package/src/browser.ts ADDED
@@ -0,0 +1,27 @@
1
+ export * from "./index.js";
2
+ export type {
3
+ OpenSeedVaultBrowserInput,
4
+ SeedVault,
5
+ VaultEntry,
6
+ VaultEntryEncrypted,
7
+ VaultExport,
8
+ VaultHeader,
9
+ VaultKdfParams,
10
+ VaultStore,
11
+ VaultSummary,
12
+ } from "@qubic.ts/sdk/browser";
13
+ export {
14
+ VaultEntryExistsError,
15
+ VaultEntryNotFoundError,
16
+ VaultError,
17
+ VaultInvalidPassphraseError,
18
+ VaultNotFoundError,
19
+ } from "@qubic.ts/sdk/browser";
20
+ export type { CreateBrowserVaultInput } from "./vault/browser.js";
21
+ export {
22
+ createBrowserVault,
23
+ createLocalStorageVaultStore,
24
+ createMemoryVaultStore,
25
+ importBrowserVault,
26
+ openBrowserVault,
27
+ } from "./vault/browser.js";
@@ -0,0 +1,309 @@
1
+ import type { ContractDefinition, ContractsRegistry } from "@qubic.ts/contracts";
2
+ import type { QueryRawResult, SeedSourceInput, SendTransactionResult } from "@qubic.ts/sdk";
3
+
4
+ export type ContractCodecSchema = Readonly<{
5
+ functions?: Readonly<Record<string, Readonly<{ input: unknown; output: unknown }>>>;
6
+ procedures?: Readonly<Record<string, Readonly<{ input: unknown; output: unknown }>>>;
7
+ }>;
8
+
9
+ export type ContractRegistrySchema = Readonly<Record<string, ContractCodecSchema>>;
10
+
11
+ type SchemaFunctions<S extends ContractCodecSchema> = NonNullable<S["functions"]>;
12
+ type SchemaProcedures<S extends ContractCodecSchema> = NonNullable<S["procedures"]>;
13
+
14
+ type ContractEntryLike = Readonly<{
15
+ kind: "function" | "procedure";
16
+ name: string;
17
+ inputTypeName?: string;
18
+ outputTypeName?: string;
19
+ }>;
20
+
21
+ type ContractIoFieldLike = Readonly<{
22
+ name: string;
23
+ type: string;
24
+ }>;
25
+
26
+ type ContractIoTypeLike =
27
+ | Readonly<{
28
+ kind: "struct";
29
+ name: string;
30
+ fields: readonly ContractIoFieldLike[];
31
+ }>
32
+ | Readonly<{
33
+ kind: "alias";
34
+ name: string;
35
+ target: string;
36
+ }>;
37
+
38
+ type ContractDefinitionLike = Readonly<{
39
+ name: string;
40
+ address?: string;
41
+ entries: readonly ContractEntryLike[];
42
+ ioTypes?: readonly ContractIoTypeLike[];
43
+ }>;
44
+
45
+ type RegistryLike = Readonly<{
46
+ contracts: readonly ContractDefinitionLike[];
47
+ }>;
48
+
49
+ type TrimLeft<Value extends string> = Value extends ` ${infer Rest}` ? TrimLeft<Rest> : Value;
50
+ type TrimRight<Value extends string> = Value extends `${infer Rest} ` ? TrimRight<Rest> : Value;
51
+ type Trim<Value extends string> = TrimLeft<TrimRight<Value>>;
52
+ type TailSegment<Value extends string> = Value extends `${string}::${infer Rest}`
53
+ ? TailSegment<Rest>
54
+ : Value;
55
+ type DecrementMap = [0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
56
+ type Dec<Depth extends number> = Depth extends keyof DecrementMap ? DecrementMap[Depth] : 0;
57
+
58
+ type PrimitiveTypeValue<TypeName extends string> = TypeName extends
59
+ | "uint8"
60
+ | "uint16"
61
+ | "uint32"
62
+ | "sint8"
63
+ | "sint16"
64
+ | "sint32"
65
+ | "bit"
66
+ | "char"
67
+ ? number
68
+ : TypeName extends "uint64" | "sint64"
69
+ ? bigint
70
+ : TypeName extends "bool"
71
+ ? boolean
72
+ : TypeName extends "id"
73
+ ? string
74
+ : TypeName extends "m256i"
75
+ ? Uint8Array
76
+ : never;
77
+
78
+ type ExactIoType<Contract extends ContractDefinitionLike, TypeName extends string> = Extract<
79
+ NonNullable<Contract["ioTypes"]>[number],
80
+ { name: TypeName }
81
+ >;
82
+
83
+ type LookupIoType<Contract extends ContractDefinitionLike, TypeName extends string> = [
84
+ ExactIoType<Contract, TypeName>,
85
+ ] extends [never]
86
+ ? ExactIoType<Contract, TailSegment<TypeName>>
87
+ : ExactIoType<Contract, TypeName>;
88
+
89
+ type StructValueFromFields<
90
+ Contract extends ContractDefinitionLike,
91
+ Fields extends readonly ContractIoFieldLike[],
92
+ Depth extends number,
93
+ > = Fields extends readonly []
94
+ ? Record<string, never>
95
+ : {
96
+ [Field in Fields[number] as Field["name"]]: ResolveContractType<
97
+ Contract,
98
+ Field["type"],
99
+ Depth
100
+ >;
101
+ };
102
+
103
+ type ResolveDeclaredContractType<
104
+ Contract extends ContractDefinitionLike,
105
+ TypeName extends string,
106
+ Depth extends number,
107
+ > = LookupIoType<Contract, TypeName> extends infer Io
108
+ ? Io extends { kind: "alias"; target: infer Target extends string }
109
+ ? ResolveContractType<Contract, Target, Dec<Depth>>
110
+ : Io extends { kind: "struct"; fields: infer Fields extends readonly ContractIoFieldLike[] }
111
+ ? StructValueFromFields<Contract, Fields, Dec<Depth>>
112
+ : unknown
113
+ : unknown;
114
+
115
+ type ResolveContractType<
116
+ Contract extends ContractDefinitionLike,
117
+ TypeName extends string,
118
+ Depth extends number = 6,
119
+ > = Depth extends 0
120
+ ? unknown
121
+ : PrimitiveTypeValue<Trim<TypeName>> extends never
122
+ ? Trim<TypeName> extends `Array<${infer ElementType}, ${string}>`
123
+ ? ReadonlyArray<ResolveContractType<Contract, Trim<ElementType>, Dec<Depth>>>
124
+ : ResolveDeclaredContractType<Contract, Trim<TypeName>, Depth>
125
+ : PrimitiveTypeValue<Trim<TypeName>>;
126
+
127
+ type EntryFunctionMap<
128
+ Entry extends ContractEntryLike,
129
+ Contract extends ContractDefinitionLike,
130
+ > = Entry extends { kind: "function"; name: infer Name extends string }
131
+ ? Name extends string
132
+ ? Readonly<
133
+ Record<
134
+ Name,
135
+ Readonly<{
136
+ input: Entry extends { inputTypeName: infer InputTypeName extends string }
137
+ ? ResolveContractType<Contract, InputTypeName>
138
+ : unknown;
139
+ output: Entry extends { outputTypeName: infer OutputTypeName extends string }
140
+ ? ResolveContractType<Contract, OutputTypeName>
141
+ : unknown;
142
+ }>
143
+ >
144
+ >
145
+ : Readonly<Record<never, never>>
146
+ : Readonly<Record<never, never>>;
147
+
148
+ type EntryProcedureMap<
149
+ Entry extends ContractEntryLike,
150
+ Contract extends ContractDefinitionLike,
151
+ > = Entry extends { kind: "procedure"; name: infer Name extends string }
152
+ ? Name extends string
153
+ ? Readonly<
154
+ Record<
155
+ Name,
156
+ Readonly<{
157
+ input: Entry extends { inputTypeName: infer InputTypeName extends string }
158
+ ? ResolveContractType<Contract, InputTypeName>
159
+ : unknown;
160
+ output: Entry extends { outputTypeName: infer OutputTypeName extends string }
161
+ ? ResolveContractType<Contract, OutputTypeName>
162
+ : unknown;
163
+ }>
164
+ >
165
+ >
166
+ : Readonly<Record<never, never>>
167
+ : Readonly<Record<never, never>>;
168
+
169
+ type UnionToIntersection<Value> = (Value extends unknown ? (arg: Value) => void : never) extends (
170
+ arg: infer Intersection,
171
+ ) => void
172
+ ? Intersection
173
+ : never;
174
+
175
+ type Merge<Value> = { [Key in keyof Value]: Value[Key] };
176
+
177
+ type ContractSchemaFromDefinition<Definition extends ContractDefinitionLike> = Readonly<{
178
+ __meta: Readonly<{
179
+ address: Definition extends { address: infer Address extends string } ? Address : string;
180
+ }>;
181
+ functions: Merge<
182
+ UnionToIntersection<EntryFunctionMap<Definition["entries"][number], Definition>>
183
+ >;
184
+ procedures: Merge<
185
+ UnionToIntersection<EntryProcedureMap<Definition["entries"][number], Definition>>
186
+ >;
187
+ }>;
188
+
189
+ export type ContractRegistryToSchema<Registry extends RegistryLike> = Readonly<{
190
+ [Definition in Registry["contracts"][number] as Definition["name"]]: ContractSchemaFromDefinition<Definition>;
191
+ }>;
192
+
193
+ export type ContractFunctionName<S extends ContractCodecSchema> = keyof SchemaFunctions<S> & string;
194
+ export type ContractProcedureName<S extends ContractCodecSchema> = keyof SchemaProcedures<S> &
195
+ string;
196
+
197
+ export type ContractFunctionInput<
198
+ S extends ContractCodecSchema,
199
+ Name extends string,
200
+ > = Name extends keyof SchemaFunctions<S>
201
+ ? SchemaFunctions<S>[Name] extends { input: infer Input }
202
+ ? Input
203
+ : unknown
204
+ : unknown;
205
+
206
+ export type ContractFunctionOutput<
207
+ S extends ContractCodecSchema,
208
+ Name extends string,
209
+ > = Name extends keyof SchemaFunctions<S>
210
+ ? SchemaFunctions<S>[Name] extends { output: infer Output }
211
+ ? Output
212
+ : unknown
213
+ : unknown;
214
+
215
+ export type ContractProcedureInput<
216
+ S extends ContractCodecSchema,
217
+ Name extends string,
218
+ > = Name extends keyof SchemaProcedures<S>
219
+ ? SchemaProcedures<S>[Name] extends { input: infer Input }
220
+ ? Input
221
+ : unknown
222
+ : unknown;
223
+
224
+ export type ContractProcedureOutput<
225
+ S extends ContractCodecSchema,
226
+ Name extends string,
227
+ > = Name extends keyof SchemaProcedures<S>
228
+ ? SchemaProcedures<S>[Name] extends { output: infer Output }
229
+ ? Output
230
+ : unknown
231
+ : unknown;
232
+
233
+ type StringToTuple<
234
+ Value extends string,
235
+ Accumulator extends readonly unknown[] = readonly [],
236
+ > = Value extends `${infer _}${infer Rest}`
237
+ ? StringToTuple<Rest, readonly [unknown, ...Accumulator]>
238
+ : Accumulator;
239
+
240
+ type IsStringLiteral<Value extends string> = string extends Value ? false : true;
241
+
242
+ type IsLength60<Value extends string> =
243
+ IsStringLiteral<Value> extends true
244
+ ? StringToTuple<Value>["length"] extends 60
245
+ ? true
246
+ : false
247
+ : false;
248
+
249
+ type ContractAddress<Schema extends ContractCodecSchema> = Schema extends {
250
+ __meta: { address: infer Address extends string };
251
+ }
252
+ ? Address
253
+ : string;
254
+
255
+ export type ContractRequiresExplicitToIdentity<Schema extends ContractCodecSchema> =
256
+ IsLength60<ContractAddress<Schema>> extends true ? false : true;
257
+
258
+ export type ContractRegistryInput = ContractsRegistry | readonly ContractDefinition[];
259
+
260
+ export type ContractQueryInput<Input = unknown> = Readonly<{
261
+ inputBytes?: Uint8Array;
262
+ inputValue?: Input;
263
+ expectedOutputSize?: number;
264
+ retries?: number;
265
+ retryDelayMs?: number;
266
+ signal?: AbortSignal;
267
+ allowSequentialLayout?: boolean;
268
+ decodeOutput?: boolean;
269
+ }>;
270
+
271
+ export type ContractQueryResult<Output = unknown> = QueryRawResult &
272
+ Readonly<{
273
+ decoded?: Output;
274
+ }>;
275
+
276
+ export type ContractMutationResult<Output = unknown> = SendTransactionResult &
277
+ Readonly<{
278
+ responseBytes: Uint8Array;
279
+ responseBase64: string;
280
+ decoded?: Output;
281
+ }>;
282
+
283
+ export type ContractProcedureTxInput<
284
+ Input = unknown,
285
+ Output = unknown,
286
+ RequiresToIdentity extends boolean = false,
287
+ > = SeedSourceInput &
288
+ Readonly<{
289
+ name: string;
290
+ amount?: bigint;
291
+ targetTick?: bigint | number;
292
+ inputBytes?: Uint8Array;
293
+ inputValue?: Input;
294
+ allowSequentialLayout?: boolean;
295
+ decodeResponse?: (result: SendTransactionResult) => Output;
296
+ }> &
297
+ (RequiresToIdentity extends true
298
+ ? Readonly<{ toIdentity: string }>
299
+ : Readonly<{ toIdentity?: string }>);
300
+
301
+ export type ContractHandleLike = Readonly<{
302
+ query<Input = unknown, Output = unknown>(
303
+ name: string,
304
+ input: ContractQueryInput<Input>,
305
+ ): Promise<ContractQueryResult<Output>>;
306
+ sendProcedure<Input = unknown, Output = unknown>(
307
+ input: ContractProcedureTxInput<Input, Output>,
308
+ ): Promise<ContractMutationResult<Output>>;
309
+ }>;
@@ -0,0 +1,85 @@
1
+ import type {
2
+ ContractCodecSchema,
3
+ ContractFunctionInput,
4
+ ContractFunctionOutput,
5
+ ContractRegistrySchema,
6
+ } from "./contract-types.js";
7
+ import { createSdkProvider } from "./providers/sdk-provider.js";
8
+
9
+ type DemoSchema = Readonly<{
10
+ QUTIL: Readonly<{
11
+ functions: Readonly<{
12
+ GetFees: Readonly<{
13
+ input: Record<string, never>;
14
+ output: bigint;
15
+ }>;
16
+ GetPollInfo: Readonly<{
17
+ input: Readonly<{ poll_id: bigint }>;
18
+ output: Readonly<{ title: string }>;
19
+ }>;
20
+ }>;
21
+ procedures: Readonly<Record<never, never>>;
22
+ }>;
23
+ QX: Readonly<{
24
+ functions: Readonly<Record<never, never>>;
25
+ procedures: Readonly<{
26
+ IssueAsset: Readonly<{
27
+ input: Readonly<{
28
+ assetName: bigint;
29
+ numberOfShares: bigint;
30
+ unitOfMeasurement: bigint;
31
+ numberOfDecimalPlaces: number;
32
+ }>;
33
+ output: Readonly<{ txHash: string }>;
34
+ }>;
35
+ }>;
36
+ }>;
37
+ }>;
38
+
39
+ type _SchemaSatisfiesContract = DemoSchema extends ContractRegistrySchema ? true : false;
40
+ const _schemaSatisfiesContract: _SchemaSatisfiesContract = true;
41
+
42
+ type GetPollInfoInput = ContractFunctionInput<DemoSchema["QUTIL"], "GetPollInfo">;
43
+ type GetPollInfoOutput = ContractFunctionOutput<DemoSchema["QUTIL"], "GetPollInfo">;
44
+
45
+ const _validGetPollInfoInput: GetPollInfoInput = { poll_id: 1n };
46
+ const _validGetPollInfoOutput: GetPollInfoOutput = { title: "ok" };
47
+
48
+ // @ts-expect-error poll_id expects bigint
49
+ const _invalidGetPollInfoInputType: GetPollInfoInput = { poll_id: 1 };
50
+
51
+ const _provider = createSdkProvider<DemoSchema>();
52
+ const _useContractQuery = _provider.useContractQuery;
53
+ const _useContractMutation = _provider.useContractMutation;
54
+
55
+ _useContractQuery("QUTIL", "GetFees", {});
56
+ _useContractQuery("QUTIL", "GetPollInfo", { inputValue: { poll_id: 1n } });
57
+
58
+ // @ts-expect-error unknown function for QUTIL
59
+ _useContractQuery("QUTIL", "NotARealFunction", { inputValue: {} });
60
+
61
+ _useContractQuery("QUTIL", "GetPollInfo", {
62
+ // @ts-expect-error wrong input shape for GetPollInfo
63
+ inputValue: { pollId: 1n },
64
+ });
65
+
66
+ const _qxMutation = _useContractMutation("QX");
67
+
68
+ _qxMutation.mutate({
69
+ name: "IssueAsset",
70
+ fromSeed: "...",
71
+ toIdentity: "YOUR_CONTRACT_IDENTITY60",
72
+ inputValue: {
73
+ assetName: 0n,
74
+ numberOfShares: 1n,
75
+ unitOfMeasurement: 0n,
76
+ numberOfDecimalPlaces: 0,
77
+ },
78
+ });
79
+
80
+ _useContractMutation("QUTIL").mutate({
81
+ // @ts-expect-error QUTIL does not have IssueAsset
82
+ name: "IssueAsset",
83
+ fromSeed: "...",
84
+ toIdentity: "YOUR_CONTRACT_IDENTITY60",
85
+ });