@misofm/musicos 0.2.0 → 0.3.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 (50) hide show
  1. package/README.md +90 -13
  2. package/dist/client.d.ts +27 -26
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +58 -51
  5. package/dist/client.js.map +1 -1
  6. package/dist/deployments.d.ts +9 -0
  7. package/dist/deployments.d.ts.map +1 -1
  8. package/dist/deployments.js +14 -0
  9. package/dist/deployments.js.map +1 -1
  10. package/dist/errors.d.ts +10 -0
  11. package/dist/errors.d.ts.map +1 -0
  12. package/dist/errors.js +17 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/events.d.ts +6 -1
  15. package/dist/events.d.ts.map +1 -1
  16. package/dist/events.js +0 -5
  17. package/dist/events.js.map +1 -1
  18. package/dist/execute.d.ts +1 -48
  19. package/dist/execute.d.ts.map +1 -1
  20. package/dist/execute.js +5 -106
  21. package/dist/execute.js.map +1 -1
  22. package/dist/internal.d.ts +45 -6
  23. package/dist/internal.d.ts.map +1 -1
  24. package/dist/internal.js.map +1 -1
  25. package/dist/queries.d.ts +38 -62
  26. package/dist/queries.d.ts.map +1 -1
  27. package/dist/queries.js +240 -266
  28. package/dist/queries.js.map +1 -1
  29. package/dist/transactions.d.ts +2 -1
  30. package/dist/transactions.d.ts.map +1 -1
  31. package/dist/transactions.js.map +1 -1
  32. package/dist/types.d.ts +129 -79
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/types.js +169 -1
  35. package/dist/types.js.map +1 -1
  36. package/dist/view.d.ts +3 -2
  37. package/dist/view.d.ts.map +1 -1
  38. package/dist/view.js +19 -6
  39. package/dist/view.js.map +1 -1
  40. package/package.json +8 -1
  41. package/src/client.ts +78 -98
  42. package/src/deployments.ts +15 -0
  43. package/src/errors.ts +30 -0
  44. package/src/events.ts +1 -1
  45. package/src/execute.ts +5 -133
  46. package/src/internal.ts +17 -23
  47. package/src/queries.ts +386 -424
  48. package/src/transactions.ts +2 -1
  49. package/src/types.ts +59 -48
  50. package/src/view.ts +23 -9
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,2BAA2B;IAC1C,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,oDAAoD;IACpD,KAAK,EAAE,aAAa,CAAC;IACrB,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,2BAA2B;IAC1C,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,oDAAoD;IACpD,KAAK,EAAE,aAAa,CAAC;IACrB,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,+GA4ChC,CAAC"}
package/dist/view.js CHANGED
@@ -4,8 +4,10 @@
4
4
  // through the Core `simulateTransaction` API to read a computed value without
5
5
  // changing state — used where the value is a pure function of inputs the chain
6
6
  // derives (e.g. the deterministic release id).
7
+ import { Effect } from "effect";
7
8
  import { Transaction } from "@mysten/sui/transactions";
8
9
  import { bcs } from "@mysten/sui/bcs";
10
+ import { SuiClient, SuiRpcError } from "@misofm/effect";
9
11
  import * as release from "./contracts/musicos/release.js";
10
12
  import { asU256, asU64 } from "./numeric.js";
11
13
  /**
@@ -14,7 +16,7 @@ import { asU256, asU64 } from "./numeric.js";
14
16
  * Tracks embedded in a release must reference this exact ID, so it is computed
15
17
  * up front and threaded into the core release builder.
16
18
  */
17
- export async function deriveTargetReleaseId(client, misoPackageId, params) {
19
+ export const deriveTargetReleaseId = Effect.fn("deriveTargetReleaseId")(function* (misoPackageId, params) {
18
20
  if (params.recordingIds.length !== params.splitBps.length) {
19
21
  throw new Error(`deriveTargetReleaseId: recordingIds (${params.recordingIds.length}) and splitBps (${params.splitBps.length}) length mismatch.`);
20
22
  }
@@ -29,14 +31,25 @@ export async function deriveTargetReleaseId(client, misoPackageId, params) {
29
31
  asU256("release nonce", params.nonce),
30
32
  ],
31
33
  }));
34
+ const client = yield* SuiClient;
32
35
  // gRPC/Core equivalent of devInspect: simulate with per-command return values.
33
- const res = await client.core.simulateTransaction({ transaction: tx, include: { commandResults: true } });
36
+ const res = yield* Effect.tryPromise({
37
+ try: (signal) => client.core.simulateTransaction({ transaction: tx, include: { commandResults: true }, signal }),
38
+ catch: (cause) => new SuiRpcError({ operation: "simulateTransaction", cause }),
39
+ });
34
40
  if (res.$kind !== "Transaction") {
35
- throw new Error(`derive_target_release_id simulation failed: ${JSON.stringify(res.FailedTransaction.status)}`);
41
+ return yield* new SuiRpcError({
42
+ operation: "simulateTransaction",
43
+ cause: new Error(`derive_target_release_id simulation failed: ${JSON.stringify(res.FailedTransaction.status)}`),
44
+ });
36
45
  }
37
46
  const returned = res.commandResults?.[0]?.returnValues?.[0]?.bcs;
38
- if (!returned)
39
- throw new Error("derive_target_release_id returned no value.");
47
+ if (!returned) {
48
+ return yield* new SuiRpcError({
49
+ operation: "simulateTransaction",
50
+ cause: new Error("derive_target_release_id returned no value."),
51
+ });
52
+ }
40
53
  return bcs.Address.parse(returned);
41
- }
54
+ });
42
55
  //# sourceMappingURL=view.js.map
package/dist/view.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,sCAAsC;AAEtC,kFAAkF;AAClF,8EAA8E;AAC9E,+EAA+E;AAC/E,+CAA+C;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC,OAAO,KAAK,OAAO,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAsB,MAAM,cAAc,CAAC;AAejE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAyB,EACzB,aAAqB,EACrB,MAAmC;IAEnC,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,CAAC,YAAY,CAAC,MAAM,mBAAmB,MAAM,CAAC,QAAQ,CAAC,MAAM,oBAAoB,CAAC,CAAC;IACnJ,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;IAC7B,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,EAAE,CAAC,GAAG,CACJ,OAAO,CAAC,qBAAqB,CAAC;QAC5B,OAAO,EAAE,aAAa;QACtB,SAAS,EAAE;YACT,MAAM,CAAC,iBAAiB;YACxB,MAAM,CAAC,YAAY;YACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;YACvD,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC;SACtC;KACF,CAAC,CACH,CAAC;IAEF,+EAA+E;IAC/E,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAC1G,IAAI,GAAG,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjH,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IACjE,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC9E,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@misofm/musicos",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "packageManager": "bun@1.4.0",
5
5
  "description": "Typed bindings, queries, event decoders, and PTB builders for the Miso object model (Composition, Recording, Release, Track) on Sui.",
6
6
  "license": "Apache-2.0",
@@ -92,6 +92,10 @@
92
92
  "types": "./dist/contracts/*.d.ts",
93
93
  "default": "./dist/contracts/*.js"
94
94
  },
95
+ "./errors": {
96
+ "types": "./dist/errors.d.ts",
97
+ "default": "./dist/errors.js"
98
+ },
95
99
  "./package.json": "./package.json"
96
100
  },
97
101
  "files": [
@@ -102,17 +106,20 @@
102
106
  "package.json"
103
107
  ],
104
108
  "dependencies": {
109
+ "@misofm/effect": "0.1.0",
105
110
  "@mysten/bcs": "^2.1.1"
106
111
  },
107
112
  "devDependencies": {
108
113
  "@mysten/sui": "2.29.0",
109
114
  "@types/bun": "^1.4.0",
115
+ "effect": "4.0.0-rc.112",
110
116
  "typedoc": "^0.28.20",
111
117
  "typedoc-plugin-markdown": "^4.13.0",
112
118
  "typescript": "^7.0.2"
113
119
  },
114
120
  "peerDependencies": {
115
121
  "@mysten/sui": "2.29.0",
122
+ "effect": "4.0.0-rc.112",
116
123
  "typescript": "^5.7 || ^6 || ^7"
117
124
  },
118
125
  "main": "./dist/index.js"
package/src/client.ts CHANGED
@@ -1,11 +1,21 @@
1
1
  // Copyright (c) Miso Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import type { ConflictingWorkKindError } from "./errors.ts";
4
5
  import type {
5
6
  ClientWithCoreApi,
6
7
  SuiClientRegistration,
7
8
  } from "@mysten/sui/client";
8
9
  import type { SuiGraphQLClient } from "@mysten/sui/graphql";
10
+ import { Effect } from "effect";
11
+ import {
12
+ GraphQLUnavailableError,
13
+ SuiClient,
14
+ SuiGraphQL,
15
+ type BcsDecodeError,
16
+ type ObjectNotFoundError,
17
+ type SuiRpcError,
18
+ } from "@misofm/effect";
9
19
  import {
10
20
  getMisoDeployment,
11
21
  normalizeMisoDeployment,
@@ -26,6 +36,7 @@ import type {
26
36
  RecordingAdminCap,
27
37
  Release,
28
38
  ReleaseAdminCap,
39
+ ReleaseRegistry,
29
40
  } from "./types.ts";
30
41
 
31
42
  // Generated call modules (type-safe Move calls) and BCS structs.
@@ -66,7 +77,7 @@ function isFullDeployment(
66
77
  * ```ts
67
78
  * const client = new SuiGrpcClient({ network: 'testnet' })
68
79
  * .$extend(miso());
69
- * const composition = await client.miso.getCompositionById('0x...');
80
+ * const composition = await Effect.runPromise(client.miso.getCompositionById('0x...'));
70
81
  * ```
71
82
  */
72
83
  export function miso<const Name extends string = "miso">(
@@ -143,92 +154,77 @@ export class MisoProtocolClient {
143
154
  return this.#deployment.packageId;
144
155
  }
145
156
 
157
+ /** Provides `SuiClient` from this client's `ClientWithCoreApi`, so a method's program has `R = never`. */
158
+ #run<A, E>(effect: Effect.Effect<A, E, SuiClient>): Effect.Effect<A, E> {
159
+ return effect.pipe(Effect.provide(SuiClient.layer(this.#client)));
160
+ }
161
+
146
162
  // === Composition ===
147
163
 
148
- async getCompositionById(compositionId: string): Promise<Composition> {
149
- return queries.getCompositionById(this.#client, compositionId);
164
+ getCompositionById(compositionId: string): Effect.Effect<Composition, ObjectNotFoundError | SuiRpcError | BcsDecodeError> {
165
+ return this.#run(queries.getCompositionById(compositionId));
150
166
  }
151
- async getCompositionsByIds(
152
- ids: string[],
153
- ): Promise<Record<string, Composition>> {
154
- return queries.getCompositionsByIds(this.#client, ids);
167
+ getCompositionsByIds(ids: string[]): Effect.Effect<Record<string, Composition>, SuiRpcError | BcsDecodeError> {
168
+ return this.#run(queries.getCompositionsByIds(ids));
155
169
  }
156
- async getWorksByIds(ids: queries.WorkIds): Promise<queries.WorksById> {
157
- return queries.getWorksByIds(this.#client, ids);
170
+ getWorksByIds(ids: queries.WorkIds): Effect.Effect<queries.WorksById, ConflictingWorkKindError | SuiRpcError | BcsDecodeError> {
171
+ return this.#run(queries.getWorksByIds(ids));
158
172
  }
159
- async getWorkAddressesByShareTypes(
173
+ getWorkAddressesByShareTypes(
160
174
  shareTypes: queries.WorkShareTypes,
161
- ): Promise<queries.WorkAddressesByShareType> {
162
- return queries.getWorkAddressesByShareTypes(
163
- this.#requireGraphQL(),
164
- shareTypes,
165
- this.#misoPackageId,
166
- );
175
+ ): Effect.Effect<queries.WorkAddressesByShareType, SuiRpcError | GraphQLUnavailableError> {
176
+ if (!this.#graphqlClient) return Effect.fail(new GraphQLUnavailableError());
177
+ return queries
178
+ .getWorkAddressesByShareTypes(shareTypes, this.#misoPackageId)
179
+ .pipe(Effect.provide(SuiGraphQL.layer(this.#graphqlClient)));
167
180
  }
168
- async getCompositionShareType(compositionId: string): Promise<string> {
169
- return queries.getCompositionShareType(this.#client, compositionId);
181
+ getCompositionShareType(compositionId: string): Effect.Effect<string, ObjectNotFoundError | SuiRpcError> {
182
+ return this.#run(queries.getCompositionShareType(compositionId));
170
183
  }
171
- async getCompositionByShareType(shareType: string): Promise<Composition> {
172
- return queries.getCompositionByShareType(
173
- this.#client,
174
- this.#requireGraphQL(),
175
- shareType,
176
- this.#misoPackageId,
184
+ getCompositionByShareType(
185
+ shareType: string,
186
+ ): Effect.Effect<Composition, ObjectNotFoundError | SuiRpcError | BcsDecodeError | GraphQLUnavailableError> {
187
+ if (!this.#graphqlClient) return Effect.fail(new GraphQLUnavailableError());
188
+ return queries.getCompositionByShareType(shareType, this.#misoPackageId).pipe(
189
+ Effect.provide(SuiGraphQL.layer(this.#graphqlClient)),
190
+ Effect.provide(SuiClient.layer(this.#client)),
177
191
  );
178
192
  }
179
- async getCompositionAdminCapById(
180
- adminCapId: string,
181
- ): Promise<CompositionAdminCap> {
182
- return queries.getCompositionAdminCapById(this.#client, adminCapId);
183
- }
184
- async getOwnedCompositionAdminCaps(
185
- owner: string,
186
- ): Promise<CompositionAdminCap[]> {
187
- return queries.getOwnedCompositionAdminCaps(
188
- this.#client,
189
- owner,
190
- this.#misoPackageId,
191
- );
193
+ getCompositionAdminCapById(adminCapId: string): Effect.Effect<CompositionAdminCap, ObjectNotFoundError | SuiRpcError> {
194
+ return this.#run(queries.getCompositionAdminCapById(adminCapId));
195
+ }
196
+ getOwnedCompositionAdminCaps(owner: string): Effect.Effect<CompositionAdminCap[], SuiRpcError> {
197
+ return this.#run(queries.getOwnedCompositionAdminCaps(owner, this.#misoPackageId));
192
198
  }
193
199
  deriveCompositionAdminCapId(compositionId: string): string {
194
- return queries.deriveCompositionAdminCapId(
195
- compositionId,
196
- this.#misoPackageId,
197
- );
200
+ return queries.deriveCompositionAdminCapId(compositionId, this.#misoPackageId);
198
201
  }
199
202
 
200
203
  // === Recording ===
201
204
 
202
- async getRecordingById(recordingId: string): Promise<Recording> {
203
- return queries.getRecordingById(this.#client, recordingId);
205
+ getRecordingById(recordingId: string): Effect.Effect<Recording, ObjectNotFoundError | SuiRpcError | BcsDecodeError> {
206
+ return this.#run(queries.getRecordingById(recordingId));
204
207
  }
205
- async getRecordingsByIds(ids: string[]): Promise<Record<string, Recording>> {
206
- return queries.getRecordingsByIds(this.#client, ids);
208
+ getRecordingsByIds(ids: string[]): Effect.Effect<Record<string, Recording>, SuiRpcError | BcsDecodeError> {
209
+ return this.#run(queries.getRecordingsByIds(ids));
207
210
  }
208
- async getRecordingShareType(recordingId: string): Promise<string> {
209
- return queries.getRecordingShareType(this.#client, recordingId);
211
+ getRecordingShareType(recordingId: string): Effect.Effect<string, ObjectNotFoundError | SuiRpcError> {
212
+ return this.#run(queries.getRecordingShareType(recordingId));
210
213
  }
211
- async getRecordingByShareType(shareType: string): Promise<Recording> {
212
- return queries.getRecordingByShareType(
213
- this.#client,
214
- this.#requireGraphQL(),
215
- shareType,
216
- this.#misoPackageId,
214
+ getRecordingByShareType(
215
+ shareType: string,
216
+ ): Effect.Effect<Recording, ObjectNotFoundError | SuiRpcError | BcsDecodeError | GraphQLUnavailableError> {
217
+ if (!this.#graphqlClient) return Effect.fail(new GraphQLUnavailableError());
218
+ return queries.getRecordingByShareType(shareType, this.#misoPackageId).pipe(
219
+ Effect.provide(SuiGraphQL.layer(this.#graphqlClient)),
220
+ Effect.provide(SuiClient.layer(this.#client)),
217
221
  );
218
222
  }
219
- async getRecordingAdminCapById(
220
- adminCapId: string,
221
- ): Promise<RecordingAdminCap> {
222
- return queries.getRecordingAdminCapById(this.#client, adminCapId);
223
- }
224
- async getOwnedRecordingAdminCaps(
225
- owner: string,
226
- ): Promise<RecordingAdminCap[]> {
227
- return queries.getOwnedRecordingAdminCaps(
228
- this.#client,
229
- owner,
230
- this.#misoPackageId,
231
- );
223
+ getRecordingAdminCapById(adminCapId: string): Effect.Effect<RecordingAdminCap, ObjectNotFoundError | SuiRpcError> {
224
+ return this.#run(queries.getRecordingAdminCapById(adminCapId));
225
+ }
226
+ getOwnedRecordingAdminCaps(owner: string): Effect.Effect<RecordingAdminCap[], SuiRpcError> {
227
+ return this.#run(queries.getOwnedRecordingAdminCaps(owner, this.#misoPackageId));
232
228
  }
233
229
  deriveRecordingAdminCapId(recordingId: string): string {
234
230
  return queries.deriveRecordingAdminCapId(recordingId, this.#misoPackageId);
@@ -236,54 +232,47 @@ export class MisoProtocolClient {
236
232
 
237
233
  // === Release ===
238
234
 
239
- async getReleaseById(releaseId: string): Promise<Release> {
240
- return queries.getReleaseById(this.#client, releaseId);
235
+ getReleaseById(releaseId: string): Effect.Effect<Release, ObjectNotFoundError | SuiRpcError | BcsDecodeError> {
236
+ return this.#run(queries.getReleaseById(releaseId));
241
237
  }
242
238
  /** Read the shared canonical core `miso::release::ReleaseRegistry`. */
243
- async getReleaseRegistryById(registryId: string) {
244
- return queries.getReleaseRegistryById(this.#client, registryId);
239
+ getReleaseRegistryById(registryId: string): Effect.Effect<ReleaseRegistry, ObjectNotFoundError | SuiRpcError | BcsDecodeError> {
240
+ return this.#run(queries.getReleaseRegistryById(registryId));
245
241
  }
246
- async getReleasesByIds(ids: string[]): Promise<Record<string, Release>> {
247
- return queries.getReleasesByIds(this.#client, ids);
242
+ getReleasesByIds(ids: string[]): Effect.Effect<Record<string, Release>, SuiRpcError | BcsDecodeError> {
243
+ return this.#run(queries.getReleasesByIds(ids));
248
244
  }
249
- async getReleaseAdminCapById(adminCapId: string): Promise<ReleaseAdminCap> {
250
- return queries.getReleaseAdminCapById(this.#client, adminCapId);
245
+ getReleaseAdminCapById(adminCapId: string): Effect.Effect<ReleaseAdminCap, ObjectNotFoundError | SuiRpcError> {
246
+ return this.#run(queries.getReleaseAdminCapById(adminCapId));
251
247
  }
252
248
  deriveReleaseAdminCapId(releaseId: string): string {
253
249
  return queries.deriveReleaseAdminCapId(releaseId, this.#misoPackageId);
254
250
  }
255
- async getOwnedReleaseAdminCaps(owner: string): Promise<ReleaseAdminCap[]> {
256
- return queries.getOwnedReleaseAdminCaps(
257
- this.#client,
258
- owner,
259
- this.#misoPackageId,
260
- );
251
+ getOwnedReleaseAdminCaps(owner: string): Effect.Effect<ReleaseAdminCap[], SuiRpcError> {
252
+ return this.#run(queries.getOwnedReleaseAdminCaps(owner, this.#misoPackageId));
261
253
  }
254
+
262
255
  // === Share Currency ===
263
256
 
264
- async getShareCurrencyType(shareCurrencyId: string): Promise<string> {
265
- return queries.getShareCurrencyType(this.#client, shareCurrencyId);
257
+ getShareCurrencyType(shareCurrencyId: string): Effect.Effect<string, ObjectNotFoundError | SuiRpcError> {
258
+ return this.#run(queries.getShareCurrencyType(shareCurrencyId));
266
259
  }
267
260
  /**
268
261
  * The `TreasuryCap<shareType>` owned by `owner`. Takes the share TYPE — if you
269
262
  * hold only the `Currency` object id, resolve it first with
270
263
  * {@link getShareCurrencyType}.
271
264
  */
272
- async getShareCurrencyTreasuryCap(
273
- shareType: string,
274
- owner: string,
275
- ): Promise<string> {
276
- return queries.getShareCurrencyTreasuryCap(this.#client, shareType, owner);
265
+ getShareCurrencyTreasuryCap(shareType: string, owner: string): Effect.Effect<string, SuiRpcError> {
266
+ return this.#run(queries.getShareCurrencyTreasuryCap(shareType, owner));
277
267
  }
278
268
 
279
269
  // === Simulate-based reads (view) ===
280
270
 
281
271
  get view() {
282
- const client = this.#client;
283
272
  const misoPackageId = this.#misoPackageId;
284
273
  return {
285
274
  deriveTargetReleaseId: (params: view.DeriveTargetReleaseIdParams) =>
286
- view.deriveTargetReleaseId(client, misoPackageId, params),
275
+ this.#run(view.deriveTargetReleaseId(misoPackageId, params)),
287
276
  };
288
277
  }
289
278
 
@@ -326,15 +315,6 @@ export class MisoProtocolClient {
326
315
  events: eventParsers,
327
316
  };
328
317
  }
329
-
330
- #requireGraphQL(): SuiGraphQLClient {
331
- if (!this.#graphqlClient) {
332
- throw new Error(
333
- "GraphQL client required. Pass graphqlClient to miso() options.",
334
- );
335
- }
336
- return this.#graphqlClient;
337
- }
338
318
  }
339
319
 
340
320
  /** @deprecated Prefer the layer-specific `MisoProtocolClient` name. */
@@ -1,7 +1,9 @@
1
1
  // Copyright (c) Miso Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import { Effect } from "effect";
4
5
  import { normalizeSuiAddress } from "@mysten/sui/utils";
6
+ import { DeploymentError } from "@misofm/effect/errors";
5
7
 
6
8
  /** Sui networks for which this SDK may bundle a verified deployment. */
7
9
  export type MisoNetwork = "mainnet" | "testnet";
@@ -164,3 +166,16 @@ export function normalizeMisoDeployment(deployment: unknown): MisoDeployment {
164
166
  Object.fromEntries(CANONICAL_MISO_PACKAGE_NAMES.map((name) => [name, deployment[name]])),
165
167
  ) as MisoDeployment;
166
168
  }
169
+
170
+ /**
171
+ * Effect-returning form of {@link assertMisoDeployment} + {@link normalizeMisoDeployment}, for
172
+ * configuration boundaries that are already composing `Effect` programs (e.g. loading a
173
+ * deployment manifest from a config service). Synchronous and pure — validation is not I/O — so
174
+ * both this and the throwing form are fine; use whichever fits the call site.
175
+ */
176
+ export function validateMisoDeployment(deployment: unknown): Effect.Effect<MisoDeployment, DeploymentError> {
177
+ return Effect.try({
178
+ try: () => normalizeMisoDeployment(deployment),
179
+ catch: (cause) => new DeploymentError({ message: cause instanceof Error ? cause.message : String(cause) }),
180
+ });
181
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,30 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // `@misofm/musicos` has no failure modes of its own beyond the shared Sui
5
+ // read/write vocabulary — every query is a Core object read, a GraphQL type
6
+ // discovery, or a BCS decode, and every one of those is already covered by
7
+ // `@misofm/effect`'s tagged errors. Re-exported here so callers can import the
8
+ // complete error vocabulary from one place (`@misofm/musicos/errors`) without
9
+ // also depending on `@misofm/effect` directly.
10
+ import { Schema } from "effect";
11
+
12
+ export {
13
+ ObjectNotFoundError,
14
+ ObjectTypeMismatchError,
15
+ SuiRpcError,
16
+ BcsDecodeError,
17
+ TransactionFailedError,
18
+ GraphQLUnavailableError,
19
+ DeploymentError,
20
+ type SuiReadError,
21
+ } from "@misofm/effect/errors";
22
+
23
+ /** One object id was requested under two different work kinds in a single batched read. */
24
+ export class ConflictingWorkKindError extends Schema.TaggedError<ConflictingWorkKindError>()(
25
+ "ConflictingWorkKindError",
26
+ {
27
+ objectId: Schema.String,
28
+ kinds: Schema.Array(Schema.String),
29
+ },
30
+ ) {}
package/src/events.ts CHANGED
@@ -7,8 +7,8 @@
7
7
  * and nested layouts exactly, which is the safe indexer boundary.
8
8
  */
9
9
 
10
+ import type { BcsParser } from "@misofm/effect";
10
11
  import * as release from "./contracts/musicos/release.ts";
11
- import type { BcsParser } from "./queries.ts";
12
12
 
13
13
  /** Decode raw event BCS with the corresponding generated codec. */
14
14
  export function decodeEvent<T>(codec: BcsParser<T>, bytes: Uint8Array): T {
package/src/execute.ts CHANGED
@@ -2,136 +2,8 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  // Transaction execution + effect extraction (the Signer-parameter pattern).
5
- //
6
- // Builders elsewhere only *append* to a caller-owned Transaction; this module is
7
- // where a transaction is actually submitted. `signAndExecute` submits over the
8
- // unified Core API, unwraps the `{ $kind: "Transaction", Transaction }` envelope,
9
- // waits for finality, and returns changed objects, the objectId→type map, balance
10
- // changes, and net gas for downstream extraction. Everything here is
11
- // transport-agnostic — it takes any `ClientWithCoreApi`, so gRPC / JSON-RPC /
12
- // GraphQL clients all work.
13
- //
14
-
15
- import { Transaction } from "@mysten/sui/transactions";
16
- import type { ClientWithCoreApi, SuiClientTypes } from "@mysten/sui/client";
17
- import type { Signer } from "@mysten/sui/cryptography";
18
- import type { TxThunk } from "./transactions.ts";
19
-
20
- /** The effect fields every submit path requests, so extraction is uniform. */
21
- export const FULL_INCLUDE = { effects: true, objectTypes: true, balanceChanges: true } as const;
22
- type FullInclude = typeof FULL_INCLUDE;
23
-
24
- export interface ExecResult {
25
- digest: string;
26
- /** Objects created/mutated/deleted by the transaction. */
27
- changedObjects: SuiClientTypes.ChangedObject[];
28
- /** Map of changed objectId → fully-qualified type. */
29
- objectTypes: Record<string, string>;
30
- /** Net coin balance deltas by address. */
31
- balanceChanges: SuiClientTypes.BalanceChange[];
32
- /** Net gas cost in MIST (computation + storage − rebate). */
33
- gasUsed: number;
34
- }
35
-
36
- /** Builds a fresh Transaction from one or more thunks (awaiting async ones). */
37
- export async function buildTx(...thunks: TxThunk[]): Promise<Transaction> {
38
- const tx = new Transaction();
39
- for (const thunk of thunks) await thunk(tx);
40
- return tx;
41
- }
42
-
43
- /** Normalizes the `{ $kind }` transaction-result envelope into an {@link ExecResult}. */
44
- export function toExecResult(res: SuiClientTypes.TransactionResult<FullInclude>): ExecResult {
45
- if (res.$kind !== "Transaction") {
46
- const failed = res.FailedTransaction;
47
- const status = failed.effects?.status;
48
- const err = status && !status.success ? JSON.stringify(status.error) : "unknown error";
49
- throw new Error(`Transaction failed: ${err} (digest ${failed.digest})`);
50
- }
51
-
52
- const t = res.Transaction;
53
- const effects = t.effects as SuiClientTypes.TransactionEffects;
54
- if (!effects.status.success) {
55
- throw new Error(`Transaction reverted: ${JSON.stringify(effects.status.error)} (digest ${t.digest})`);
56
- }
57
-
58
- return {
59
- digest: t.digest,
60
- changedObjects: effects.changedObjects,
61
- objectTypes: (t.objectTypes as Record<string, string>) ?? {},
62
- balanceChanges: (t.balanceChanges as SuiClientTypes.BalanceChange[]) ?? [],
63
- gasUsed: netGas(effects.gasUsed),
64
- };
65
- }
66
-
67
- /** Signs, executes, and waits for a transaction; returns changes, types, gas. */
68
- export async function signAndExecute(client: ClientWithCoreApi, signer: Signer, tx: Transaction): Promise<ExecResult> {
69
- const res = await client.core.signAndExecuteTransaction({ transaction: tx, signer, include: FULL_INCLUDE });
70
- const result = toExecResult(res);
71
- await client.core.waitForTransaction({ digest: result.digest });
72
- return result;
73
- }
74
-
75
- /** Convenience: build from thunks, then sign+execute in one call. */
76
- export async function execThunks(client: ClientWithCoreApi, signer: Signer, ...thunks: TxThunk[]): Promise<ExecResult> {
77
- return signAndExecute(client, signer, await buildTx(...thunks));
78
- }
79
-
80
- // ── Object-change extractors ────────────────────────────────────────────────
81
-
82
- /** The package id from the (single) newly-published package. */
83
- export function publishedPackageId(r: ExecResult): string {
84
- const pkg = r.changedObjects.find((c) => c.idOperation === "Created" && c.outputState === "PackageWrite");
85
- if (!pkg) throw new Error("No published package found in object changes.");
86
- return pkg.objectId;
87
- }
88
-
89
- /** All package ids newly published by the transaction (up to 5 per PTB). */
90
- export function allPublishedPackageIds(r: ExecResult): string[] {
91
- return r.changedObjects
92
- .filter((c) => c.idOperation === "Created" && c.outputState === "PackageWrite")
93
- .map((c) => c.objectId);
94
- }
95
-
96
- /** The first newly-created object whose type contains `substr`. */
97
- export function createdByType(r: ExecResult, substr: string): string {
98
- const id = maybeCreatedByType(r, substr);
99
- if (!id) throw new Error(`No created object with type containing "${substr}" found in object changes.`);
100
- return id;
101
- }
102
-
103
- /** Like {@link createdByType} but returns undefined instead of throwing. */
104
- export function maybeCreatedByType(r: ExecResult, substr: string): string | undefined {
105
- for (const c of r.changedObjects) {
106
- if (c.idOperation === "Created" && (r.objectTypes[c.objectId] ?? "").includes(substr)) return c.objectId;
107
- }
108
- return undefined;
109
- }
110
-
111
- /** The first newly-created object whose type is EXACTLY `type` (for non-generic types). */
112
- export function createdByExactType(r: ExecResult, type: string): string {
113
- for (const c of r.changedObjects) {
114
- if (c.idOperation === "Created" && r.objectTypes[c.objectId] === type) return c.objectId;
115
- }
116
- throw new Error(`No created object of exact type "${type}" found in object changes.`);
117
- }
118
-
119
- /** All newly-created objects whose type contains `substr`. */
120
- export function allCreatedByType(r: ExecResult, substr: string): { objectId: string; objectType: string }[] {
121
- const out: { objectId: string; objectType: string }[] = [];
122
- for (const c of r.changedObjects) {
123
- const type = r.objectTypes[c.objectId] ?? "";
124
- if (c.idOperation === "Created" && type.includes(substr)) out.push({ objectId: c.objectId, objectType: type });
125
- }
126
- return out;
127
- }
128
-
129
- /** The signed balance delta for `address` in `coinType`, or "0" if absent. */
130
- export function balanceDelta(r: ExecResult, address: string, coinType: string): string {
131
- const change = r.balanceChanges.find((b) => b.address === address && b.coinType === coinType);
132
- return change?.amount ?? "0";
133
- }
134
-
135
- function netGas(gasUsed: SuiClientTypes.GasCostSummary): number {
136
- return Number(gasUsed.computationCost) + Number(gasUsed.storageCost) - Number(gasUsed.storageRebate);
137
- }
5
+ // This module is a thin re-export of `@misofm/effect/execute` so the
6
+ // `@misofm/musicos/execute` subpath keeps resolving for existing callers
7
+ // the implementation is transport-agnostic and shared across every `@misofm/*`
8
+ // SDK, so there is exactly one copy of it.
9
+ export * from "@misofm/effect/execute";