@zing-protocol/zing-sdk 0.0.14 → 0.0.16

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/bcs.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { ObjectOwner } from "@mysten/sui/client";
2
1
  export declare const BlobId: import("@mysten/sui/bcs").BcsType<string, string | bigint, "u256">;
3
2
  export declare const QuiltPatchId: import("@mysten/sui/bcs").BcsStruct<{
4
3
  quiltId: import("@mysten/sui/bcs").BcsType<string, string | bigint, "u256">;
@@ -46,16 +45,3 @@ export declare const MoveObjectType: import("@mysten/sui/bcs").BcsEnum<{
46
45
  StakedSui: null;
47
46
  Coin: import("@mysten/sui/bcs").BcsType<string, string | import("@mysten/sui/bcs").TypeTag, string>;
48
47
  }, "MoveObjectType">;
49
- export declare const SuiMoveObject: import("@mysten/sui/bcs").BcsStruct<{
50
- data: import("@mysten/sui/bcs").BcsEnum<{
51
- MoveObject: import("@mysten/sui/bcs").BcsStruct<{
52
- type: import("@mysten/sui/bcs").BcsType<any, string, string>;
53
- hasPublicTransfer: import("@mysten/sui/bcs").BcsType<boolean, boolean, "bool">;
54
- version: import("@mysten/sui/bcs").BcsType<string, string | number | bigint, "u64">;
55
- contents: import("@mysten/sui/bcs").BcsType<any, string, string>;
56
- }, string>;
57
- }, "Data">;
58
- owner: import("@mysten/sui/bcs").BcsType<any, ObjectOwner, string>;
59
- previousTransaction: import("@mysten/sui/bcs").BcsType<string, string, "ObjectDigest">;
60
- storageRebate: import("@mysten/sui/bcs").BcsType<string, string | number | bigint, "u64">;
61
- }, string>;
package/dist/bcs.js CHANGED
@@ -1,5 +1,4 @@
1
- import { bcs, TypeTagSerializer } from "@mysten/sui/bcs";
2
- import { fromBase64, normalizeStructTag, parseStructTag, SUI_FRAMEWORK_ADDRESS, SUI_SYSTEM_ADDRESS, } from "@mysten/sui/utils";
1
+ import { bcs } from "@mysten/sui/bcs";
3
2
  import { blobIdFromInt, blobIdToInt } from "@mysten/walrus";
4
3
  function compareBcsBytes(a, b) {
5
4
  // sort by length first, because bcs bytes prefix length
@@ -44,66 +43,3 @@ export const MoveObjectType = bcs.enum("MoveObjectType", {
44
43
  StakedSui: null,
45
44
  Coin: bcs.TypeTag,
46
45
  });
47
- export const SuiMoveObject = bcs.struct("SuiMoveObject", {
48
- data: bcs.enum("Data", {
49
- MoveObject: bcs.struct("MoveObject", {
50
- type: MoveObjectType.transform({
51
- input: (objectType) => {
52
- const structTag = parseStructTag(objectType);
53
- if (structTag.address === SUI_FRAMEWORK_ADDRESS &&
54
- structTag.module === "coin" &&
55
- structTag.name === "Coin" &&
56
- typeof structTag.typeParams[0] === "object") {
57
- const innerStructTag = structTag.typeParams[0];
58
- if (innerStructTag.address === SUI_FRAMEWORK_ADDRESS &&
59
- innerStructTag.module === "sui" &&
60
- innerStructTag.name === "SUI") {
61
- return { GasCoin: true, $kind: "GasCoin" };
62
- }
63
- return { Coin: normalizeStructTag(innerStructTag), $kind: "Coin" };
64
- }
65
- else if (structTag.address === SUI_SYSTEM_ADDRESS &&
66
- structTag.module === "staking_pool" &&
67
- structTag.name === "StakedSui") {
68
- return { StakedSui: true, $kind: "StakedSui" };
69
- }
70
- return {
71
- Other: {
72
- ...structTag,
73
- typeParams: structTag.typeParams.map((typeParam) => TypeTagSerializer.parseFromStr(normalizeStructTag(typeParam))),
74
- },
75
- $kind: "Other",
76
- };
77
- },
78
- }),
79
- hasPublicTransfer: bcs.bool(),
80
- version: bcs.u64(),
81
- contents: bcs.byteVector().transform({ input: fromBase64 }),
82
- }),
83
- }),
84
- owner: bcs.Owner.transform({
85
- input: (objectOwner) => {
86
- if (objectOwner === "Immutable") {
87
- return { Immutable: null };
88
- }
89
- else if ("Shared" in objectOwner) {
90
- return {
91
- Shared: {
92
- initialSharedVersion: objectOwner.Shared.initial_shared_version,
93
- },
94
- };
95
- }
96
- else if ("ConsensusAddressOwner" in objectOwner) {
97
- return {
98
- ConsensusAddressOwner: {
99
- owner: objectOwner.ConsensusAddressOwner.owner,
100
- startVersion: objectOwner.ConsensusAddressOwner.start_version,
101
- },
102
- };
103
- }
104
- return objectOwner;
105
- },
106
- }),
107
- previousTransaction: bcs.ObjectDigest,
108
- storageRebate: bcs.u64(),
109
- });
@@ -6,18 +6,15 @@ import type { Config } from "../config/types.js";
6
6
  import type { SuiNetwork, ZKLoginSignerState } from "../types.js";
7
7
  import type { SealClient } from "@mysten/seal";
8
8
  import type { SuiGrpcClient } from "@mysten/sui/grpc";
9
- import type { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
10
9
  interface Params {
11
10
  network: SuiNetwork;
12
11
  suiGrpcClient: SuiGrpcClient;
13
- suiJsonRpcClient: SuiJsonRpcClient;
14
12
  }
15
13
  export declare class ZingClient {
16
14
  suiGrpcClient: SuiGrpcClient;
17
- suiJsonRpcClient: SuiJsonRpcClient;
18
15
  network: SuiNetwork;
19
16
  config: Config;
20
- constructor({ network, suiGrpcClient, suiJsonRpcClient }: Params);
17
+ constructor({ network, suiGrpcClient }: Params);
21
18
  getConfig(): Config;
22
19
  getDerivedStudioID(address: string): string;
23
20
  getDerivedStorageID(address: string): string;
@@ -266,8 +263,8 @@ export declare class ZingClient {
266
263
  }[];
267
264
  };
268
265
  }[]>;
269
- getBalance(owner: string, coinSymbol: CoinSymbol): Promise<import("node_modules/@mysten/sui/dist/esm/grpc/proto/sui/rpc/v2/state_service.js").GetBalanceResponse>;
270
- getSessionKey(saltServerUrl: string, signer: ZKLoginSignerState, owner: string): Promise<SessionKey>;
266
+ getBalance(owner: string, coinSymbol: CoinSymbol): Promise<import("node_modules/@mysten/sui/dist/grpc/proto/sui/rpc/v2/state_service.mjs").GetBalanceResponse>;
267
+ getSessionKey(saltServerUrl: string, signer: ZKLoginSignerState, owner: string): Promise<SessionKey | null>;
271
268
  buildSealApproveTransactionBytes(owner: string): Promise<Uint8Array<ArrayBuffer>>;
272
269
  getFileKey(sealClient: SealClient, sessionKey: SessionKey, owner: string, encryptedFileKeyBytes: number[]): Promise<CryptoKey>;
273
270
  subscribeToStudioTransaction({ sender, creatorAddress, subscriptionAmount, level, }: SubscribeParams): (tx: Transaction) => void;
@@ -11,9 +11,8 @@ import { SessionKey } from "@mysten/seal";
11
11
  import { Transaction, coinWithBalance } from "@mysten/sui/transactions";
12
12
  import { fromHex } from "@mysten/sui/utils";
13
13
  export class ZingClient {
14
- constructor({ network, suiGrpcClient, suiJsonRpcClient }) {
14
+ constructor({ network, suiGrpcClient }) {
15
15
  this.suiGrpcClient = suiGrpcClient;
16
- this.suiJsonRpcClient = suiJsonRpcClient;
17
16
  this.network = network || "testnet";
18
17
  this.config = getConfig(network);
19
18
  }
@@ -99,24 +98,31 @@ export class ZingClient {
99
98
  .then((res) => res.response);
100
99
  }
101
100
  async getSessionKey(saltServerUrl, signer, owner) {
102
- const { suiAddress, ephemeralKeyPair, decodedJwt, zkProof, maxEpoch } = signer;
103
- if (!suiAddress ||
104
- !ephemeralKeyPair ||
105
- !decodedJwt ||
106
- !zkProof ||
107
- !maxEpoch) {
108
- throw new Error("Missing required wallet data for session key creation");
101
+ try {
102
+ const { suiAddress, ephemeralKeyPair, decodedJwt, zkProof, maxEpoch } = signer;
103
+ if (!suiAddress ||
104
+ !ephemeralKeyPair ||
105
+ !decodedJwt ||
106
+ !zkProof ||
107
+ !maxEpoch) {
108
+ throw new Error("Missing required wallet data for session key creation");
109
+ }
110
+ const sessionKey = await SessionKey.create({
111
+ address: owner,
112
+ packageId: this.config.zing.ZING_STUDIO_V0_PACKAGE_ADDRESS,
113
+ ttlMin: 10,
114
+ suiClient: this.suiGrpcClient,
115
+ });
116
+ const message = sessionKey.getPersonalMessage();
117
+ const { zkLoginSignature } = await signPersonalMessage(saltServerUrl, signer, message);
118
+ await sessionKey.setPersonalMessageSignature(zkLoginSignature);
119
+ return sessionKey;
120
+ }
121
+ catch (error) {
122
+ console.error("Fail to get SessionKey");
123
+ console.error({ error });
124
+ return null;
109
125
  }
110
- const sessionKey = await SessionKey.create({
111
- address: owner,
112
- packageId: this.config.zing.ZING_STUDIO_V0_PACKAGE_ADDRESS,
113
- ttlMin: 10,
114
- suiClient: this.suiJsonRpcClient,
115
- });
116
- const message = sessionKey.getPersonalMessage();
117
- const { zkLoginSignature } = await signPersonalMessage(saltServerUrl, signer, message);
118
- sessionKey.setPersonalMessageSignature(zkLoginSignature);
119
- return sessionKey;
120
126
  }
121
127
  async buildSealApproveTransactionBytes(owner) {
122
128
  const tx = new Transaction();
@@ -131,17 +137,19 @@ export class ZingClient {
131
137
  },
132
138
  }));
133
139
  return tx.build({
134
- client: this.suiJsonRpcClient,
140
+ client: this.suiGrpcClient,
135
141
  onlyTransactionKind: true,
136
142
  });
137
143
  }
138
144
  async getFileKey(sealClient, sessionKey, owner, encryptedFileKeyBytes) {
139
145
  const txBytes = await this.buildSealApproveTransactionBytes(owner);
146
+ console.log({ txBytes });
140
147
  const decryptedKey = await sealClient.decrypt({
141
148
  data: new Uint8Array(encryptedFileKeyBytes),
142
149
  sessionKey,
143
150
  txBytes,
144
151
  });
152
+ console.log({ decryptedKey });
145
153
  return await importFileKey(decryptedKey);
146
154
  }
147
155
  // --- Transaction Builders ---
@@ -38,7 +38,7 @@ export const WalrusProvider = ({ walrusClient, sealClient, children, autoInit =
38
38
  zingStorageTreasurySharedObjectRef: config.zing.ZING_STORAGE_TREASURY_SHARED_OBJECT_REF,
39
39
  blobRegisteredEventType: config.walrus.EVENT_TYPES.blobRegistered,
40
40
  publishArticleEventType: config.zing.EVENT_TYPES.publishArticleEvent,
41
- }, zingClient.suiGrpcClient, zingClient.suiJsonRpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, walrusFiles, subscriptionLevel, metadata, saltServerUrl, signer, onProgress);
41
+ }, zingClient.suiGrpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, walrusFiles, subscriptionLevel, metadata, saltServerUrl, signer, onProgress);
42
42
  }, [walrusClient]);
43
43
  const calculateQuiltSize = useCallback((walrusSystem, files, ivSize = 12) => {
44
44
  const numShards = walrusSystem.committee.n_shards;
@@ -1,12 +1,10 @@
1
1
  import { ZingClient } from "../client/index.js";
2
2
  import type { SuiNetwork } from "../types.js";
3
3
  import type { SuiGrpcClient } from "@mysten/sui/grpc";
4
- import type { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
5
4
  import type { ReactNode } from "react";
6
5
  interface ZingClientProviderProps {
7
6
  network: SuiNetwork;
8
7
  suiGrpcClient: SuiGrpcClient;
9
- suiJsonRpcClient: SuiJsonRpcClient;
10
8
  children: ReactNode;
11
9
  }
12
10
  export declare const ZingClientProvider: React.FC<ZingClientProviderProps>;
@@ -4,12 +4,11 @@ import { createContext, useContext, useMemo } from "react";
4
4
  const ZingClientContext = createContext({
5
5
  client: null,
6
6
  });
7
- export const ZingClientProvider = ({ network, suiGrpcClient, suiJsonRpcClient, children, }) => {
7
+ export const ZingClientProvider = ({ network, suiGrpcClient, children, }) => {
8
8
  const client = useMemo(() => new ZingClient({
9
9
  network,
10
10
  suiGrpcClient,
11
- suiJsonRpcClient,
12
- }), [network, suiGrpcClient, suiJsonRpcClient]);
11
+ }), [network, suiGrpcClient]);
13
12
  return (_jsx(ZingClientContext.Provider, { value: { client }, children: children }));
14
13
  };
15
14
  export const useZingClient = () => {
@@ -1,7 +1,7 @@
1
1
  export const testnetZingConfig = {
2
2
  ZING_FRAMEWORK_PACKAGE_ADDRESS: "0xd851eb5b907b60aa5fd958dd74044d809c49ee60001cad621726f03ea138f943",
3
3
  ZING_IDENTITY_PACKAGE_ADDRESS: "0xaaf27a90890ac1efface4fbb22597e95829cbe6cbb771df02f0d2cc93f067c70",
4
- ZING_STUDIO_PACKAGE_ADDRESS: "0x4e497b857da8adcd084fd39a887c36801499a1314bb94e026d9e93d13f8f40e5",
4
+ ZING_STUDIO_PACKAGE_ADDRESS: "0x200e858488929b31f7dbfa87ea85a1ada811945f33fb00aefe600762855507db",
5
5
  ZING_STUDIO_V0_PACKAGE_ADDRESS: "0x3502955f106ee334653443005b37ebc6d1ddf7b9c704d39090263ae136ba599d",
6
6
  ZING_TREASURY_SHARED_OBJECT_REF: {
7
7
  objectId: "0xca56bc3982525decbd4b025d3d4ae4de07259d6efc187577bfc3ab212e20574f",
package/dist/getters.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { QuiltPatchId } from "./bcs.js";
2
2
  import type { SuiGrpcClient } from "@mysten/sui/grpc";
3
- import type { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
4
3
  import type { EncodingType, WalrusClient } from "@mysten/walrus";
5
4
  export declare function getDerivedStudioID(studioConfigId: string, address: string): string;
6
5
  export declare function getDerivedStorageID(studioConfigId: string, address: string): string;
@@ -257,7 +256,7 @@ export declare function getWorksByObjectIds(suiGrpcClient: SuiGrpcClient, workOb
257
256
  }[];
258
257
  };
259
258
  }[]>;
260
- export declare function getPublishedArticleAndBlobId(suiGrpcClient: SuiGrpcClient, suiClient: SuiJsonRpcClient, walrusClient: WalrusClient, digest: string, blobRegisteredEventType: string, publishArticleEventType: string): Promise<{
259
+ export declare function getPublishedArticleAndBlobId(suiGrpcClient: SuiGrpcClient, walrusClient: WalrusClient, digest: string, blobRegisteredEventType: string, publishArticleEventType: string): Promise<{
261
260
  parsedPublishArticleEvent: {
262
261
  article_id: string;
263
262
  owner: string;
package/dist/getters.js CHANGED
@@ -7,7 +7,7 @@ import { BlobRegistered } from "./_generated/zing_studio/deps/walrus/events.js";
7
7
  import { Referral } from "./_generated/zing_studio/referral.js";
8
8
  import { StorageSpace, StorageTreasury, } from "./_generated/zing_studio/storage.js";
9
9
  import { Member, Studio } from "./_generated/zing_studio/studio.js";
10
- import { QuiltPatchId, SuiMoveObject } from "./bcs.js";
10
+ import { QuiltPatchId } from "./bcs.js";
11
11
  import { bcs } from "@mysten/sui/bcs";
12
12
  import { deriveDynamicFieldID, deriveObjectID, fromBase64, normalizeStructTag, toBase64, } from "@mysten/sui/utils";
13
13
  // Walrus
@@ -48,8 +48,10 @@ export async function getIdentifierByAddress(suiGrpcClient, addressToIdentifierD
48
48
  if (!res.response.object?.bcs?.value) {
49
49
  return null;
50
50
  }
51
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
52
- const field = Field(bcs.Address, bcs.String).parse(suiMoveObject.data.MoveObject.contents);
51
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
52
+ if (suiMoveObject.data.$kind === "Package")
53
+ throw new Error("Move Object is Package");
54
+ const field = Field(bcs.Address, bcs.String).parse(suiMoveObject.data.Move.contents);
53
55
  return field.value;
54
56
  }
55
57
  export async function getIdentifierInfoByIdentifier(suiGrpcClient, identifierInfoDynamicFieldId, identifier) {
@@ -63,8 +65,10 @@ export async function getIdentifierInfoByIdentifier(suiGrpcClient, identifierInf
63
65
  if (!res.response.object?.bcs?.value) {
64
66
  return null;
65
67
  }
66
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
67
- const field = Field(bcs.String, IdentifierInfo).parse(suiMoveObject.data.MoveObject.contents);
68
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
69
+ if (suiMoveObject.data.$kind === "Package")
70
+ throw new Error("Move Object is Package");
71
+ const field = Field(bcs.String, IdentifierInfo).parse(suiMoveObject.data.Move.contents);
68
72
  return field.value;
69
73
  }
70
74
  export async function getDonationByIdentifier(suiGrpcClient, donationTableId, identifier) {
@@ -78,8 +82,10 @@ export async function getDonationByIdentifier(suiGrpcClient, donationTableId, id
78
82
  if (!res.response.object?.bcs?.value) {
79
83
  return null;
80
84
  }
81
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
82
- const field = Field(bcs.String, VecMap(TypeName, bcs.U64)).parse(suiMoveObject.data.MoveObject.contents);
85
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
86
+ if (suiMoveObject.data.$kind === "Package")
87
+ throw new Error("Move Object is Package");
88
+ const field = Field(bcs.String, VecMap(TypeName, bcs.U64)).parse(suiMoveObject.data.Move.contents);
83
89
  return field.value;
84
90
  }
85
91
  export async function getStudio(suiGrpcClient, studioId) {
@@ -93,8 +99,10 @@ export async function getStudio(suiGrpcClient, studioId) {
93
99
  if (!res.response.object?.bcs?.value) {
94
100
  return null;
95
101
  }
96
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
97
- return Studio.parse(suiMoveObject.data.MoveObject.contents);
102
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
103
+ if (suiMoveObject.data.$kind === "Package")
104
+ throw new Error("Move Object is Package");
105
+ return Studio.parse(suiMoveObject.data.Move.contents);
98
106
  }
99
107
  catch (error) {
100
108
  console.error(error);
@@ -112,8 +120,10 @@ export async function getStorageSpace(suiGrpcClient, storageSpaceId) {
112
120
  if (!res.response.object?.bcs?.value) {
113
121
  return null;
114
122
  }
115
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
116
- return StorageSpace.parse(suiMoveObject.data.MoveObject.contents);
123
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
124
+ if (suiMoveObject.data.$kind === "Package")
125
+ throw new Error("Move Object is Package");
126
+ return StorageSpace.parse(suiMoveObject.data.Move.contents);
117
127
  }
118
128
  catch (error) {
119
129
  console.error(error);
@@ -130,8 +140,10 @@ export async function getStorageTreasury(suiGrpcClient, storageTreasuryId) {
130
140
  if (!res.response.object?.bcs?.value) {
131
141
  return null;
132
142
  }
133
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
134
- return StorageTreasury.parse(suiMoveObject.data.MoveObject.contents);
143
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
144
+ if (suiMoveObject.data.$kind === "Package")
145
+ throw new Error("Move Object is Package");
146
+ return StorageTreasury.parse(suiMoveObject.data.Move.contents);
135
147
  }
136
148
  export async function getMember(suiGrpcClient, membershipTableId, member) {
137
149
  const dfObjectId = deriveDynamicFieldID(membershipTableId, "address", bcs.Address.serialize(member).toBytes());
@@ -144,8 +156,10 @@ export async function getMember(suiGrpcClient, membershipTableId, member) {
144
156
  if (!res.response.object?.bcs?.value) {
145
157
  return null;
146
158
  }
147
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
148
- const field = Field(bcs.Address, Member).parse(suiMoveObject.data.MoveObject.contents);
159
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
160
+ if (suiMoveObject.data.$kind === "Package")
161
+ throw new Error("Move Object is Package");
162
+ const field = Field(bcs.Address, Member).parse(suiMoveObject.data.Move.contents);
149
163
  return field.value;
150
164
  }
151
165
  export async function getMembers(suiGrpcClient, membershipTableId, cursor, limit = 20) {
@@ -160,9 +174,11 @@ export async function getMembers(suiGrpcClient, membershipTableId, cursor, limit
160
174
  const data = res.response.dynamicFields.map((df) => {
161
175
  if (!df.fieldObject?.bcs?.value)
162
176
  throw new Error("Wrong readMask for reading members");
163
- const suiMoveObject = SuiMoveObject.parse(df.fieldObject.bcs.value);
177
+ const suiMoveObject = bcs.Object.parse(df.fieldObject.bcs.value);
164
178
  // Wrapped in dynamicFields
165
- const field = Field(bcs.Address, Member).parse(suiMoveObject.data.MoveObject.contents);
179
+ if (suiMoveObject.data.$kind === "Package")
180
+ throw new Error("Move Object is Package");
181
+ const field = Field(bcs.Address, Member).parse(suiMoveObject.data.Move.contents);
166
182
  return {
167
183
  member: field.name,
168
184
  level: field.value.level,
@@ -187,8 +203,10 @@ export async function getReferral(suiGrpcClient, referralID) {
187
203
  if (!res.response.object?.bcs?.value) {
188
204
  return null;
189
205
  }
190
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
191
- const field = Field(bcs.vector(bcs.u8()), Referral).parse(suiMoveObject.data.MoveObject.contents);
206
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
207
+ if (suiMoveObject.data.$kind === "Package")
208
+ throw new Error("Move Object is Package");
209
+ const field = Field(bcs.vector(bcs.u8()), Referral).parse(suiMoveObject.data.Move.contents);
192
210
  return field.value;
193
211
  }
194
212
  export async function getWork(suiGrpcClient, workId, workType) {
@@ -201,13 +219,14 @@ export async function getWork(suiGrpcClient, workId, workType) {
201
219
  if (!res.response.object?.bcs?.value) {
202
220
  return null;
203
221
  }
204
- const suiMoveObject = SuiMoveObject.parse(res.response.object.bcs.value);
205
- const type = suiMoveObject.data.MoveObject
206
- .type;
222
+ const suiMoveObject = bcs.Object.parse(res.response.object.bcs.value);
223
+ if (suiMoveObject.data.$kind === "Package")
224
+ throw new Error("Move Object is Package");
225
+ const type = suiMoveObject.data.Move.type;
207
226
  if (type.$kind !== "Other" ||
208
227
  normalizeStructTag(type.Other) !== workType)
209
228
  return null;
210
- return Article.parse(suiMoveObject.data.MoveObject.contents);
229
+ return Article.parse(suiMoveObject.data.Move.contents);
211
230
  }
212
231
  export async function getWorks(suiGrpcClient, workTableId, workType, cursor, limit = 20) {
213
232
  const res = await suiGrpcClient.stateService.listDynamicFields({
@@ -248,19 +267,24 @@ export async function getWorksByObjectIds(suiGrpcClient, workObjectIds, workType
248
267
  const suiMoveObjects = [];
249
268
  res.response.objects.forEach((obj) => {
250
269
  if (obj.result.oneofKind === "object" && obj.result.object.bcs?.value) {
251
- const suiMoveObject = SuiMoveObject.parse(obj.result.object.bcs.value);
252
- const type = suiMoveObject.data.MoveObject
253
- .type;
270
+ const suiMoveObject = bcs.Object.parse(obj.result.object.bcs.value);
271
+ if (suiMoveObject.data.$kind === "Package")
272
+ throw new Error("Move Object is Package");
273
+ const type = suiMoveObject.data.Move.type;
254
274
  const workType_ = normalizeStructTag(type.Other);
255
275
  if (type.$kind === "Other" && workType_ === workType)
256
276
  suiMoveObjects.push(suiMoveObject);
257
277
  }
258
278
  });
259
- return suiMoveObjects.map((obj) => Article.parse(obj.data.MoveObject.contents));
279
+ return suiMoveObjects.map((obj) => {
280
+ if (obj.data.$kind === "Package")
281
+ throw new Error("Move Object is Package");
282
+ return Article.parse(obj.data.Move.contents);
283
+ });
260
284
  }
261
- export async function getPublishedArticleAndBlobId(suiGrpcClient, suiClient, walrusClient, digest, blobRegisteredEventType, publishArticleEventType) {
285
+ export async function getPublishedArticleAndBlobId(suiGrpcClient, walrusClient, digest, blobRegisteredEventType, publishArticleEventType) {
262
286
  // suiGrpcClient waitForTransaction calling core.getTransaction which is broken
263
- await suiClient.waitForTransaction({
287
+ await suiGrpcClient.core.waitForTransaction({
264
288
  digest,
265
289
  });
266
290
  if (!digest)
@@ -1,11 +1,11 @@
1
1
  import type { PlatformType } from "../config/common.js";
2
2
  import type { ReclaimProof } from "../lib/utils/reclaim.js";
3
- import type { SuiClient } from "@mysten/sui/client";
3
+ import type { SuiGrpcClient } from "@mysten/sui/grpc";
4
4
  interface CommitProofParams {
5
- suiClient: SuiClient;
5
+ suiClient: SuiGrpcClient;
6
6
  walletAddress: string;
7
7
  platform: PlatformType;
8
8
  proof: ReclaimProof;
9
9
  }
10
- export declare function useCommitProof(): import("@tanstack/react-query").UseMutationResult<any, Error, CommitProofParams, unknown>;
10
+ export declare function useCommitProof(): import("@tanstack/react-query").UseMutationResult<import("@mysten/sui/jsonRpc").TransactionEffects | null, Error, CommitProofParams, unknown>;
11
11
  export {};
@@ -32,20 +32,27 @@ export function useCommitProof() {
32
32
  });
33
33
  if (!commitTransactionResponse)
34
34
  throw new Error("fail to commit proof");
35
- const commitTransactionObjectChanges = (await suiClient.waitForTransaction({
35
+ const settledCommitTransactionResult = await suiClient.waitForTransaction({
36
36
  digest: commitTransactionResponse.transactionDigest,
37
- options: {
38
- showObjectChanges: true,
37
+ include: {
38
+ effects: true,
39
+ objectTypes: true,
39
40
  },
40
- })).objectChanges;
41
+ });
42
+ const commitTransactionObjectChanges = settledCommitTransactionResult.Transaction?.effects.changedObjects ||
43
+ [];
41
44
  if (!commitTransactionObjectChanges)
42
45
  throw new Error("fail to commit proof");
43
- const commitment = commitTransactionObjectChanges.find((objChanges) => objChanges.type === "created" &&
44
- objChanges.objectType === config.zing.PROOF_COMMITMENT_TYPE);
45
- if (!commitment || commitment.type !== "created")
46
+ const commitment = commitTransactionObjectChanges.find((objChange) => {
47
+ if (objChange.idOperation !== "Created")
48
+ return false;
49
+ const type = settledCommitTransactionResult.Transaction?.objectTypes[objChange.objectId];
50
+ return type === config.zing.PROOF_COMMITMENT_TYPE;
51
+ });
52
+ if (!commitment || commitment.idOperation !== "Created")
46
53
  throw new Error("fail to commit proof");
47
54
  const revealTransaction = new Transaction();
48
- const [signers, proofObj] = revealTransaction.add(revealAndVerifyProof({
55
+ const [, proofObj] = revealTransaction.add(revealAndVerifyProof({
49
56
  package: config.zing.ZING_IDENTITY_PACKAGE_ADDRESS,
50
57
  typeArguments: [identityPlatform.PLATFORM_TYPE],
51
58
  arguments: {
@@ -2,5 +2,5 @@ import type { Transaction } from "@mysten/sui/transactions";
2
2
  interface SignAndExecuteTransactionParams {
3
3
  transaction: Transaction;
4
4
  }
5
- export declare const useSignAndExecuteTransaction: () => import("@tanstack/react-query").UseMutationResult<any, Error, SignAndExecuteTransactionParams, unknown>;
5
+ export declare const useSignAndExecuteTransaction: () => import("@tanstack/react-query").UseMutationResult<import("@mysten/sui/jsonRpc").TransactionEffects | null, Error, SignAndExecuteTransactionParams, unknown>;
6
6
  export {};
@@ -18,11 +18,14 @@ export const useSignAndExecuteTransaction = () => {
18
18
  // for Debug usage
19
19
  transaction.setSender(signer.suiAddress);
20
20
  transaction.setGasOwner(GAS_POOL_OWNER);
21
- const dryRunResponse = await suiClient.dryRunTransactionBlock({
22
- transactionBlock: await transaction.build({ client: suiClient }),
21
+ const dryRunResponse = await suiClient.simulateTransaction({
22
+ transaction: await transaction.build({ client: suiClient }),
23
+ include: {
24
+ effects: true,
25
+ },
23
26
  });
24
27
  console.log({ dryRunResponse });
25
- if (dryRunResponse.effects.status.status === "success") {
28
+ if (dryRunResponse.Transaction?.effects.status.success) {
26
29
  const effects = await signAndExecuteGasPoolTransaction(saltServerUrl, signer, suiClient, transaction);
27
30
  // TODO: handle error message by code
28
31
  if (!effects)
@@ -1,6 +1,6 @@
1
1
  import { Transaction } from "@mysten/sui/transactions";
2
2
  import type { ZingClient } from "../client/index.js";
3
- import type { TransactionEffects } from "@mysten/sui/client";
3
+ import type { TransactionEffects } from "@mysten/sui/jsonRpc";
4
4
  declare const zingMutationMethodMap: (zingClient: ZingClient) => {
5
5
  subscribeToStudioTransaction: ({ sender, creatorAddress, subscriptionAmount, level, }: import("../client/types.js").SubscribeParams) => (tx: Transaction) => void;
6
6
  purchaseStorageTierTransaction: ({ sender, objs, newTierIdx, balance, referrer, }: import("../client/types.js").PurchaseStorageTierParams) => (tx: Transaction) => void;
@@ -28,7 +28,7 @@ export function useZingMutation() {
28
28
  },
29
29
  onSuccess: async (effects) => {
30
30
  if (effects?.transactionDigest) {
31
- await zingClient.suiJsonRpcClient.waitForTransaction({
31
+ await zingClient.suiGrpcClient.waitForTransaction({
32
32
  digest: effects.transactionDigest,
33
33
  });
34
34
  }
@@ -111,7 +111,7 @@ declare const zingQueryMethodMap: (zingClient: ZingClient) => {
111
111
  level: number;
112
112
  expired_at: string;
113
113
  } | null>;
114
- getBalance: (owner: string, coinSymbol: import("../index.js").CoinSymbol) => Promise<import("node_modules/@mysten/sui/dist/esm/grpc/proto/sui/rpc/v2/state_service.js").GetBalanceResponse>;
114
+ getBalance: (owner: string, coinSymbol: import("../index.js").CoinSymbol) => Promise<import("node_modules/@mysten/sui/dist/grpc/proto/sui/rpc/v2/state_service.mjs").GetBalanceResponse>;
115
115
  };
116
116
  type ZingQueryMethods = ReturnType<typeof zingQueryMethodMap>;
117
117
  type ExtractParams<T> = T extends (...args: infer P) => any ? P : never;
@@ -117,7 +117,7 @@ declare const zingQueryMethodMap: (zingClient: ZingClient) => {
117
117
  referrer: string;
118
118
  expired_at: string;
119
119
  } | null>;
120
- getBalance: (owner: string, coinSymbol: import("../index.js").CoinSymbol) => Promise<import("node_modules/@mysten/sui/dist/esm/grpc/proto/sui/rpc/v2/state_service.js").GetBalanceResponse>;
120
+ getBalance: (owner: string, coinSymbol: import("../index.js").CoinSymbol) => Promise<import("node_modules/@mysten/sui/dist/grpc/proto/sui/rpc/v2/state_service.mjs").GetBalanceResponse>;
121
121
  getWork: (workId: string, workType?: import("../index.js").WorkType) => Promise<{
122
122
  id: {
123
123
  id: string;
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from "./bcs.js";
8
8
  export * from "./_generated/index.js";
9
9
  export * from "./components/index.js";
10
10
  export * from "./client/index.js";
11
+ export * from "./stores/index.js";
11
12
  export type * from "./types.js";
12
13
  export type InfiniteQueryResult<TData> = {
13
14
  pages: TData[];
package/dist/index.js CHANGED
@@ -8,3 +8,4 @@ export * from "./bcs.js";
8
8
  export * from "./_generated/index.js";
9
9
  export * from "./components/index.js";
10
10
  export * from "./client/index.js";
11
+ export * from "./stores/index.js";
@@ -0,0 +1,11 @@
1
+ export interface OAuthState {
2
+ ephemeralSecretKey: string;
3
+ maxEpoch: number;
4
+ randomness: string;
5
+ authProvider: string;
6
+ timestamp: number;
7
+ }
8
+ export declare function isIOSPWA(): boolean;
9
+ export declare function saveOAuthState(state: OAuthState): void;
10
+ export declare function getOAuthState(): OAuthState | null;
11
+ export declare function clearOAuthState(): void;
@@ -0,0 +1,55 @@
1
+ // Storage keys for OAuth state
2
+ const OAUTH_STATE_KEY = "zing:oauth:state";
3
+ // Helper to detect iOS (Safari or PWA) where popups are unreliable
4
+ export function isIOSPWA() {
5
+ // Check if it's iOS device
6
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
7
+ if (!isIOS)
8
+ return false;
9
+ // In iOS, we should use redirect for:
10
+ // 1. PWA/Standalone mode (home screen apps)
11
+ // 2. Regular Safari (popups are blocked by default)
12
+ const isStandalone = window.navigator.standalone === true;
13
+ const isSafari = /Safari/.test(navigator.userAgent) &&
14
+ !/CriOS|FxiOS|EdgiOS/.test(navigator.userAgent);
15
+ // Use redirect-based flow for iOS Safari or standalone mode
16
+ return isStandalone || isSafari;
17
+ }
18
+ export function saveOAuthState(state) {
19
+ try {
20
+ localStorage.setItem(OAUTH_STATE_KEY, JSON.stringify(state));
21
+ }
22
+ catch (error) {
23
+ console.error("Failed to save OAuth state:", error);
24
+ }
25
+ }
26
+ export function getOAuthState() {
27
+ try {
28
+ const data = localStorage.getItem(OAUTH_STATE_KEY);
29
+ if (!data) {
30
+ console.error("No OAuth state found in localStorage");
31
+ return null;
32
+ }
33
+ const state = JSON.parse(data);
34
+ // Check if state is not too old (5 minutes max)
35
+ const now = Date.now();
36
+ if (now - state.timestamp > 5 * 60 * 1000) {
37
+ console.error("OAuth state expired");
38
+ clearOAuthState();
39
+ return null;
40
+ }
41
+ return state;
42
+ }
43
+ catch (error) {
44
+ console.error("Failed to get OAuth state:", error);
45
+ return null;
46
+ }
47
+ }
48
+ export function clearOAuthState() {
49
+ try {
50
+ localStorage.removeItem(OAUTH_STATE_KEY);
51
+ }
52
+ catch (error) {
53
+ console.error("Failed to clear OAuth state:", error);
54
+ }
55
+ }
@@ -5,3 +5,4 @@ export declare const formatBalance: (balance: string | number | bigint, decimal:
5
5
  export declare const formatBytes: (bytes: number) => string;
6
6
  export declare const getDaysRemaining: (comp: number) => number;
7
7
  export declare const bytesToGB: (bytes: number) => number;
8
+ export declare function isIOSPWA(): boolean;
@@ -23,3 +23,12 @@ export const getDaysRemaining = (comp) => {
23
23
  return diffDays;
24
24
  };
25
25
  export const bytesToGB = (bytes) => bytes / (1024 * 1024 * 1024);
26
+ export function isIOSPWA() {
27
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
28
+ if (!isIOS)
29
+ return false;
30
+ const isStandalone = window.navigator.standalone === true;
31
+ const isSafari = /Safari/.test(navigator.userAgent) &&
32
+ !/CriOS|FxiOS|EdgiOS/.test(navigator.userAgent);
33
+ return isStandalone || isSafari;
34
+ }
@@ -1,4 +1,4 @@
1
- import type { EncodingType } from "@mysten/walrus";
1
+ type EncodingType = "RS2" | "RedStuff";
2
2
  export interface QuiltSizeInput {
3
3
  blobs: {
4
4
  size: number;
@@ -59,3 +59,4 @@ export declare function calculateEncryptedQuiltSize(files: Array<{
59
59
  identifier: string;
60
60
  tags?: Record<string, string>;
61
61
  }>, numShards: number, ivSize?: number, encodingType?: EncodingType): QuiltSizeResult;
62
+ export {};
@@ -1,8 +1,9 @@
1
1
  import type { ZkLoginProofParams, ZkLoginProofResponse, ZKLoginSignerState } from "../types.js";
2
- import type { SuiClient } from "@mysten/sui/client";
2
+ import type { SuiGrpcClient } from "@mysten/sui/grpc";
3
+ import type { TransactionEffects } from "@mysten/sui/jsonRpc";
3
4
  import type { Transaction } from "@mysten/sui/transactions";
4
- export declare function getSigner(suiClient: SuiClient): Promise<ZKLoginSignerState>;
5
- export declare function signAndExecuteGasPoolTransaction(saltServerUrl: string, signer: ZKLoginSignerState, suiClient: SuiClient, tx: Transaction, gasBudget?: number, reserveDurationSecs?: number): Promise<any>;
5
+ export declare function getSigner(suiClient: SuiGrpcClient): Promise<ZKLoginSignerState>;
6
+ export declare function signAndExecuteGasPoolTransaction(saltServerUrl: string, signer: ZKLoginSignerState, suiClient: SuiGrpcClient, tx: Transaction, gasBudget?: number, reserveDurationSecs?: number): Promise<TransactionEffects | undefined>;
6
7
  export declare function signPersonalMessage(saltServerUrl: string, signer: ZKLoginSignerState, message: Uint8Array): Promise<{
7
8
  zkLoginSignature: any;
8
9
  bytes: Uint8Array<ArrayBuffer>;
@@ -4,7 +4,7 @@ import { fromBase64 } from "@mysten/sui/utils";
4
4
  import { decodeJwt } from "@mysten/sui/zklogin";
5
5
  export async function getSigner(suiClient) {
6
6
  const zkLoginStorage = await zkloginStorage.getState();
7
- const { epoch: currentEpoch } = await suiClient.getLatestSuiSystemState();
7
+ const { systemState: { epoch: currentEpoch }, } = await suiClient.core.getCurrentSystemState();
8
8
  if (!zkLoginStorage?.jwt ||
9
9
  !zkLoginStorage?.maxEpoch ||
10
10
  !zkLoginStorage.ephemeralSecretKey ||
@@ -4,7 +4,6 @@ import type { WalrusUploadFlowStage } from "../config/common.js";
4
4
  import type { SharedObjectRef, WalrusSystemState } from "../config/types.js";
5
5
  import type { ZKLoginSignerState } from "../types.js";
6
6
  import type { SuiGrpcClient } from "@mysten/sui/grpc";
7
- import type { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
8
7
  import type { CertifyBlobOptions, WalrusClient, WalrusFile, WriteFilesFlowOptions, WriteFilesFlowRegisterOptions, WriteFilesFlowUploadOptions } from "@mysten/walrus";
9
8
  type ZingWriteFlowConfig = {
10
9
  zingStudioPackageId: string;
@@ -28,7 +27,7 @@ export declare function buildCertifyArticleBlobTransaction(config: {
28
27
  zingStudioConfigSharedObjectRef: SharedObjectRef;
29
28
  walrusSystemSharedObjectRef: SharedObjectRef;
30
29
  }, walrusClient: WalrusClient, owner: string, articleId: string, { blobId, blobObjectId, confirmations, certificate, deletable, }: CertifyBlobOptions): (tx: Transaction) => Promise<void>;
31
- export declare const zingWriteFlow: (config: ZingWriteFlowConfig, suiGrpcClient: SuiGrpcClient, suiJsonRpcClient: SuiJsonRpcClient, walrusClient: WalrusClient, walrusSystem: WalrusSystemState, walTreasury: string, storageByEpoch: Record<number, number>, fileKey: CryptoKey, studioObjectId: string, owner: string, subscriptionLevel: null | number, articleMetadata: {
30
+ export declare const zingWriteFlow: (config: ZingWriteFlowConfig, suiGrpcClient: SuiGrpcClient, walrusClient: WalrusClient, walrusSystem: WalrusSystemState, walTreasury: string, storageByEpoch: Record<number, number>, fileKey: CryptoKey, studioObjectId: string, owner: string, subscriptionLevel: null | number, articleMetadata: {
32
31
  identifier: string;
33
32
  tags: {
34
33
  "content-type": string;
@@ -64,7 +63,7 @@ export declare const zingWriteFlow: (config: ZingWriteFlowConfig, suiGrpcClient:
64
63
  blobObjectId: string;
65
64
  }[]>;
66
65
  };
67
- export declare function uploadFileToWalrus(zingWriteFlowConfig: ZingWriteFlowConfig, suiGrpcClient: SuiGrpcClient, suiJsonRpcClient: SuiJsonRpcClient, walrusClient: WalrusClient, walrusSystem: WalrusSystemState, walTreasury: string, storageByEpoch: Record<number, number>, fileKey: CryptoKey, walrusFiles: WalrusFile[], subscriptionLevel: null | number, metadata: {
66
+ export declare function uploadFileToWalrus(zingWriteFlowConfig: ZingWriteFlowConfig, suiGrpcClient: SuiGrpcClient, walrusClient: WalrusClient, walrusSystem: WalrusSystemState, walTreasury: string, storageByEpoch: Record<number, number>, fileKey: CryptoKey, walrusFiles: WalrusFile[], subscriptionLevel: null | number, metadata: {
68
67
  identifier: string;
69
68
  tags: {
70
69
  "content-type": string;
@@ -131,7 +131,7 @@ export function buildCertifyArticleBlobTransaction(config, walrusClient, owner,
131
131
  }));
132
132
  };
133
133
  }
134
- export const zingWriteFlow = (config, suiGrpcClient, suiJsonRpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, studioObjectId, owner, subscriptionLevel, articleMetadata, options, withUploadRelayClient, blobRegisteredEventType, publishArticleEventType) => {
134
+ export const zingWriteFlow = (config, suiGrpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, studioObjectId, owner, subscriptionLevel, articleMetadata, options, withUploadRelayClient, blobRegisteredEventType, publishArticleEventType) => {
135
135
  const { files } = options;
136
136
  const encode = async () => {
137
137
  const { quilt, index } = await walrusClient.encodeQuilt({
@@ -180,7 +180,7 @@ export const zingWriteFlow = (config, suiGrpcClient, suiJsonRpcClient, walrusCli
180
180
  };
181
181
  };
182
182
  const upload = async ({ index, data, metadata, deletable }, { digest }) => {
183
- const { parsedPublishArticleEvent, blobObjectId } = await getPublishedArticleAndBlobId(suiGrpcClient, suiJsonRpcClient, walrusClient, digest, blobRegisteredEventType, publishArticleEventType);
183
+ const { parsedPublishArticleEvent, blobObjectId } = await getPublishedArticleAndBlobId(suiGrpcClient, walrusClient, digest, blobRegisteredEventType, publishArticleEventType);
184
184
  const articleId = parsedPublishArticleEvent.article_id;
185
185
  if (withUploadRelayClient) {
186
186
  const meta = metadata;
@@ -295,7 +295,7 @@ export const zingWriteFlow = (config, suiGrpcClient, suiJsonRpcClient, walrusCli
295
295
  listFiles: async () => listFiles(getResults("certify", "listFiles")),
296
296
  };
297
297
  };
298
- export async function uploadFileToWalrus(zingWriteFlowConfig, suiGrpcClient, suiJsonRpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, walrusFiles, subscriptionLevel, metadata, saltServerUrl, signer, onProgress) {
298
+ export async function uploadFileToWalrus(zingWriteFlowConfig, suiGrpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, walrusFiles, subscriptionLevel, metadata, saltServerUrl, signer, onProgress) {
299
299
  const report = (stage) => {
300
300
  if (onProgress)
301
301
  onProgress(stage);
@@ -304,7 +304,7 @@ export async function uploadFileToWalrus(zingWriteFlowConfig, suiGrpcClient, sui
304
304
  if (!owner)
305
305
  throw new Error("no signer");
306
306
  // Step 1: Create and encode the flow (can be done immediately when file is selected)
307
- const flow = zingWriteFlow(zingWriteFlowConfig, suiGrpcClient, suiJsonRpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, getDerivedStudioID(zingWriteFlowConfig.zingStudioConfigSharedObjectRef.objectId, owner), owner, subscriptionLevel, metadata, {
307
+ const flow = zingWriteFlow(zingWriteFlowConfig, suiGrpcClient, walrusClient, walrusSystem, walTreasury, storageByEpoch, fileKey, getDerivedStudioID(zingWriteFlowConfig.zingStudioConfigSharedObjectRef.objectId, owner), owner, subscriptionLevel, metadata, {
308
308
  files: walrusFiles,
309
309
  }, true, zingWriteFlowConfig.blobRegisteredEventType, zingWriteFlowConfig.publishArticleEventType);
310
310
  report("encode");
@@ -319,17 +319,19 @@ export async function uploadFileToWalrus(zingWriteFlowConfig, suiGrpcClient, sui
319
319
  owner,
320
320
  deletable: true,
321
321
  });
322
- const registerTxEffects = await signAndExecuteGasPoolTransaction(saltServerUrl, signer, suiJsonRpcClient, registerTx);
322
+ const registerTxEffects = await signAndExecuteGasPoolTransaction(saltServerUrl, signer, suiGrpcClient, registerTx);
323
323
  if (!registerTxEffects?.transactionDigest)
324
324
  throw new Error("fail to execute register Blob transaction");
325
- const finalizedTransaction = await suiJsonRpcClient.waitForTransaction({
325
+ const finalizedTransaction = await suiGrpcClient.waitForTransaction({
326
326
  digest: registerTxEffects.transactionDigest,
327
327
  });
328
+ if (!finalizedTransaction?.Transaction?.digest)
329
+ throw new Error("Fail to get finalizedTransaction digest when waiting");
328
330
  // Step 3: Upload the data to storage nodes
329
331
  // This can be done immediately after the register step, or as a separate step the user initiates
330
332
  report("upload");
331
333
  return await flow.upload({
332
- digest: finalizedTransaction.digest,
334
+ digest: finalizedTransaction.Transaction?.digest,
333
335
  });
334
336
  }
335
337
  const parsedPublishArticleEvent = await handleRegister();
@@ -337,10 +339,10 @@ export async function uploadFileToWalrus(zingWriteFlowConfig, suiGrpcClient, sui
337
339
  async function handleCertify() {
338
340
  report("certify_blob");
339
341
  const certifyTx = flow.certify();
340
- const certifyTxEffects = await signAndExecuteGasPoolTransaction(saltServerUrl, signer, suiJsonRpcClient, certifyTx);
342
+ const certifyTxEffects = await signAndExecuteGasPoolTransaction(saltServerUrl, signer, suiGrpcClient, certifyTx);
341
343
  if (!certifyTxEffects?.transactionDigest)
342
344
  throw new Error("fail to execute certify Blob transaction");
343
- await suiJsonRpcClient.waitForTransaction({
345
+ await suiGrpcClient.waitForTransaction({
344
346
  digest: certifyTxEffects.transactionDigest,
345
347
  });
346
348
  report("publish");
@@ -2,7 +2,7 @@ import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
2
2
  import { decodeJwt } from "@mysten/sui/zklogin";
3
3
  import type { AuthProvider } from "../config/common.js";
4
4
  import type { PartialZkLoginSignature, ZKLoginSignerState } from "../types.js";
5
- import type { SuiClient } from "@mysten/sui/client";
5
+ import type { SuiGrpcClient } from "@mysten/sui/grpc";
6
6
  import type { StoreApi } from "zustand";
7
7
  export interface WalletAccount {
8
8
  jwt: ReturnType<typeof decodeJwt> & {
@@ -15,7 +15,7 @@ export interface WalletAccount {
15
15
  };
16
16
  }
17
17
  export interface WalletState {
18
- suiClient: SuiClient;
18
+ suiClient: SuiGrpcClient;
19
19
  isConnected: boolean;
20
20
  isLoading: boolean;
21
21
  account: WalletAccount | null;
@@ -41,7 +41,7 @@ export type WalletActions = {
41
41
  };
42
42
  export type WalletStore = WalletState & WalletActions;
43
43
  export type WalletStoreConfig = {
44
- suiClient: SuiClient;
44
+ suiClient: SuiGrpcClient;
45
45
  oAuthClientId: string;
46
46
  saltServerUrl: string;
47
47
  network?: string;
@@ -1,4 +1,5 @@
1
1
  import { zkloginStorage } from "./zkloginStore.js";
2
+ import { isIOSPWA } from "../lib/utils/helpers.js";
2
3
  import { createZkLoginProof } from "../mutations/signer.js";
3
4
  import { decodeSuiPrivateKey } from "@mysten/sui/cryptography";
4
5
  import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
@@ -36,9 +37,9 @@ export function createWalletStore(config) {
36
37
  async login(provider) {
37
38
  try {
38
39
  set({ isLoading: true, error: null, authProvider: provider });
39
- // 1?? Generate ephemeral keypair and maxEpoch
40
+ // Generate ephemeral keypair and maxEpoch
40
41
  const ephemeralKeyPair = new Ed25519Keypair();
41
- const { epoch } = await suiClient.getLatestSuiSystemState();
42
+ const { systemState: { epoch }, } = await suiClient.core.getCurrentSystemState();
42
43
  const maxEpoch = Number(epoch) + 10;
43
44
  const randomness = generateRandomness();
44
45
  const nonce = generateNonce(ephemeralKeyPair.getPublicKey(), maxEpoch, randomness);
@@ -51,96 +52,123 @@ export function createWalletStore(config) {
51
52
  nonce,
52
53
  });
53
54
  const loginURL = `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
54
- const idToken = await new Promise((resolve, reject) => {
55
- const width = 500;
56
- const height = 600;
57
- const left = window.screenX + (window.innerWidth - width) / 2;
58
- const top = window.screenY + (window.innerHeight - height) / 2;
59
- const popup = window.open(loginURL, "oauth2-login", `width=${width},height=${height},top=${top},left=${left}`);
60
- if (!popup)
61
- return reject(new Error("Failed to open popup"));
62
- let resolved = false;
63
- // Listen for postMessage from the callback page
64
- const messageHandler = (event) => {
65
- // Security: verify origin
66
- if (event.origin !== window.location.origin)
67
- return;
68
- if (event.data?.type !== "oauth-callback")
69
- return;
70
- if (resolved)
71
- return;
72
- resolved = true;
73
- window.removeEventListener("message", messageHandler);
74
- clearInterval(checkClosed);
75
- if (event.data.error) {
76
- return reject(new Error(event.data.error));
77
- }
78
- if (event.data.idToken) {
79
- resolve(event.data.idToken);
80
- }
81
- else {
82
- reject(new Error("No ID token received"));
55
+ // Save OAuth state for BOTH popup and redirect flows
56
+ const ephemeralSecretKey = toBase64(decodeSuiPrivateKey(ephemeralKeyPair.getSecretKey()).secretKey);
57
+ localStorage.setItem("zing:oauth:state", JSON.stringify({
58
+ ephemeralSecretKey,
59
+ maxEpoch,
60
+ randomness,
61
+ authProvider: provider,
62
+ timestamp: Date.now(),
63
+ }));
64
+ // Check if iOS (Safari or PWA) - use redirect flow
65
+ const shouldUseRedirect = isIOSPWA();
66
+ if (shouldUseRedirect) {
67
+ // Redirect to OAuth provider
68
+ window.location.href = loginURL;
69
+ return;
70
+ }
71
+ // Desktop/regular browsers: use popup flow
72
+ try {
73
+ const idToken = await new Promise((resolve, reject) => {
74
+ const width = 500;
75
+ const height = 600;
76
+ const left = window.screenX + (window.innerWidth - width) / 2;
77
+ const top = window.screenY + (window.innerHeight - height) / 2;
78
+ const popup = window.open(loginURL, "oauth2-login", `width=${width},height=${height},top=${top},left=${left}`);
79
+ // If popup was blocked, fall back to redirect
80
+ if (!popup) {
81
+ console.warn("Popup blocked, falling back to redirect flow");
82
+ window.location.href = loginURL;
83
+ return; // Don't reject, just redirect
83
84
  }
84
- };
85
- window.addEventListener("message", messageHandler);
86
- // Check if popup was closed without completing auth
87
- const checkClosed = setInterval(() => {
88
- if (!popup || popup.closed) {
85
+ let resolved = false;
86
+ // Listen for postMessage from the callback page
87
+ const messageHandler = (event) => {
88
+ // Security: verify origin
89
+ if (event.origin !== window.location.origin)
90
+ return;
91
+ if (event.data?.type !== "oauth-callback")
92
+ return;
93
+ if (resolved)
94
+ return;
95
+ resolved = true;
96
+ window.removeEventListener("message", messageHandler);
97
+ clearInterval(checkClosed);
98
+ if (event.data.error) {
99
+ return reject(new Error(event.data.error));
100
+ }
101
+ if (event.data.idToken) {
102
+ resolve(event.data.idToken);
103
+ }
104
+ else {
105
+ reject(new Error("No ID token received"));
106
+ }
107
+ };
108
+ window.addEventListener("message", messageHandler);
109
+ // Check if popup was closed without completing auth
110
+ const checkClosed = setInterval(() => {
111
+ if (!popup || popup.closed) {
112
+ if (!resolved) {
113
+ resolved = true;
114
+ clearInterval(checkClosed);
115
+ window.removeEventListener("message", messageHandler);
116
+ reject(new Error("Login popup closed before completing authentication"));
117
+ }
118
+ }
119
+ }, 1000);
120
+ // Timeout after 5 minutes
121
+ setTimeout(() => {
89
122
  if (!resolved) {
90
123
  resolved = true;
91
124
  clearInterval(checkClosed);
92
125
  window.removeEventListener("message", messageHandler);
93
- reject(new Error("Login popup closed before completing authentication"));
126
+ if (popup && !popup.closed)
127
+ popup.close();
128
+ reject(new Error("Login timeout"));
94
129
  }
95
- }
96
- }, 1000);
97
- // Timeout after 5 minutes
98
- setTimeout(() => {
99
- if (!resolved) {
100
- resolved = true;
101
- clearInterval(checkClosed);
102
- window.removeEventListener("message", messageHandler);
103
- if (popup && !popup.closed)
104
- popup.close();
105
- reject(new Error("Login timeout"));
106
- }
107
- }, 5 * 60 * 1000);
108
- });
109
- // 4?? Decode JWT
110
- const decoded = decodeJwt(idToken);
111
- // 5?? Persist ephemeral secret / salt / jwt / maxEpoch
112
- zkloginStorage
113
- .getState()
114
- .setEphemeralSecretKey(toBase64(decodeSuiPrivateKey(ephemeralKeyPair.getSecretKey()).secretKey));
115
- zkloginStorage.getState().setJWT(idToken);
116
- zkloginStorage.getState().setMaxEpoch(maxEpoch);
117
- const extendedEphemeralPublicKey = getExtendedEphemeralPublicKey(ephemeralKeyPair.getPublicKey());
118
- const zkProofResponse = await createZkLoginProof(config.saltServerUrl, {
119
- jwtTokenString: idToken,
120
- maxEpoch: String(maxEpoch),
121
- extendedEphemeralPublicKey,
122
- jwtRandomness: randomness,
123
- });
124
- if (!zkProofResponse || !zkProofResponse.zkProof) {
125
- throw new Error("Invalid response from proof server: Missing zkProof");
130
+ }, 5 * 60 * 1000);
131
+ });
132
+ // Popup flow completed - process the token
133
+ const decoded = decodeJwt(idToken);
134
+ // Persist ephemeral secret
135
+ zkloginStorage.getState().setEphemeralSecretKey(ephemeralSecretKey);
136
+ zkloginStorage.getState().setJWT(idToken);
137
+ zkloginStorage.getState().setMaxEpoch(maxEpoch);
138
+ const extendedEphemeralPublicKey = getExtendedEphemeralPublicKey(ephemeralKeyPair.getPublicKey());
139
+ const zkProofResponse = await createZkLoginProof(config.saltServerUrl, {
140
+ jwtTokenString: idToken,
141
+ maxEpoch: String(maxEpoch),
142
+ extendedEphemeralPublicKey,
143
+ jwtRandomness: randomness,
144
+ });
145
+ if (!zkProofResponse || !zkProofResponse.zkProof) {
146
+ throw new Error("Invalid response from proof server: Missing zkProof");
147
+ }
148
+ const { zkProof, suiAddress } = zkProofResponse;
149
+ zkloginStorage.getState().setZKProof(JSON.stringify(zkProof));
150
+ zkloginStorage.getState().setSuiAddress(suiAddress);
151
+ // Clear OAuth state
152
+ localStorage.removeItem("zing:oauth:state");
153
+ const account = { jwt: decoded };
154
+ set({
155
+ jwtTokenString: idToken,
156
+ decodedJwt: decoded,
157
+ ephemeralKeyPair,
158
+ suiAddress,
159
+ zkProof,
160
+ maxEpoch,
161
+ account,
162
+ isConnected: true,
163
+ isLoading: false,
164
+ error: null,
165
+ });
166
+ }
167
+ catch (popupError) {
168
+ // Clean up OAuth state on popup error
169
+ localStorage.removeItem("zing:oauth:state");
170
+ throw popupError;
126
171
  }
127
- // 2. Access keys directly from the response (no .result nesting)
128
- const { zkProof, suiAddress } = zkProofResponse;
129
- zkloginStorage.getState().setZKProof(JSON.stringify(zkProof));
130
- zkloginStorage.getState().setSuiAddress(suiAddress);
131
- const account = { jwt: decoded };
132
- set({
133
- jwtTokenString: idToken,
134
- decodedJwt: decoded,
135
- ephemeralKeyPair,
136
- suiAddress,
137
- zkProof,
138
- maxEpoch,
139
- account,
140
- isConnected: true,
141
- isLoading: false,
142
- error: null,
143
- });
144
172
  }
145
173
  catch (err) {
146
174
  set({ error: err?.message ?? String(err), isLoading: false });
@@ -185,7 +213,7 @@ export function createWalletStore(config) {
185
213
  async initFromStorage() {
186
214
  try {
187
215
  set({ isLoading: true });
188
- const { epoch: currentEpoch } = await suiClient.getLatestSuiSystemState();
216
+ const { systemState: { epoch: currentEpoch }, } = await suiClient.core.getCurrentSystemState();
189
217
  const stored = {
190
218
  jwt: zkloginStorage.getState().jwt,
191
219
  maxEpoch: zkloginStorage.getState().maxEpoch,
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { PlatformType } from "./config/common.js";
2
- import type { SuiObjectRef, TransactionEffects } from "@mysten/sui/client";
2
+ import type { SuiObjectRef, TransactionEffects } from "@mysten/sui/jsonRpc";
3
3
  import type { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
4
4
  import type { decodeJwt, getZkLoginSignature } from "@mysten/sui/zklogin";
5
5
  export type SuiNetwork = "mainnet" | "testnet";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@zing-protocol/zing-sdk",
3
3
  "sideEffects": false,
4
4
  "type": "module",
5
- "version": "0.0.14",
5
+ "version": "0.0.16",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
@@ -16,9 +16,9 @@
16
16
  "type-check": "tsc --noEmit"
17
17
  },
18
18
  "dependencies": {
19
- "@mysten/seal": "^0.9.3",
20
- "@mysten/sui": "^1.45.0",
21
- "@mysten/walrus": "^0.9.0",
19
+ "@mysten/seal": "^1.0.1",
20
+ "@mysten/sui": "^2.4.0",
21
+ "@mysten/walrus": "^1.0.3",
22
22
  "@tanstack/react-query": "5.90.5",
23
23
  "@reclaimprotocol/js-sdk": "^4.5.1",
24
24
  "js-sha3": "^0.9.3",