@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 +0 -14
- package/dist/bcs.js +1 -65
- package/dist/client/index.d.ts +3 -6
- package/dist/client/index.js +28 -20
- package/dist/components/walrus-provider.js +1 -1
- package/dist/components/zing-provider.d.ts +0 -2
- package/dist/components/zing-provider.js +2 -3
- package/dist/config/testnet.js +1 -1
- package/dist/getters.d.ts +1 -2
- package/dist/getters.js +53 -29
- package/dist/hooks/useReclaim.d.ts +3 -3
- package/dist/hooks/useReclaim.js +15 -8
- package/dist/hooks/useSignAndExecuteTransaction.d.ts +1 -1
- package/dist/hooks/useSignAndExecuteTransaction.js +6 -3
- package/dist/hooks/useZingMutation.d.ts +1 -1
- package/dist/hooks/useZingMutation.js +1 -1
- package/dist/hooks/useZingQueries.d.ts +1 -1
- package/dist/hooks/useZingQuery.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/oauth-pwa.d.ts +11 -0
- package/dist/lib/oauth-pwa.js +55 -0
- package/dist/lib/utils/helpers.d.ts +1 -0
- package/dist/lib/utils/helpers.js +9 -0
- package/dist/lib/utils/quilt.d.ts +2 -1
- package/dist/mutations/signer.d.ts +4 -3
- package/dist/mutations/signer.js +1 -1
- package/dist/mutations/walrus.d.ts +2 -3
- package/dist/mutations/walrus.js +11 -9
- package/dist/stores/walletStore.d.ts +3 -3
- package/dist/stores/walletStore.js +114 -86
- package/dist/types.d.ts +1 -1
- package/package.json +4 -4
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
|
|
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
|
-
});
|
package/dist/client/index.d.ts
CHANGED
|
@@ -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
|
|
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/
|
|
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;
|
package/dist/client/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
!
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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.
|
|
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,
|
|
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,
|
|
7
|
+
export const ZingClientProvider = ({ network, suiGrpcClient, children, }) => {
|
|
8
8
|
const client = useMemo(() => new ZingClient({
|
|
9
9
|
network,
|
|
10
10
|
suiGrpcClient,
|
|
11
|
-
|
|
12
|
-
}), [network, suiGrpcClient, suiJsonRpcClient]);
|
|
11
|
+
}), [network, suiGrpcClient]);
|
|
13
12
|
return (_jsx(ZingClientContext.Provider, { value: { client }, children: children }));
|
|
14
13
|
};
|
|
15
14
|
export const useZingClient = () => {
|
package/dist/config/testnet.js
CHANGED
|
@@ -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: "
|
|
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,
|
|
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
|
|
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 =
|
|
52
|
-
|
|
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 =
|
|
67
|
-
|
|
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 =
|
|
82
|
-
|
|
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 =
|
|
97
|
-
|
|
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 =
|
|
116
|
-
|
|
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 =
|
|
134
|
-
|
|
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 =
|
|
148
|
-
|
|
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 =
|
|
177
|
+
const suiMoveObject = bcs.Object.parse(df.fieldObject.bcs.value);
|
|
164
178
|
// Wrapped in dynamicFields
|
|
165
|
-
|
|
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 =
|
|
191
|
-
|
|
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 =
|
|
205
|
-
|
|
206
|
-
|
|
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.
|
|
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 =
|
|
252
|
-
|
|
253
|
-
|
|
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) =>
|
|
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,
|
|
285
|
+
export async function getPublishedArticleAndBlobId(suiGrpcClient, walrusClient, digest, blobRegisteredEventType, publishArticleEventType) {
|
|
262
286
|
// suiGrpcClient waitForTransaction calling core.getTransaction which is broken
|
|
263
|
-
await
|
|
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 {
|
|
3
|
+
import type { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
4
4
|
interface CommitProofParams {
|
|
5
|
-
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<
|
|
10
|
+
export declare function useCommitProof(): import("@tanstack/react-query").UseMutationResult<import("@mysten/sui/jsonRpc").TransactionEffects | null, Error, CommitProofParams, unknown>;
|
|
11
11
|
export {};
|
package/dist/hooks/useReclaim.js
CHANGED
|
@@ -32,20 +32,27 @@ export function useCommitProof() {
|
|
|
32
32
|
});
|
|
33
33
|
if (!commitTransactionResponse)
|
|
34
34
|
throw new Error("fail to commit proof");
|
|
35
|
-
const
|
|
35
|
+
const settledCommitTransactionResult = await suiClient.waitForTransaction({
|
|
36
36
|
digest: commitTransactionResponse.transactionDigest,
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
include: {
|
|
38
|
+
effects: true,
|
|
39
|
+
objectTypes: true,
|
|
39
40
|
},
|
|
40
|
-
})
|
|
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((
|
|
44
|
-
|
|
45
|
-
|
|
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 [
|
|
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<
|
|
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.
|
|
22
|
-
|
|
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.
|
|
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/
|
|
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.
|
|
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/
|
|
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/
|
|
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
|
@@ -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
|
-
|
|
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 {
|
|
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:
|
|
5
|
-
export declare function signAndExecuteGasPoolTransaction(saltServerUrl: string, signer: ZKLoginSignerState, suiClient:
|
|
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>;
|
package/dist/mutations/signer.js
CHANGED
|
@@ -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.
|
|
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,
|
|
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,
|
|
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;
|
package/dist/mutations/walrus.js
CHANGED
|
@@ -131,7 +131,7 @@ export function buildCertifyArticleBlobTransaction(config, walrusClient, owner,
|
|
|
131
131
|
}));
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
|
-
export const zingWriteFlow = (config, suiGrpcClient,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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 {
|
|
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:
|
|
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:
|
|
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
|
-
//
|
|
40
|
+
// Generate ephemeral keypair and maxEpoch
|
|
40
41
|
const ephemeralKeyPair = new Ed25519Keypair();
|
|
41
|
-
const { epoch } = await suiClient.
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
126
|
+
if (popup && !popup.closed)
|
|
127
|
+
popup.close();
|
|
128
|
+
reject(new Error("Login timeout"));
|
|
94
129
|
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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.
|
|
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/
|
|
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.
|
|
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.
|
|
20
|
-
"@mysten/sui": "^
|
|
21
|
-
"@mysten/walrus": "^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",
|