@misofm/partyos 0.1.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.
package/dist/queries.js CHANGED
@@ -1,123 +1,85 @@
1
1
  // Copyright (c) Miso Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ // Typed reads: fetch an on-chain object (or dynamic field) via the Core API, BCS-parse
4
+ // it through the generated struct, and map to the public camelCase types. Every read
5
+ // requires the `SuiClient` service (see `@misofm/effect`) instead of taking a client
6
+ // parameter; not-found and type-mismatch paths are typed failures, not thrown errors.
7
+ import { Effect, Option, Stream } from "effect";
3
8
  import { deriveDynamicFieldID, deriveObjectID, normalizeStructTag } from "@mysten/sui/utils";
4
9
  import { bcs } from "@mysten/sui/bcs";
10
+ import { assertObjectType, decodeBcs, getObjectContent, getObjectsContent, getOptionalObjectContent, listDynamicFields, } from "@misofm/effect";
5
11
  import { MembershipKey as MembershipKeyBcs, Party as PartyBcs, PendingInviteKey as PendingInviteKeyBcs, PendingMembershipKey as PendingMembershipKeyBcs, } from "./contracts/partyos/party.js";
6
12
  import { keyBytes, mapParty } from "./internal.js";
7
- /** True for the Core API's "object does not exist" error (a missing dynamic field). */
8
- export function isNotFound(e) {
9
- const msg = e instanceof Error ? e.message : String(e);
10
- return /not\s*found|does not exist|no object/i.test(msg);
11
- }
12
- /**
13
- * Reads an object's BCS content, or null when it does not exist. A missing
14
- * object (e.g. an unset dynamic field) surfaces as a thrown "not found" from the
15
- * Core API, not an empty result, so optional reads can treat it as absence.
16
- */
17
- export async function getObjectContent(client, objectId) {
18
- try {
19
- const { object } = await client.core.getObject({ objectId, include: { content: true } });
20
- return object?.content ?? null;
21
- }
22
- catch (e) {
23
- if (isNotFound(e))
24
- return null;
25
- throw e;
26
- }
27
- }
13
+ import { Party } from "./types.js";
28
14
  /** The `Party` struct tag of one partyos deployment. */
29
15
  export function partyType(partyPackageId) {
30
16
  return normalizeStructTag(`${partyPackageId}::party::Party`);
31
17
  }
32
- // A Party from another partyos package (a previous generation) parses
33
- // identically but no deployed package accepts it, so the object's type is
34
- // checked against the deployment before its content is trusted.
35
- function assertPartyType(objectId, type, partyPackageId) {
36
- const expected = partyType(partyPackageId);
37
- if (type === undefined || normalizeStructTag(type) !== expected) {
38
- throw new Error(`Object ${objectId} is ${type ?? "of unknown type"}, not a ${expected}` +
39
- (type?.endsWith("::party::Party") ? " (a Party from a different partyos deployment)" : ""));
40
- }
18
+ /** Decodes one object's BCS content into a `Party`, mapping the generated parse output first. */
19
+ function decodeParty(objectId, content, expectedType) {
20
+ return decodeBcs({ parse: (bytes) => mapParty(objectId, PartyBcs.parse(bytes)) }, Party, content, { type: expectedType, objectId });
41
21
  }
42
22
  /** Fetches and parses a shared `Party` object of this deployment's partyos package. */
43
- export async function getPartyById(client, partyId, partyPackageId) {
44
- let object;
45
- try {
46
- ({ object } = await client.core.getObject({ objectId: partyId, include: { content: true } }));
47
- }
48
- catch (e) {
49
- if (isNotFound(e))
50
- throw new Error(`Party not found: ${partyId}`);
51
- throw e;
52
- }
53
- if (!object?.content)
54
- throw new Error(`Party not found: ${partyId}`);
55
- assertPartyType(partyId, object.type, partyPackageId);
56
- return mapParty(partyId, PartyBcs.parse(object.content));
57
- }
23
+ export const getPartyById = Effect.fn("getPartyById")(function* (partyId, partyPackageId) {
24
+ const expected = partyType(partyPackageId);
25
+ const object = yield* getObjectContent(partyId);
26
+ // A Party from another partyos package (a previous generation) parses
27
+ // identically but no deployed package accepts it, so the object's type is
28
+ // checked against the deployment before its content is trusted.
29
+ yield* assertObjectType(partyId, normalizeStructTag(object.type), expected);
30
+ return yield* decodeParty(partyId, object.content, expected);
31
+ });
58
32
  /**
59
33
  * Fetches and parses multiple shared `Party` objects in one Core request.
60
34
  * Missing objects are skipped; an object of another type is an error.
61
35
  */
62
- export async function getPartiesByIds(client, partyIds, partyPackageId) {
36
+ export const getPartiesByIds = Effect.fn("getPartiesByIds")(function* (partyIds, partyPackageId) {
63
37
  if (partyIds.length === 0)
64
38
  return {};
65
- const { objects } = await client.core.getObjects({
66
- objectIds: [...new Set(partyIds)],
67
- include: { content: true },
68
- });
39
+ const expected = partyType(partyPackageId);
40
+ const contentById = yield* getObjectsContent([...new Set(partyIds)]);
69
41
  const parties = {};
70
- for (const obj of objects) {
71
- if (obj instanceof Error)
72
- continue;
73
- assertPartyType(obj.objectId, obj.type, partyPackageId);
74
- parties[obj.objectId] = mapParty(obj.objectId, PartyBcs.parse(obj.content));
42
+ for (const [objectId, { content, type }] of contentById) {
43
+ yield* assertObjectType(objectId, normalizeStructTag(type), expected);
44
+ parties[objectId] = yield* decodeParty(objectId, content, expected);
75
45
  }
76
46
  return parties;
77
- }
47
+ });
78
48
  /** Derives a party's `PartyAdminCap` id (it is a `derived_object` off the party UID). */
79
49
  export function derivePartyAdminCapId(partyId, partyPackageId) {
80
50
  return deriveObjectID(partyId, `${partyPackageId}::party::PartyAdminCapKey`, bcs.Address.serialize(partyId).toBytes());
81
51
  }
82
52
  // === Group membership reads ===
83
53
  /** Collects the ids stored in every dynamic-field key of `parentId` whose type ends with `keySuffix`. */
84
- async function collectKeyIds(client, parentId, keySuffix, codec) {
85
- const ids = [];
86
- let cursor;
87
- do {
88
- const page = await client.core.listDynamicFields({ parentId, cursor: cursor ?? undefined });
89
- for (const f of page.dynamicFields) {
90
- if (typeof f.name?.type === "string" && f.name.type.endsWith(keySuffix) && f.name.bcs != null) {
91
- const [id] = codec.parse(keyBytes(f.name.bcs));
92
- ids.push(String(id));
93
- }
94
- }
95
- cursor = page.hasNextPage ? page.cursor : null;
96
- } while (cursor);
97
- return ids;
54
+ function collectKeyIds(parentId, keySuffix, codec) {
55
+ return listDynamicFields(parentId).pipe(Stream.filter((f) => typeof f.name?.type === "string" && f.name.type.endsWith(keySuffix) && f.name.bcs != null), Stream.map((f) => {
56
+ const [id] = codec.parse(keyBytes(f.name.bcs));
57
+ return String(id);
58
+ }), Stream.runCollect, Effect.map((chunk) => Array.from(chunk)));
98
59
  }
99
60
  /**
100
61
  * The group ids a party currently belongs to, read from its `MembershipKey`
101
62
  * dynamic fields (the member-side record). No indexer required.
102
63
  */
103
- export async function getMemberships(client, partyId) {
104
- return collectKeyIds(client, partyId, "::party::MembershipKey", MembershipKeyBcs);
64
+ export function getMemberships(partyId) {
65
+ return collectKeyIds(partyId, "::party::MembershipKey", MembershipKeyBcs);
105
66
  }
106
67
  /** The member ids invited to a group but not yet accepted (its `PendingInviteKey` fields). */
107
- export async function getPendingInvites(client, groupId) {
108
- return collectKeyIds(client, groupId, "::party::PendingInviteKey", PendingInviteKeyBcs);
68
+ export function getPendingInvites(groupId) {
69
+ return collectKeyIds(groupId, "::party::PendingInviteKey", PendingInviteKeyBcs);
109
70
  }
110
71
  /**
111
72
  * The group ids that have invited a party but are still awaiting its response.
112
73
  * This reads the member-side `PendingMembershipKey` inbox index, so it only
113
74
  * enumerates the target party's dynamic fields.
114
75
  */
115
- export async function getPendingMemberships(client, partyId) {
116
- return collectKeyIds(client, partyId, "::party::PendingMembershipKey", PendingMembershipKeyBcs);
76
+ export function getPendingMemberships(partyId) {
77
+ return collectKeyIds(partyId, "::party::PendingMembershipKey", PendingMembershipKeyBcs);
117
78
  }
118
79
  /** Whether `memberId` currently holds a membership record for `groupId`. */
119
- export async function isMember(client, memberId, groupId, partyPackageId) {
80
+ export const isMember = Effect.fn("isMember")(function* (memberId, groupId, partyPackageId) {
120
81
  const fieldId = deriveDynamicFieldID(memberId, `${partyPackageId}::party::MembershipKey`, MembershipKeyBcs.serialize([groupId]).toBytes());
121
- return (await getObjectContent(client, fieldId)) !== null;
122
- }
82
+ const content = yield* getOptionalObjectContent(fieldId);
83
+ return Option.isSome(content);
84
+ });
123
85
  //# sourceMappingURL=queries.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"queries.js","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,12 +1,17 @@
1
- export type PartyKind = "individual" | "group";
2
- export interface Party {
3
- id: string;
4
- kind: PartyKind;
1
+ import { Schema } from "effect";
2
+ export declare const PartyKind: Schema.Literals<readonly ["individual", "group"]>;
3
+ export type PartyKind = typeof PartyKind.Type;
4
+ declare const Party_base: Schema.Class<Party, Schema.Struct<{
5
+ readonly id: Schema.String;
6
+ readonly kind: Schema.Literals<readonly ["individual", "group"]>;
5
7
  /** Human-readable name (not verified). */
6
- name: string;
8
+ readonly name: Schema.String;
7
9
  /** Member party ids — present only when `kind === "group"`. */
8
- members?: string[];
10
+ readonly members: Schema.optional<Schema.$Array<Schema.String>>;
9
11
  /** Unix ms when the party was created. */
10
- createdAtMs: number;
12
+ readonly createdAtMs: Schema.Number;
13
+ }>, {}>;
14
+ export declare class Party extends Party_base {
11
15
  }
16
+ export {};
12
17
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,eAAO,MAAM,SAAS,mDAA2C,CAAC;AAClE,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC;;;;IAK5C,0CAA0C;;IAE1C,+DAA+D;;IAE/D,0CAA0C;;;AAP5C,qBAAa,KAAM,SAAQ,UASzB;CAAG"}
package/dist/types.js CHANGED
@@ -1,4 +1,18 @@
1
1
  // Copyright (c) Miso Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- export {};
3
+ // Public, camelCase result types. The mapper in ./internal.ts turns the generated
4
+ // (snake_case, Move-shaped) parse output into the plain shape `Party` decodes from.
5
+ import { Schema } from "effect";
6
+ export const PartyKind = Schema.Literals(["individual", "group"]);
7
+ export class Party extends Schema.Class("@misofm/partyos/Party")({
8
+ id: Schema.String,
9
+ kind: PartyKind,
10
+ /** Human-readable name (not verified). */
11
+ name: Schema.String,
12
+ /** Member party ids — present only when `kind === "group"`. */
13
+ members: Schema.optional(Schema.Array(Schema.String)),
14
+ /** Unix ms when the party was created. */
15
+ createdAtMs: Schema.Number,
16
+ }) {
17
+ }
4
18
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,sCAAsC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,sCAAsC;AAEtC,kFAAkF;AAClF,oFAAoF;AAEpF,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;AAGlE,MAAM,OAAO,KAAM,SAAQ,MAAM,CAAC,KAAK,CAAQ,uBAAuB,CAAC,CAAC;IACtE,EAAE,EAAE,MAAM,CAAC,MAAM;IACjB,IAAI,EAAE,SAAS;IACf,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrD,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC,MAAM;CAC3B,CAAC;CAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@misofm/partyos",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "packageManager": "bun@1.4.0",
5
5
  "description": "Typed bindings, queries, and PTB builders for the PartyOS object model (Party identity, admin caps, and group membership) on Sui.",
6
6
  "license": "Apache-2.0",
@@ -50,6 +50,10 @@
50
50
  "types": "./dist/deployments.d.ts",
51
51
  "default": "./dist/deployments.js"
52
52
  },
53
+ "./errors": {
54
+ "types": "./dist/errors.d.ts",
55
+ "default": "./dist/errors.js"
56
+ },
53
57
  "./queries": {
54
58
  "types": "./dist/queries.d.ts",
55
59
  "default": "./dist/queries.js"
@@ -80,17 +84,20 @@
80
84
  "package.json"
81
85
  ],
82
86
  "dependencies": {
87
+ "@misofm/effect": "0.1.0",
83
88
  "@mysten/bcs": "^2.1.1"
84
89
  },
85
90
  "devDependencies": {
86
91
  "@mysten/sui": "2.29.0",
87
92
  "@types/bun": "^1.4.0",
93
+ "effect": "4.0.0-rc.112",
88
94
  "typedoc": "^0.28.20",
89
95
  "typedoc-plugin-markdown": "^4.13.0",
90
96
  "typescript": "^7.0.2"
91
97
  },
92
98
  "peerDependencies": {
93
99
  "@mysten/sui": "2.29.0",
100
+ "effect": "4.0.0-rc.112",
94
101
  "typescript": "^5.7 || ^6 || ^7"
95
102
  },
96
103
  "main": "./dist/index.js"
package/src/client.ts CHANGED
@@ -5,7 +5,10 @@
5
5
  // deployment. Consumers reach this through `client.partyos` after
6
6
  // `$extend(partyos())`, or construct `PartyosClient` directly.
7
7
 
8
+ import { Effect } from "effect";
8
9
  import type { ClientWithCoreApi, SuiClientRegistration } from "@mysten/sui/client";
10
+ import { SuiClient } from "@misofm/effect";
11
+ import type { BcsDecodeError, ObjectNotFoundError, ObjectTypeMismatchError, SuiRpcError } from "@misofm/effect";
9
12
  import { getPartyDeployment, normalizePartyDeployment, type PartyDeployment } from "./deployments.ts";
10
13
  import { PARTY_REF_RETURNING_CALLS } from "./contracts.ts";
11
14
  import * as queries from "./queries.ts";
@@ -74,10 +77,12 @@ export function partyos<const Name extends string = "partyos">(
74
77
  export class PartyosClient {
75
78
  #client: ClientWithCoreApi;
76
79
  #deployment: PartyDeployment;
80
+ #layer: ReturnType<typeof SuiClient.layer>;
77
81
 
78
82
  constructor(client: ClientWithCoreApi, deployment: PartyDeployment) {
79
83
  this.#client = client;
80
84
  this.#deployment = normalizePartyDeployment(deployment);
85
+ this.#layer = SuiClient.layer(client);
81
86
  }
82
87
 
83
88
  /** The exact deployment selected for this client. */
@@ -89,32 +94,43 @@ export class PartyosClient {
89
94
  return this.#deployment.partyos;
90
95
  }
91
96
 
97
+ /** Provides the `SuiClient` service bound to this client, discharging `R`. */
98
+ #provide<A, E>(effect: Effect.Effect<A, E, SuiClient>): Effect.Effect<A, E> {
99
+ return effect.pipe(Effect.provide(this.#layer));
100
+ }
101
+
92
102
  // === Queries ===
103
+ // Each method provides `SuiClient` internally, so callers get `Effect<A, E>`
104
+ // (R = never) and only need `Effect.runPromise` (or their own composition).
93
105
 
94
- async getPartyById(partyId: string): Promise<Party> {
95
- return queries.getPartyById(this.#client, partyId, this.#pkg);
106
+ getPartyById(
107
+ partyId: string,
108
+ ): Effect.Effect<Party, ObjectNotFoundError | ObjectTypeMismatchError | BcsDecodeError | SuiRpcError> {
109
+ return this.#provide(queries.getPartyById(partyId, this.#pkg));
96
110
  }
97
- async getPartiesByIds(partyIds: readonly string[]): Promise<Partial<Record<string, Party>>> {
98
- return queries.getPartiesByIds(this.#client, partyIds, this.#pkg);
111
+ getPartiesByIds(
112
+ partyIds: readonly string[],
113
+ ): Effect.Effect<Partial<Record<string, Party>>, ObjectTypeMismatchError | BcsDecodeError | SuiRpcError> {
114
+ return this.#provide(queries.getPartiesByIds(partyIds, this.#pkg));
99
115
  }
100
116
  derivePartyAdminCapId(partyId: string): string {
101
117
  return queries.derivePartyAdminCapId(partyId, this.#pkg);
102
118
  }
103
119
  /** Group ids a party belongs to (member-side membership records). */
104
- async getMemberships(partyId: string): Promise<string[]> {
105
- return queries.getMemberships(this.#client, partyId);
120
+ getMemberships(partyId: string): Effect.Effect<string[], SuiRpcError> {
121
+ return this.#provide(queries.getMemberships(partyId));
106
122
  }
107
123
  /** Member ids invited to a group but not yet accepted. */
108
- async getPendingInvites(groupId: string): Promise<string[]> {
109
- return queries.getPendingInvites(this.#client, groupId);
124
+ getPendingInvites(groupId: string): Effect.Effect<string[], SuiRpcError> {
125
+ return this.#provide(queries.getPendingInvites(groupId));
110
126
  }
111
127
  /** Group ids that have invited this party but are awaiting its response. */
112
- async getPendingMemberships(partyId: string): Promise<string[]> {
113
- return queries.getPendingMemberships(this.#client, partyId);
128
+ getPendingMemberships(partyId: string): Effect.Effect<string[], SuiRpcError> {
129
+ return this.#provide(queries.getPendingMemberships(partyId));
114
130
  }
115
131
  /** Whether a party is a member of a group. */
116
- async isMember(memberId: string, groupId: string): Promise<boolean> {
117
- return queries.isMember(this.#client, memberId, groupId, this.#pkg);
132
+ isMember(memberId: string, groupId: string): Effect.Effect<boolean, SuiRpcError> {
133
+ return this.#provide(queries.isMember(memberId, groupId, this.#pkg));
118
134
  }
119
135
 
120
136
  // === Transaction builders (thunks; the package id is bound from the client) ===
@@ -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";
5
7
 
6
8
  /** Sui networks for which this SDK may bundle a verified deployment. */
7
9
  export type PartyosNetwork = "mainnet" | "testnet";
@@ -26,7 +28,7 @@ export type PartyDeployment = Readonly<Record<PartyosPackageName, string>>;
26
28
  /** Verified immutable deployments bundled with this SDK release. */
27
29
  export const PARTYOS_DEPLOYMENTS = Object.freeze({
28
30
  testnet: Object.freeze({
29
- partyos: "0xc9fc5d918da992b7c6499880fc509635def384d8529948b28f58494daedf8ec8",
31
+ partyos: "0x342425da86c4389c1f5558013251f18017ead98414db5644569890ba3a4a434c",
30
32
  } as const),
31
33
  } as const) satisfies Partial<Record<PartyosNetwork, PartyDeployment>>;
32
34
 
@@ -88,3 +90,17 @@ export function normalizePartyDeployment(deployment: unknown): PartyDeployment {
88
90
  Object.fromEntries(CANONICAL_PARTYOS_PACKAGE_NAMES.map((name) => [name, deployment[name]])),
89
91
  ) as PartyDeployment;
90
92
  }
93
+
94
+ /**
95
+ * Effect counterpart to {@link normalizePartyDeployment}: validation is pure and
96
+ * synchronous, so this exists only for callers composing a config-loading
97
+ * pipeline out of Effects rather than throwing at a configuration boundary.
98
+ */
99
+ export const validatePartyDeployment = Effect.fn("validatePartyDeployment")(function* (
100
+ input: unknown,
101
+ ): Effect.fn.Return<PartyDeployment, DeploymentError> {
102
+ return yield* Effect.try({
103
+ try: () => normalizePartyDeployment(input),
104
+ catch: (cause) => new DeploymentError({ message: cause instanceof Error ? cause.message : String(cause) }),
105
+ });
106
+ });
package/src/errors.ts ADDED
@@ -0,0 +1,18 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // Party-specific tagged errors, plus the shared vocabulary re-exported so
5
+ // callers never need to reach into `@misofm/effect` directly. `getPartyById`
6
+ // and `getPartiesByIds` fail with the foundation's `ObjectNotFoundError` /
7
+ // `ObjectTypeMismatchError` — `PartyNotFoundError` below is offered for
8
+ // callers that want a party-scoped tag instead of pattern-matching the
9
+ // generic object vocabulary.
10
+
11
+ import { Schema } from "effect";
12
+
13
+ export * from "@misofm/effect/errors";
14
+
15
+ /** A party object does not exist (never existed, was deleted, or the id is not a party). */
16
+ export class PartyNotFoundError extends Schema.TaggedError<PartyNotFoundError>()("PartyNotFoundError", {
17
+ partyId: Schema.String,
18
+ }) {}
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export * from "./transactions.ts";
10
10
  export * from "./queries.ts";
11
11
  export * from "./client.ts";
12
12
  export * from "./deployments.ts";
13
+ export * from "./errors.ts";
13
14
 
14
15
  // Generated, ABI-bound bindings (BCS structs + type-safe Move calls).
15
16
  export * as contracts from "./contracts.ts";
package/src/internal.ts CHANGED
@@ -2,13 +2,15 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  // The single boundary between generated BCS-parse output (snake_case, Move-shaped)
5
- // and the public camelCase types.
5
+ // and the public camelCase types. `mapParty` returns a plain object shaped like
6
+ // `Party`'s encoded form; `Schema.decodeUnknownEffect(Party)` (via `decodeBcs`)
7
+ // validates and constructs the class from it.
6
8
 
7
9
  import { fromBase64 } from "@mysten/sui/utils";
8
10
  import type { Party } from "./types.ts";
9
11
 
10
12
  // deno-lint-ignore no-explicit-any -- generated parse output is loosely typed
11
- export function mapParty(id: string, d: any): Party {
13
+ export function mapParty(id: string, d: any): typeof Party.Encoded {
12
14
  const kind = d.kind;
13
15
  const createdAtMs = Number(d.created_at_ms);
14
16
  // PartyKind is `Individual | Group(VecSet<ID>)`. The enum parses to