@mysten/sui 2.18.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/bcs/bcs.d.mts +6 -6
- package/dist/cryptography/signature.d.mts +6 -6
- package/dist/grpc/proto/sui/rpc/v2/ledger_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/move_package_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/name_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.mts +4 -4
- package/dist/transactions/Transaction.d.mts +6 -6
- package/dist/transactions/Transaction.d.mts.map +1 -1
- package/dist/verify/index.d.mts +2 -2
- package/dist/verify/index.mjs +2 -2
- package/dist/verify/verify.d.mts +21 -1
- package/dist/verify/verify.d.mts.map +1 -1
- package/dist/verify/verify.mjs +49 -14
- package/dist/verify/verify.mjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/dist/zklogin/bcs.d.mts +14 -14
- package/dist/zklogin/bcs.d.mts.map +1 -1
- package/dist/zklogin/index.d.mts +2 -1
- package/dist/zklogin/index.mjs +2 -1
- package/dist/zklogin/publickey.d.mts +4 -0
- package/dist/zklogin/publickey.d.mts.map +1 -1
- package/dist/zklogin/publickey.mjs +6 -0
- package/dist/zklogin/publickey.mjs.map +1 -1
- package/dist/zklogin/signer.d.mts +55 -0
- package/dist/zklogin/signer.d.mts.map +1 -0
- package/dist/zklogin/signer.mjs +68 -0
- package/dist/zklogin/signer.mjs.map +1 -0
- package/docs/migrations/sui-2.0/dapp-kit.md +5 -1
- package/package.json +3 -3
- package/src/verify/index.ts +3 -0
- package/src/verify/verify.ts +68 -34
- package/src/version.ts +1 -1
- package/src/zklogin/index.ts +2 -0
- package/src/zklogin/publickey.ts +7 -0
- package/src/zklogin/signer.ts +121 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @mysten/sui.js
|
|
2
2
|
|
|
3
|
+
## 2.20.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7452835: Add `ZkLoginSigner`, a transport- and provider-agnostic zkLogin signer. It wraps any
|
|
8
|
+
ephemeral `Signer` and transforms its signatures into zkLogin signatures using the supplied proof
|
|
9
|
+
`inputs` and `maxEpoch`:
|
|
10
|
+
`new ZkLoginSigner({ ephemeralSigner, maxEpoch, inputs, legacyAddress })`. The address is derived
|
|
11
|
+
from the proof; `legacyAddress` is a required boolean (consistent with `jwtToAddress`,
|
|
12
|
+
`toZkLoginPublicIdentifier`, and the other zkLogin address APIs). Optionally pass `address` to
|
|
13
|
+
validate the derived address (throws on mismatch) and `client` to make the derived public key able
|
|
14
|
+
to verify signatures. Like other composite signers (e.g. `MultiSigSigner`), calling `sign()`
|
|
15
|
+
directly throws — use `signTransaction` / `signPersonalMessage`.
|
|
16
|
+
|
|
17
|
+
Also adds a read-only `legacyAddress` getter to `ZkLoginPublicIdentifier`.
|
|
18
|
+
|
|
19
|
+
## 2.19.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- 2be98ce: Add `isValidSignature`, `isValidPersonalMessageSignature`, and
|
|
24
|
+
`isValidTransactionSignature` to `@mysten/sui/verify` — boolean-returning siblings of the existing
|
|
25
|
+
`verify*` functions, taking the same arguments. They return `false` for a malformed or invalid
|
|
26
|
+
signature (or one that doesn't match a supplied `address`) instead of throwing, while still
|
|
27
|
+
letting a genuine environmental failure during verification (e.g. a zkLogin JWK/epoch lookup)
|
|
28
|
+
propagate. The `verify*` functions now delegate to these.
|
|
29
|
+
|
|
3
30
|
## 2.18.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/dist/bcs/bcs.d.mts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { TypeTag as TypeTag$1 } from "./types.mjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _mysten_bcs810 from "@mysten/bcs";
|
|
3
3
|
import { BcsType } from "@mysten/bcs";
|
|
4
4
|
|
|
5
5
|
//#region src/bcs/bcs.d.ts
|
|
6
6
|
declare const TypeTag: BcsType<string, string | TypeTag$1, string>;
|
|
7
|
-
declare function IntentMessage<T extends BcsType<any>>(T: T):
|
|
8
|
-
intent:
|
|
9
|
-
scope:
|
|
7
|
+
declare function IntentMessage<T extends BcsType<any>>(T: T): _mysten_bcs810.BcsStruct<{
|
|
8
|
+
intent: _mysten_bcs810.BcsStruct<{
|
|
9
|
+
scope: _mysten_bcs810.BcsEnum<{
|
|
10
10
|
TransactionData: null;
|
|
11
11
|
TransactionEffects: null;
|
|
12
12
|
CheckpointSummary: null;
|
|
13
13
|
PersonalMessage: null;
|
|
14
14
|
}, "IntentScope">;
|
|
15
|
-
version:
|
|
15
|
+
version: _mysten_bcs810.BcsEnum<{
|
|
16
16
|
V0: null;
|
|
17
17
|
}, "IntentVersion">;
|
|
18
|
-
appId:
|
|
18
|
+
appId: _mysten_bcs810.BcsEnum<{
|
|
19
19
|
Sui: null;
|
|
20
20
|
}, "AppId">;
|
|
21
21
|
}, string>;
|
|
@@ -23,12 +23,6 @@ declare function toSerializedSignature({
|
|
|
23
23
|
* Decodes a serialized signature into its constituent components: the signature scheme, the actual signature, and the public key
|
|
24
24
|
*/
|
|
25
25
|
declare function parseSerializedSignature(serializedSignature: string): {
|
|
26
|
-
serializedSignature: string;
|
|
27
|
-
signatureScheme: "ED25519" | "Secp256k1" | "Secp256r1";
|
|
28
|
-
signature: Uint8Array<ArrayBuffer>;
|
|
29
|
-
publicKey: Uint8Array<ArrayBuffer>;
|
|
30
|
-
bytes: Uint8Array<ArrayBuffer>;
|
|
31
|
-
} | {
|
|
32
26
|
signatureScheme: "Passkey";
|
|
33
27
|
serializedSignature: string;
|
|
34
28
|
signature: Uint8Array<ArrayBufferLike>;
|
|
@@ -60,6 +54,12 @@ declare function parseSerializedSignature(serializedSignature: string): {
|
|
|
60
54
|
};
|
|
61
55
|
signature: Uint8Array<ArrayBufferLike>;
|
|
62
56
|
publicKey: Uint8Array<ArrayBuffer>;
|
|
57
|
+
} | {
|
|
58
|
+
serializedSignature: string;
|
|
59
|
+
signatureScheme: "ED25519" | "Secp256k1" | "Secp256r1";
|
|
60
|
+
signature: Uint8Array<ArrayBuffer>;
|
|
61
|
+
publicKey: Uint8Array<ArrayBuffer>;
|
|
62
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
63
63
|
} | {
|
|
64
64
|
serializedSignature: string;
|
|
65
65
|
signatureScheme: "MultiSig";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BatchGetObjectsRequest, BatchGetObjectsResponse, BatchGetTransactionsRequest, BatchGetTransactionsResponse, GetCheckpointRequest, GetCheckpointResponse, GetEpochRequest, GetEpochResponse, GetObjectRequest, GetObjectResponse, GetServiceInfoRequest, GetServiceInfoResponse, GetTransactionRequest, GetTransactionResponse } from "./ledger_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime3 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc3 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/ledger_service.client.d.ts
|
|
@@ -45,9 +45,9 @@ interface ILedgerServiceClient {
|
|
|
45
45
|
declare class LedgerServiceClient implements ILedgerServiceClient, ServiceInfo {
|
|
46
46
|
private readonly _transport;
|
|
47
47
|
typeName: string;
|
|
48
|
-
methods:
|
|
48
|
+
methods: _protobuf_ts_runtime_rpc3.MethodInfo<any, any>[];
|
|
49
49
|
options: {
|
|
50
|
-
[extensionName: string]:
|
|
50
|
+
[extensionName: string]: _protobuf_ts_runtime3.JsonValue;
|
|
51
51
|
};
|
|
52
52
|
constructor(_transport: RpcTransport);
|
|
53
53
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GetDatatypeRequest, GetDatatypeResponse, GetFunctionRequest, GetFunctionResponse, GetPackageRequest, GetPackageResponse, ListPackageVersionsRequest, ListPackageVersionsResponse } from "./move_package_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime0 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc0 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/move_package_service.client.d.ts
|
|
@@ -31,9 +31,9 @@ interface IMovePackageServiceClient {
|
|
|
31
31
|
declare class MovePackageServiceClient implements IMovePackageServiceClient, ServiceInfo {
|
|
32
32
|
private readonly _transport;
|
|
33
33
|
typeName: string;
|
|
34
|
-
methods:
|
|
34
|
+
methods: _protobuf_ts_runtime_rpc0.MethodInfo<any, any>[];
|
|
35
35
|
options: {
|
|
36
|
-
[extensionName: string]:
|
|
36
|
+
[extensionName: string]: _protobuf_ts_runtime0.JsonValue;
|
|
37
37
|
};
|
|
38
38
|
constructor(_transport: RpcTransport);
|
|
39
39
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LookupNameRequest, LookupNameResponse, ReverseLookupNameRequest, ReverseLookupNameResponse } from "./name_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime5 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc5 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/name_service.client.d.ts
|
|
@@ -23,9 +23,9 @@ interface INameServiceClient {
|
|
|
23
23
|
declare class NameServiceClient implements INameServiceClient, ServiceInfo {
|
|
24
24
|
private readonly _transport;
|
|
25
25
|
typeName: string;
|
|
26
|
-
methods:
|
|
26
|
+
methods: _protobuf_ts_runtime_rpc5.MethodInfo<any, any>[];
|
|
27
27
|
options: {
|
|
28
|
-
[extensionName: string]:
|
|
28
|
+
[extensionName: string]: _protobuf_ts_runtime5.JsonValue;
|
|
29
29
|
};
|
|
30
30
|
constructor(_transport: RpcTransport);
|
|
31
31
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VerifySignatureRequest, VerifySignatureResponse } from "./signature_verification_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime2 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc2 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.ts
|
|
@@ -21,9 +21,9 @@ interface ISignatureVerificationServiceClient {
|
|
|
21
21
|
declare class SignatureVerificationServiceClient implements ISignatureVerificationServiceClient, ServiceInfo {
|
|
22
22
|
private readonly _transport;
|
|
23
23
|
typeName: string;
|
|
24
|
-
methods:
|
|
24
|
+
methods: _protobuf_ts_runtime_rpc2.MethodInfo<any, any>[];
|
|
25
25
|
options: {
|
|
26
|
-
[extensionName: string]:
|
|
26
|
+
[extensionName: string]: _protobuf_ts_runtime2.JsonValue;
|
|
27
27
|
};
|
|
28
28
|
constructor(_transport: RpcTransport);
|
|
29
29
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GetBalanceRequest, GetBalanceResponse, GetCoinInfoRequest, GetCoinInfoResponse, ListBalancesRequest, ListBalancesResponse, ListDynamicFieldsRequest, ListDynamicFieldsResponse, ListOwnedObjectsRequest, ListOwnedObjectsResponse } from "./state_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime4 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc4 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/state_service.client.d.ts
|
|
@@ -35,9 +35,9 @@ interface IStateServiceClient {
|
|
|
35
35
|
declare class StateServiceClient implements IStateServiceClient, ServiceInfo {
|
|
36
36
|
private readonly _transport;
|
|
37
37
|
typeName: string;
|
|
38
|
-
methods:
|
|
38
|
+
methods: _protobuf_ts_runtime_rpc4.MethodInfo<any, any>[];
|
|
39
39
|
options: {
|
|
40
|
-
[extensionName: string]:
|
|
40
|
+
[extensionName: string]: _protobuf_ts_runtime4.JsonValue;
|
|
41
41
|
};
|
|
42
42
|
constructor(_transport: RpcTransport);
|
|
43
43
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SubscribeCheckpointsRequest, SubscribeCheckpointsResponse } from "./subscription_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime6 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc6 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServerStreamingCall, ServiceInfo } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/subscription_service.client.d.ts
|
|
@@ -31,9 +31,9 @@ interface ISubscriptionServiceClient {
|
|
|
31
31
|
declare class SubscriptionServiceClient implements ISubscriptionServiceClient, ServiceInfo {
|
|
32
32
|
private readonly _transport;
|
|
33
33
|
typeName: string;
|
|
34
|
-
methods:
|
|
34
|
+
methods: _protobuf_ts_runtime_rpc6.MethodInfo<any, any>[];
|
|
35
35
|
options: {
|
|
36
|
-
[extensionName: string]:
|
|
36
|
+
[extensionName: string]: _protobuf_ts_runtime6.JsonValue;
|
|
37
37
|
};
|
|
38
38
|
constructor(_transport: RpcTransport);
|
|
39
39
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ExecuteTransactionRequest, ExecuteTransactionResponse, SimulateTransactionRequest, SimulateTransactionResponse } from "./transaction_execution_service.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as _protobuf_ts_runtime1 from "@protobuf-ts/runtime";
|
|
3
|
+
import * as _protobuf_ts_runtime_rpc1 from "@protobuf-ts/runtime-rpc";
|
|
4
4
|
import { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from "@protobuf-ts/runtime-rpc";
|
|
5
5
|
|
|
6
6
|
//#region src/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.ts
|
|
@@ -23,9 +23,9 @@ interface ITransactionExecutionServiceClient {
|
|
|
23
23
|
declare class TransactionExecutionServiceClient implements ITransactionExecutionServiceClient, ServiceInfo {
|
|
24
24
|
private readonly _transport;
|
|
25
25
|
typeName: string;
|
|
26
|
-
methods:
|
|
26
|
+
methods: _protobuf_ts_runtime_rpc1.MethodInfo<any, any>[];
|
|
27
27
|
options: {
|
|
28
|
-
[extensionName: string]:
|
|
28
|
+
[extensionName: string]: _protobuf_ts_runtime1.JsonValue;
|
|
29
29
|
};
|
|
30
30
|
constructor(_transport: RpcTransport);
|
|
31
31
|
/**
|
|
@@ -8,7 +8,7 @@ import { createPure } from "./pure.mjs";
|
|
|
8
8
|
import { SignatureWithBytes, Signer } from "../cryptography/keypair.mjs";
|
|
9
9
|
import "../cryptography/index.mjs";
|
|
10
10
|
import { ClientWithCoreApi } from "../client/core.mjs";
|
|
11
|
-
import * as
|
|
11
|
+
import * as _mysten_bcs1124 from "@mysten/bcs";
|
|
12
12
|
import { SerializedBcs } from "@mysten/bcs";
|
|
13
13
|
import { InferInput } from "valibot";
|
|
14
14
|
|
|
@@ -91,7 +91,7 @@ declare class Transaction {
|
|
|
91
91
|
getData(): {
|
|
92
92
|
version: 2;
|
|
93
93
|
sender?: string | null | undefined;
|
|
94
|
-
expiration?:
|
|
94
|
+
expiration?: _mysten_bcs1124.EnumOutputShapeWithKeys<{
|
|
95
95
|
None: true;
|
|
96
96
|
Epoch: string | number;
|
|
97
97
|
ValidDuring: {
|
|
@@ -113,8 +113,8 @@ declare class Transaction {
|
|
|
113
113
|
digest: string;
|
|
114
114
|
}[] | null;
|
|
115
115
|
};
|
|
116
|
-
inputs:
|
|
117
|
-
Object:
|
|
116
|
+
inputs: _mysten_bcs1124.EnumOutputShapeWithKeys<{
|
|
117
|
+
Object: _mysten_bcs1124.EnumOutputShapeWithKeys<{
|
|
118
118
|
ImmOrOwnedObject: {
|
|
119
119
|
objectId: string;
|
|
120
120
|
version: string | number;
|
|
@@ -153,13 +153,13 @@ declare class Transaction {
|
|
|
153
153
|
Balance: string;
|
|
154
154
|
$kind: "Balance";
|
|
155
155
|
};
|
|
156
|
-
withdrawFrom:
|
|
156
|
+
withdrawFrom: _mysten_bcs1124.EnumOutputShapeWithKeys<{
|
|
157
157
|
Sender: true;
|
|
158
158
|
Sponsor: true;
|
|
159
159
|
}, "Sender" | "Sponsor">;
|
|
160
160
|
};
|
|
161
161
|
}, "Object" | "Pure" | "FundsWithdrawal" | "UnresolvedPure" | "UnresolvedObject">[];
|
|
162
|
-
commands:
|
|
162
|
+
commands: _mysten_bcs1124.EnumOutputShapeWithKeys<{
|
|
163
163
|
MoveCall: {
|
|
164
164
|
package: string;
|
|
165
165
|
module: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transaction.d.mts","names":[],"sources":["../../src/transactions/Transaction.ts"],"mappings":";;;;;;;;;;;;;;;KAyCY,yBAAA,GACT,OAAA,CAAQ,UAAA,QAAkB,cAAA;EAAmB,KAAA;EAAgB,IAAA;AAAA,OAE7D,EAAA,EAAI,WAAA,KACC,OAAA,CAAQ,UAAA,QAAkB,cAAA;EAAmB,KAAA;EAAgB,IAAA;AAAA,MAClE,qBAAA,CAAsB,yBAAA;AAAA,KAEb,iBAAA,GAAoB,OAAA,CAAQ,QAAA;EAAY,MAAA;AAAA,KACnD,OAAA,CAAQ,QAAA;EAAY,YAAA;AAAA;AAAA,KAET,yBAAA,GACT,OAAA,CAAQ,QAAA;EAAY,MAAA;AAAA,cACX,OAAA,CAAQ,QAAA;EAAY,YAAA;AAAA;AAAA,KAEpB,qBAAA,WACD,yBAAA,UAAmC,yBAAA,YACzC,EAAA,EAAI,WAAA,KAAgB,OAAA,CAAQ,CAAA;AAAA,cAiE3B,iBAAA;AAAA,UAEI,WAAA,SAAoB,uBAAA;EAC7B,MAAA,EAAQ,MAAA;AAAA;AAAA,iBAGO,aAAA,CAAc,GAAA,YAAe,GAAA,IAAO,eAAA;AAAA,KAIxC,sBAAA,YAAkC,OAAA,GAAU,yBAAA;AAAA,KAKnD,eAAA;EACJ,OAAA;AAAA;AAAA,UAGgB,sBAAA;EAhGoC;;;;;;AAGrD;EAqGC,eAAA,GAAkB,MAAA,SAAe,iBAAA;AAAA;;;;cAMrB,WAAA;EAAA;GAkJP,iBAAA;EA7P0B;;;;EAAA,OAyHxB,QAAA,CAAS,UAAA,WAAqB,UAAA,GAAU,WAAA;EAxH3B;;;AAErB;;;;;;;EAFqB,OAgJb,IAAA,CACN,WAAA,WAAsB,UAAA,GAAa,eAAA,EACnC,OAAA,GAAS,sBAAA,GAA2B,WAAA;EA8CrC,sBAAA,CAAuB,IAAA,EAAM,iBAAA;EAI7B,cAAA,CAAe,IAAA,EAAM,iBAAA;EAIrB,iBAAA,CAAkB,MAAA,UAAgB,QAAA,EAAU,iBAAA;EAQ5C,SAAA,CAAU,MAAA;EA5MC;;;;EAmNX,iBAAA,CAAkB,MAAA;EAKlB,aAAA,CAAc,UAAA,GAAa,UAAA,QAAkB,qBAAA;EAG7C,WAAA,CAAY,KAAA;EAGZ,YAAA,CAAa,MAAA;EAIb,oBAAA,CAAqB,MAAA;EAMrB,WAAA,CAAY,KAAA;EAGZ,aAAA,CAAc,QAAA,EAAU,SAAA;EAvOQ;EA8OhC,OAAA,CAAA;;;iBAPiC,
|
|
1
|
+
{"version":3,"file":"Transaction.d.mts","names":[],"sources":["../../src/transactions/Transaction.ts"],"mappings":"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"}
|
package/dist/verify/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature } from "./verify.mjs";
|
|
2
|
-
export { publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
|
1
|
+
import { isValidPersonalMessageSignature, isValidSignature, isValidTransactionSignature, publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature } from "./verify.mjs";
|
|
2
|
+
export { isValidPersonalMessageSignature, isValidSignature, isValidTransactionSignature, publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
package/dist/verify/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature } from "./verify.mjs";
|
|
1
|
+
import { isValidPersonalMessageSignature, isValidSignature, isValidTransactionSignature, publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature } from "./verify.mjs";
|
|
2
2
|
|
|
3
|
-
export { publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
|
3
|
+
export { isValidPersonalMessageSignature, isValidSignature, isValidTransactionSignature, publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
package/dist/verify/verify.d.mts
CHANGED
|
@@ -4,6 +4,26 @@ import "../cryptography/index.mjs";
|
|
|
4
4
|
import { ClientWithCoreApi } from "../client/core.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/verify/verify.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Whether `signature` is a valid signature over `bytes` (and, if `options.address`
|
|
9
|
+
* is given, was produced by that address). Returns `false` for a malformed or
|
|
10
|
+
* cryptographically invalid signature, or one that doesn't match the address;
|
|
11
|
+
* only an *environmental* failure (e.g. a zkLogin JWK/epoch lookup) throws, so a
|
|
12
|
+
* network blip is never reported as an invalid signature.
|
|
13
|
+
*/
|
|
14
|
+
declare function isValidSignature(bytes: Uint8Array, signature: string, options?: {
|
|
15
|
+
address?: string;
|
|
16
|
+
}): Promise<boolean>;
|
|
17
|
+
/** Like {@link isValidSignature}, for a personal message. */
|
|
18
|
+
declare function isValidPersonalMessageSignature(message: Uint8Array, signature: string, options?: {
|
|
19
|
+
client?: ClientWithCoreApi;
|
|
20
|
+
address?: string;
|
|
21
|
+
}): Promise<boolean>;
|
|
22
|
+
/** Like {@link isValidSignature}, for transaction bytes. */
|
|
23
|
+
declare function isValidTransactionSignature(transaction: Uint8Array, signature: string, options?: {
|
|
24
|
+
client?: ClientWithCoreApi;
|
|
25
|
+
address?: string;
|
|
26
|
+
}): Promise<boolean>;
|
|
7
27
|
declare function verifySignature(bytes: Uint8Array, signature: string, options?: {
|
|
8
28
|
address?: string;
|
|
9
29
|
}): Promise<PublicKey>;
|
|
@@ -24,5 +44,5 @@ declare function publicKeyFromSuiBytes(publicKey: string | Uint8Array, options?:
|
|
|
24
44
|
address?: string;
|
|
25
45
|
}): PublicKey;
|
|
26
46
|
//#endregion
|
|
27
|
-
export { publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
|
47
|
+
export { isValidPersonalMessageSignature, isValidSignature, isValidTransactionSignature, publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
|
28
48
|
//# sourceMappingURL=verify.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.mts","names":[],"sources":["../../src/verify/verify.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.d.mts","names":[],"sources":["../../src/verify/verify.ts"],"mappings":";;;;;;;;;;AAsBA;;;iBAAsB,gBAAA,CACrB,KAAA,EAAO,UAAA,EACP,SAAA,UACA,OAAA;EAAW,OAAA;AAAA,IACT,OAAA;;iBAQmB,+BAAA,CACrB,OAAA,EAAS,UAAA,EACT,SAAA,UACA,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,OAAA;AAAA,IACrC,OAAA;;iBAUmB,2BAAA,CACrB,WAAA,EAAa,UAAA,EACb,SAAA,UACA,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,OAAA;AAAA,IACrC,OAAA;AAAA,iBASmB,eAAA,CACrB,KAAA,EAAO,UAAA,EACP,SAAA,UACA,OAAA;EAAW,OAAA;AAAA,IACT,OAAA,CAAQ,SAAA;AAAA,iBAWW,8BAAA,CACrB,OAAA,EAAS,UAAA,EACT,SAAA,UACA,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,OAAA;AAAA,IACrC,OAAA,CAAQ,SAAA;AAAA,iBAWW,0BAAA,CACrB,WAAA,EAAa,UAAA,EACb,SAAA,UACA,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,OAAA;AAAA,IACrC,OAAA,CAAQ,SAAA;AAAA,iBAyCK,qBAAA,CACf,eAAA,EAAiB,eAAA,EACjB,KAAA,EAAO,UAAA,EACP,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,OAAA;AAAA,IACrC,SAAA;AAAA,iBAgCa,qBAAA,CACf,SAAA,WAAoB,UAAA,EACpB,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,OAAA;AAAA,IAAuB,SAAA"}
|
package/dist/verify/verify.mjs
CHANGED
|
@@ -9,23 +9,50 @@ import { MultiSigPublicKey } from "../multisig/publickey.mjs";
|
|
|
9
9
|
import { fromBase64 } from "@mysten/bcs";
|
|
10
10
|
|
|
11
11
|
//#region src/verify/verify.ts
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Whether `signature` is a valid signature over `bytes` (and, if `options.address`
|
|
14
|
+
* is given, was produced by that address). Returns `false` for a malformed or
|
|
15
|
+
* cryptographically invalid signature, or one that doesn't match the address;
|
|
16
|
+
* only an *environmental* failure (e.g. a zkLogin JWK/epoch lookup) throws, so a
|
|
17
|
+
* network blip is never reported as an invalid signature.
|
|
18
|
+
*/
|
|
19
|
+
async function isValidSignature(bytes, signature, options = {}) {
|
|
20
|
+
const parsed = tryParseSignature(signature);
|
|
21
|
+
if (!parsed) return false;
|
|
22
|
+
if (!await parsed.publicKey.verify(bytes, parsed.serializedSignature)) return false;
|
|
23
|
+
return options.address ? parsed.publicKey.verifyAddress(options.address) : true;
|
|
24
|
+
}
|
|
25
|
+
/** Like {@link isValidSignature}, for a personal message. */
|
|
26
|
+
async function isValidPersonalMessageSignature(message, signature, options = {}) {
|
|
27
|
+
const parsed = tryParseSignature(signature, { client: options.client });
|
|
28
|
+
if (!parsed) return false;
|
|
29
|
+
if (!await parsed.publicKey.verifyPersonalMessage(message, parsed.serializedSignature)) return false;
|
|
30
|
+
return options.address ? parsed.publicKey.verifyAddress(options.address) : true;
|
|
31
|
+
}
|
|
32
|
+
/** Like {@link isValidSignature}, for transaction bytes. */
|
|
33
|
+
async function isValidTransactionSignature(transaction, signature, options = {}) {
|
|
34
|
+
const parsed = tryParseSignature(signature, { client: options.client });
|
|
35
|
+
if (!parsed) return false;
|
|
36
|
+
if (!await parsed.publicKey.verifyTransaction(transaction, parsed.serializedSignature)) return false;
|
|
37
|
+
return options.address ? parsed.publicKey.verifyAddress(options.address) : true;
|
|
38
|
+
}
|
|
39
|
+
async function verifySignature(bytes, signature, options = {}) {
|
|
40
|
+
const { publicKey } = parseSignature(signature);
|
|
41
|
+
if (!await isValidSignature(bytes, signature)) throw new Error(`Signature is not valid for the provided data`);
|
|
42
|
+
if (options.address && !publicKey.verifyAddress(options.address)) throw new Error(`Signature is not valid for the provided address`);
|
|
43
|
+
return publicKey;
|
|
17
44
|
}
|
|
18
45
|
async function verifyPersonalMessageSignature(message, signature, options = {}) {
|
|
19
|
-
const
|
|
20
|
-
if (!await
|
|
21
|
-
if (options
|
|
22
|
-
return
|
|
46
|
+
const { publicKey } = parseSignature(signature, options);
|
|
47
|
+
if (!await isValidPersonalMessageSignature(message, signature, { client: options.client })) throw new Error(`Signature is not valid for the provided message`);
|
|
48
|
+
if (options.address && !publicKey.verifyAddress(options.address)) throw new Error(`Signature is not valid for the provided address`);
|
|
49
|
+
return publicKey;
|
|
23
50
|
}
|
|
24
51
|
async function verifyTransactionSignature(transaction, signature, options = {}) {
|
|
25
|
-
const
|
|
26
|
-
if (!await
|
|
27
|
-
if (options
|
|
28
|
-
return
|
|
52
|
+
const { publicKey } = parseSignature(signature, options);
|
|
53
|
+
if (!await isValidTransactionSignature(transaction, signature, { client: options.client })) throw new Error(`Signature is not valid for the provided Transaction`);
|
|
54
|
+
if (options.address && !publicKey.verifyAddress(options.address)) throw new Error(`Signature is not valid for the provided address`);
|
|
55
|
+
return publicKey;
|
|
29
56
|
}
|
|
30
57
|
function parseSignature(signature, options = {}) {
|
|
31
58
|
const parsedSignature = parseSerializedSignature(signature);
|
|
@@ -39,6 +66,14 @@ function parseSignature(signature, options = {}) {
|
|
|
39
66
|
publicKey
|
|
40
67
|
};
|
|
41
68
|
}
|
|
69
|
+
/** {@link parseSignature}, returning `null` instead of throwing on a malformed signature. */
|
|
70
|
+
function tryParseSignature(signature, options = {}) {
|
|
71
|
+
try {
|
|
72
|
+
return parseSignature(signature, options);
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
42
77
|
function publicKeyFromRawBytes(signatureScheme, bytes, options = {}) {
|
|
43
78
|
let publicKey;
|
|
44
79
|
switch (signatureScheme) {
|
|
@@ -72,5 +107,5 @@ function publicKeyFromSuiBytes(publicKey, options = {}) {
|
|
|
72
107
|
}
|
|
73
108
|
|
|
74
109
|
//#endregion
|
|
75
|
-
export { publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
|
110
|
+
export { isValidPersonalMessageSignature, isValidSignature, isValidTransactionSignature, publicKeyFromRawBytes, publicKeyFromSuiBytes, verifyPersonalMessageSignature, verifySignature, verifyTransactionSignature };
|
|
76
111
|
//# sourceMappingURL=verify.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.mjs","names":[],"sources":["../../src/verify/verify.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64 } from '@mysten/bcs';\n\nimport type { PublicKey, SignatureFlag, SignatureScheme } from '../cryptography/index.js';\nimport { parseSerializedSignature, SIGNATURE_FLAG_TO_SCHEME } from '../cryptography/index.js';\nimport { Ed25519PublicKey } from '../keypairs/ed25519/publickey.js';\nimport { PasskeyPublicKey } from '../keypairs/passkey/publickey.js';\nimport { Secp256k1PublicKey } from '../keypairs/secp256k1/publickey.js';\nimport { Secp256r1PublicKey } from '../keypairs/secp256r1/publickey.js';\nimport { MultiSigPublicKey } from '../multisig/publickey.js';\nimport { ZkLoginPublicIdentifier } from '../zklogin/publickey.js';\nimport type { ClientWithCoreApi } from '../client/core.js';\n\nexport async function
|
|
1
|
+
{"version":3,"file":"verify.mjs","names":[],"sources":["../../src/verify/verify.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64 } from '@mysten/bcs';\n\nimport type { PublicKey, SignatureFlag, SignatureScheme } from '../cryptography/index.js';\nimport { parseSerializedSignature, SIGNATURE_FLAG_TO_SCHEME } from '../cryptography/index.js';\nimport { Ed25519PublicKey } from '../keypairs/ed25519/publickey.js';\nimport { PasskeyPublicKey } from '../keypairs/passkey/publickey.js';\nimport { Secp256k1PublicKey } from '../keypairs/secp256k1/publickey.js';\nimport { Secp256r1PublicKey } from '../keypairs/secp256r1/publickey.js';\nimport { MultiSigPublicKey } from '../multisig/publickey.js';\nimport { ZkLoginPublicIdentifier } from '../zklogin/publickey.js';\nimport type { ClientWithCoreApi } from '../client/core.js';\n\n/**\n * Whether `signature` is a valid signature over `bytes` (and, if `options.address`\n * is given, was produced by that address). Returns `false` for a malformed or\n * cryptographically invalid signature, or one that doesn't match the address;\n * only an *environmental* failure (e.g. a zkLogin JWK/epoch lookup) throws, so a\n * network blip is never reported as an invalid signature.\n */\nexport async function isValidSignature(\n\tbytes: Uint8Array,\n\tsignature: string,\n\toptions: { address?: string } = {},\n): Promise<boolean> {\n\tconst parsed = tryParseSignature(signature);\n\tif (!parsed) return false;\n\tif (!(await parsed.publicKey.verify(bytes, parsed.serializedSignature))) return false;\n\treturn options.address ? parsed.publicKey.verifyAddress(options.address) : true;\n}\n\n/** Like {@link isValidSignature}, for a personal message. */\nexport async function isValidPersonalMessageSignature(\n\tmessage: Uint8Array,\n\tsignature: string,\n\toptions: { client?: ClientWithCoreApi; address?: string } = {},\n): Promise<boolean> {\n\tconst parsed = tryParseSignature(signature, { client: options.client });\n\tif (!parsed) return false;\n\tif (!(await parsed.publicKey.verifyPersonalMessage(message, parsed.serializedSignature))) {\n\t\treturn false;\n\t}\n\treturn options.address ? parsed.publicKey.verifyAddress(options.address) : true;\n}\n\n/** Like {@link isValidSignature}, for transaction bytes. */\nexport async function isValidTransactionSignature(\n\ttransaction: Uint8Array,\n\tsignature: string,\n\toptions: { client?: ClientWithCoreApi; address?: string } = {},\n): Promise<boolean> {\n\tconst parsed = tryParseSignature(signature, { client: options.client });\n\tif (!parsed) return false;\n\tif (!(await parsed.publicKey.verifyTransaction(transaction, parsed.serializedSignature))) {\n\t\treturn false;\n\t}\n\treturn options.address ? parsed.publicKey.verifyAddress(options.address) : true;\n}\n\nexport async function verifySignature(\n\tbytes: Uint8Array,\n\tsignature: string,\n\toptions: { address?: string } = {},\n): Promise<PublicKey> {\n\tconst { publicKey } = parseSignature(signature);\n\tif (!(await isValidSignature(bytes, signature))) {\n\t\tthrow new Error(`Signature is not valid for the provided data`);\n\t}\n\tif (options.address && !publicKey.verifyAddress(options.address)) {\n\t\tthrow new Error(`Signature is not valid for the provided address`);\n\t}\n\treturn publicKey;\n}\n\nexport async function verifyPersonalMessageSignature(\n\tmessage: Uint8Array,\n\tsignature: string,\n\toptions: { client?: ClientWithCoreApi; address?: string } = {},\n): Promise<PublicKey> {\n\tconst { publicKey } = parseSignature(signature, options);\n\tif (!(await isValidPersonalMessageSignature(message, signature, { client: options.client }))) {\n\t\tthrow new Error(`Signature is not valid for the provided message`);\n\t}\n\tif (options.address && !publicKey.verifyAddress(options.address)) {\n\t\tthrow new Error(`Signature is not valid for the provided address`);\n\t}\n\treturn publicKey;\n}\n\nexport async function verifyTransactionSignature(\n\ttransaction: Uint8Array,\n\tsignature: string,\n\toptions: { client?: ClientWithCoreApi; address?: string } = {},\n): Promise<PublicKey> {\n\tconst { publicKey } = parseSignature(signature, options);\n\tif (!(await isValidTransactionSignature(transaction, signature, { client: options.client }))) {\n\t\tthrow new Error(`Signature is not valid for the provided Transaction`);\n\t}\n\tif (options.address && !publicKey.verifyAddress(options.address)) {\n\t\tthrow new Error(`Signature is not valid for the provided address`);\n\t}\n\treturn publicKey;\n}\n\nfunction parseSignature(signature: string, options: { client?: ClientWithCoreApi } = {}) {\n\tconst parsedSignature = parseSerializedSignature(signature);\n\n\tif (parsedSignature.signatureScheme === 'MultiSig') {\n\t\treturn {\n\t\t\t...parsedSignature,\n\t\t\tpublicKey: new MultiSigPublicKey(parsedSignature.multisig.multisig_pk),\n\t\t};\n\t}\n\n\tconst publicKey = publicKeyFromRawBytes(\n\t\tparsedSignature.signatureScheme,\n\t\tparsedSignature.publicKey,\n\t\toptions,\n\t);\n\treturn {\n\t\t...parsedSignature,\n\t\tpublicKey,\n\t};\n}\n\n/** {@link parseSignature}, returning `null` instead of throwing on a malformed signature. */\nfunction tryParseSignature(signature: string, options: { client?: ClientWithCoreApi } = {}) {\n\ttry {\n\t\treturn parseSignature(signature, options);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function publicKeyFromRawBytes(\n\tsignatureScheme: SignatureScheme,\n\tbytes: Uint8Array,\n\toptions: { client?: ClientWithCoreApi; address?: string } = {},\n): PublicKey {\n\tlet publicKey: PublicKey;\n\tswitch (signatureScheme) {\n\t\tcase 'ED25519':\n\t\t\tpublicKey = new Ed25519PublicKey(bytes);\n\t\t\tbreak;\n\t\tcase 'Secp256k1':\n\t\t\tpublicKey = new Secp256k1PublicKey(bytes);\n\t\t\tbreak;\n\t\tcase 'Secp256r1':\n\t\t\tpublicKey = new Secp256r1PublicKey(bytes);\n\t\t\tbreak;\n\t\tcase 'MultiSig':\n\t\t\tpublicKey = new MultiSigPublicKey(bytes);\n\t\t\tbreak;\n\t\tcase 'ZkLogin':\n\t\t\tpublicKey = ZkLoginPublicIdentifier.fromBytes(bytes, options);\n\t\t\tbreak;\n\t\tcase 'Passkey':\n\t\t\tpublicKey = new PasskeyPublicKey(bytes);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported signature scheme ${signatureScheme}`);\n\t}\n\n\tif (options.address && publicKey.toSuiAddress() !== options.address) {\n\t\tthrow new Error(`Public key bytes do not match the provided address`);\n\t}\n\n\treturn publicKey;\n}\n\nexport function publicKeyFromSuiBytes(\n\tpublicKey: string | Uint8Array,\n\toptions: { client?: ClientWithCoreApi; address?: string } = {},\n) {\n\tconst bytes = typeof publicKey === 'string' ? fromBase64(publicKey) : publicKey;\n\n\tconst signatureScheme = SIGNATURE_FLAG_TO_SCHEME[bytes[0] as SignatureFlag];\n\n\treturn publicKeyFromRawBytes(signatureScheme, bytes.slice(1), options);\n}\n"],"mappings":"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"}
|
package/dist/version.mjs
CHANGED
package/dist/version.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n// This file is generated by genversion.mjs. Do not edit it directly.\n\nexport const PACKAGE_VERSION = '2.
|
|
1
|
+
{"version":3,"file":"version.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n// This file is generated by genversion.mjs. Do not edit it directly.\n\nexport const PACKAGE_VERSION = '2.20.0';\n"],"mappings":";AAKA,MAAa,kBAAkB"}
|
package/dist/zklogin/bcs.d.mts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _mysten_bcs1111 from "@mysten/bcs";
|
|
2
2
|
import { InferBcsInput } from "@mysten/bcs";
|
|
3
3
|
|
|
4
4
|
//#region src/zklogin/bcs.d.ts
|
|
5
|
-
declare const zkLoginSignature:
|
|
6
|
-
inputs:
|
|
7
|
-
proofPoints:
|
|
8
|
-
a:
|
|
5
|
+
declare const zkLoginSignature: _mysten_bcs1111.BcsStruct<{
|
|
6
|
+
inputs: _mysten_bcs1111.BcsStruct<{
|
|
7
|
+
proofPoints: _mysten_bcs1111.BcsStruct<{
|
|
8
|
+
a: _mysten_bcs1111.BcsType<string[], Iterable<string> & {
|
|
9
9
|
length: number;
|
|
10
10
|
}, string>;
|
|
11
|
-
b:
|
|
11
|
+
b: _mysten_bcs1111.BcsType<string[][], Iterable<Iterable<string> & {
|
|
12
12
|
length: number;
|
|
13
13
|
}> & {
|
|
14
14
|
length: number;
|
|
15
15
|
}, string>;
|
|
16
|
-
c:
|
|
16
|
+
c: _mysten_bcs1111.BcsType<string[], Iterable<string> & {
|
|
17
17
|
length: number;
|
|
18
18
|
}, string>;
|
|
19
19
|
}, string>;
|
|
20
|
-
issBase64Details:
|
|
21
|
-
value:
|
|
22
|
-
indexMod4:
|
|
20
|
+
issBase64Details: _mysten_bcs1111.BcsStruct<{
|
|
21
|
+
value: _mysten_bcs1111.BcsType<string, string, "string">;
|
|
22
|
+
indexMod4: _mysten_bcs1111.BcsType<number, number, "u8">;
|
|
23
23
|
}, string>;
|
|
24
|
-
headerBase64:
|
|
25
|
-
addressSeed:
|
|
24
|
+
headerBase64: _mysten_bcs1111.BcsType<string, string, "string">;
|
|
25
|
+
addressSeed: _mysten_bcs1111.BcsType<string, string, "string">;
|
|
26
26
|
}, string>;
|
|
27
|
-
maxEpoch:
|
|
28
|
-
userSignature:
|
|
27
|
+
maxEpoch: _mysten_bcs1111.BcsType<string, string | number | bigint, "u64">;
|
|
28
|
+
userSignature: _mysten_bcs1111.BcsType<Uint8Array<ArrayBufferLike>, Iterable<number>, "vector<u8>">;
|
|
29
29
|
}, string>;
|
|
30
30
|
type ZkLoginSignature = InferBcsInput<typeof zkLoginSignature>;
|
|
31
31
|
type ZkLoginSignatureInputs = ZkLoginSignature['inputs'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bcs.d.mts","names":[],"sources":["../../src/zklogin/bcs.ts"],"mappings":";;;;cAMa,gBAAA,
|
|
1
|
+
{"version":3,"file":"bcs.d.mts","names":[],"sources":["../../src/zklogin/bcs.ts"],"mappings":";;;;cAMa,gBAAA,kBAAgB,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;KAkBjB,gBAAA,GAAmB,aAAA,QAAqB,gBAAA;AAAA,KACxC,sBAAA,GAAyB,gBAAA"}
|
package/dist/zklogin/index.d.mts
CHANGED
|
@@ -3,7 +3,8 @@ import { getZkLoginSignature, parseZkLoginSignature } from "./signature.mjs";
|
|
|
3
3
|
import { genAddressSeed, getExtendedEphemeralPublicKey, hashASCIIStrToField, toBigEndianBytes, toPaddedBigEndianBytes } from "./utils.mjs";
|
|
4
4
|
import { ComputeZkLoginAddressOptions, computeZkLoginAddress, computeZkLoginAddressFromSeed, jwtToAddress } from "./address.mjs";
|
|
5
5
|
import { ZkLoginPublicIdentifier, toZkLoginPublicIdentifier } from "./publickey.mjs";
|
|
6
|
+
import { ZkLoginSigner, ZkLoginSignerOptions } from "./signer.mjs";
|
|
6
7
|
import { poseidonHash } from "./poseidon.mjs";
|
|
7
8
|
import { generateNonce, generateRandomness } from "./nonce.mjs";
|
|
8
9
|
import { decodeJwt } from "./jwt-utils.mjs";
|
|
9
|
-
export { type ComputeZkLoginAddressOptions, ZkLoginPublicIdentifier, type ZkLoginSignatureInputs, computeZkLoginAddress, computeZkLoginAddressFromSeed, decodeJwt, genAddressSeed, generateNonce, generateRandomness, getExtendedEphemeralPublicKey, getZkLoginSignature, hashASCIIStrToField, jwtToAddress, parseZkLoginSignature, poseidonHash, toBigEndianBytes, toPaddedBigEndianBytes, toZkLoginPublicIdentifier };
|
|
10
|
+
export { type ComputeZkLoginAddressOptions, ZkLoginPublicIdentifier, type ZkLoginSignatureInputs, ZkLoginSigner, type ZkLoginSignerOptions, computeZkLoginAddress, computeZkLoginAddressFromSeed, decodeJwt, genAddressSeed, generateNonce, generateRandomness, getExtendedEphemeralPublicKey, getZkLoginSignature, hashASCIIStrToField, jwtToAddress, parseZkLoginSignature, poseidonHash, toBigEndianBytes, toPaddedBigEndianBytes, toZkLoginPublicIdentifier };
|
package/dist/zklogin/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { decodeJwt } from "./jwt-utils.mjs";
|
|
|
4
4
|
import { getZkLoginSignature, parseZkLoginSignature } from "./signature.mjs";
|
|
5
5
|
import { ZkLoginPublicIdentifier, toZkLoginPublicIdentifier } from "./publickey.mjs";
|
|
6
6
|
import { computeZkLoginAddress, computeZkLoginAddressFromSeed, jwtToAddress } from "./address.mjs";
|
|
7
|
+
import { ZkLoginSigner } from "./signer.mjs";
|
|
7
8
|
import { generateNonce, generateRandomness } from "./nonce.mjs";
|
|
8
9
|
|
|
9
|
-
export { ZkLoginPublicIdentifier, computeZkLoginAddress, computeZkLoginAddressFromSeed, decodeJwt, genAddressSeed, generateNonce, generateRandomness, getExtendedEphemeralPublicKey, getZkLoginSignature, hashASCIIStrToField, jwtToAddress, parseZkLoginSignature, poseidonHash, toBigEndianBytes, toPaddedBigEndianBytes, toZkLoginPublicIdentifier };
|
|
10
|
+
export { ZkLoginPublicIdentifier, ZkLoginSigner, computeZkLoginAddress, computeZkLoginAddressFromSeed, decodeJwt, genAddressSeed, generateNonce, generateRandomness, getExtendedEphemeralPublicKey, getZkLoginSignature, hashASCIIStrToField, jwtToAddress, parseZkLoginSignature, poseidonHash, toBigEndianBytes, toPaddedBigEndianBytes, toZkLoginPublicIdentifier };
|
|
@@ -17,6 +17,10 @@ declare class ZkLoginPublicIdentifier extends PublicKey {
|
|
|
17
17
|
}?: {
|
|
18
18
|
client?: ClientWithCoreApi;
|
|
19
19
|
});
|
|
20
|
+
/**
|
|
21
|
+
* Whether this identifier resolves to the deprecated legacy address derivation.
|
|
22
|
+
*/
|
|
23
|
+
get legacyAddress(): boolean;
|
|
20
24
|
static fromBytes(bytes: Uint8Array, {
|
|
21
25
|
client,
|
|
22
26
|
address,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publickey.d.mts","names":[],"sources":["../../src/zklogin/publickey.ts"],"mappings":";;;;;;AAoBA;;cAAa,uBAAA,SAAgC,SAAA;EAAA;EASJ;;;;cAA5B,KAAA,EAAO,iBAAA;IAAqB;EAAA;IAAY,MAAA,GAAS,iBAAA;EAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"publickey.d.mts","names":[],"sources":["../../src/zklogin/publickey.ts"],"mappings":";;;;;;AAoBA;;cAAa,uBAAA,SAAgC,SAAA;EAAA;EASJ;;;;cAA5B,KAAA,EAAO,iBAAA;IAAqB;EAAA;IAAY,MAAA,GAAS,iBAAA;EAAA;EAgCqB;;;EAAA,IAV9E,aAAA,CAAA;EAAA,OAIG,SAAA,CACN,KAAA,EAAO,UAAA;IAEN,MAAA;IACA,OAAA;IACA;EAAA;IACI,MAAA,GAAS,iBAAA;IAAmB,OAAA;IAAkB,aAAA;EAAA,IAA8B,uBAAA;EAAA,OAmC3E,SAAA,CAAU,OAAA,UAAiB,KAAA,EAAO,sBAAA,GAAsB,uBAAA;EAwET;;;EA9C7C,MAAA,CAAO,SAAA,EAAW,uBAAA;EAIlB,YAAA,CAAA;EA1GmC;;;EA+H5C,UAAA,CAAA,GAAc,UAAA,CAAW,WAAA;;;;EAOzB,IAAA,CAAA;EA7HwC;;;EAoIlC,MAAA,CAAO,QAAA,EAAU,UAAA,EAAY,UAAA,EAAY,UAAA,YAAsB,OAAA;EA9GjE;;;EAqHJ,qBAAA,CAAsB,OAAA,EAAS,UAAA,EAAY,SAAA,EAAW,UAAA,YAAsB,OAAA;EA9G1E;;;EA8HF,iBAAA,CAAkB,WAAA,EAAa,UAAA,EAAY,SAAA,EAAW,UAAA,YAAsB,OAAA;EA5H1E;;;EA2IO,aAAA,CAAc,OAAA;AAAA;AAAA,iBAMR,yBAAA,CACf,WAAA,UACA,GAAA,UACA,OAAA;EAAW,MAAA,GAAS,iBAAA;EAAmB,aAAA;AAAA,IACrC,uBAAA"}
|
|
@@ -29,6 +29,12 @@ var ZkLoginPublicIdentifier = class ZkLoginPublicIdentifier extends PublicKey {
|
|
|
29
29
|
this.#legacyAddress = this.#data.length !== this.#data[0] + 1 + 32;
|
|
30
30
|
if (this.#legacyAddress) this.#data = normalizeZkLoginPublicKeyBytes(this.#data, false);
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether this identifier resolves to the deprecated legacy address derivation.
|
|
34
|
+
*/
|
|
35
|
+
get legacyAddress() {
|
|
36
|
+
return this.#legacyAddress;
|
|
37
|
+
}
|
|
32
38
|
static fromBytes(bytes, { client, address, legacyAddress } = {}) {
|
|
33
39
|
let publicKey;
|
|
34
40
|
if (legacyAddress === true) publicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, true), { client });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publickey.mjs","names":["#client","#data","#legacyAddress","#toLegacyAddress"],"sources":["../../src/zklogin/publickey.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64, toHex } from '@mysten/bcs';\nimport { blake2b } from '@noble/hashes/blake2.js';\nimport { bytesToHex } from '@noble/hashes/utils.js';\n\nimport { PublicKey } from '../cryptography/publickey.js';\nimport type { PublicKeyInitData } from '../cryptography/publickey.js';\nimport { SIGNATURE_SCHEME_TO_FLAG } from '../cryptography/signature-scheme.js';\nimport { normalizeSuiAddress, SUI_ADDRESS_LENGTH } from '../utils/sui-types.js';\nimport type { ZkLoginSignatureInputs } from './bcs.js';\nimport { extractClaimValue } from './jwt-utils.js';\nimport { parseZkLoginSignature } from './signature.js';\nimport { normalizeZkLoginIssuer, toBigEndianBytes, toPaddedBigEndianBytes } from './utils.js';\nimport type { ClientWithCoreApi } from '../client/core.js';\n\n/**\n * A zkLogin public identifier\n */\nexport class ZkLoginPublicIdentifier extends PublicKey {\n\t#data: Uint8Array<ArrayBuffer>;\n\t#client?: ClientWithCoreApi;\n\t#legacyAddress: boolean;\n\n\t/**\n\t * Create a new ZkLoginPublicIdentifier object\n\t * @param value zkLogin public identifier as buffer or base-64 encoded string\n\t */\n\tconstructor(value: PublicKeyInitData, { client }: { client?: ClientWithCoreApi } = {}) {\n\t\tsuper();\n\n\t\tthis.#client = client;\n\n\t\tif (typeof value === 'string') {\n\t\t\tthis.#data = fromBase64(value);\n\t\t} else if (value instanceof Uint8Array) {\n\t\t\tthis.#data = value as Uint8Array<ArrayBuffer>;\n\t\t} else {\n\t\t\tthis.#data = Uint8Array.from(value);\n\t\t}\n\t\tthis.#legacyAddress = this.#data.length !== this.#data[0] + 1 + 32;\n\n\t\tif (this.#legacyAddress) {\n\t\t\tthis.#data = normalizeZkLoginPublicKeyBytes(this.#data, false);\n\t\t}\n\t}\n\n\tstatic fromBytes(\n\t\tbytes: Uint8Array,\n\t\t{\n\t\t\tclient,\n\t\t\taddress,\n\t\t\tlegacyAddress,\n\t\t}: { client?: ClientWithCoreApi; address?: string; legacyAddress?: boolean } = {},\n\t) {\n\t\tlet publicKey: ZkLoginPublicIdentifier;\n\n\t\tif (legacyAddress === true) {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, true), {\n\t\t\t\tclient,\n\t\t\t});\n\t\t} else if (legacyAddress === false) {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, false), {\n\t\t\t\tclient,\n\t\t\t});\n\t\t} else if (address) {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, false), {\n\t\t\t\tclient,\n\t\t\t});\n\n\t\t\tif (publicKey.toSuiAddress() !== address) {\n\t\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, true), {\n\t\t\t\t\tclient,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(bytes, {\n\t\t\t\tclient,\n\t\t\t});\n\t\t}\n\n\t\tif (address && publicKey.toSuiAddress() !== address) {\n\t\t\tthrow new Error('Public key bytes do not match the provided address');\n\t\t}\n\n\t\treturn publicKey;\n\t}\n\n\tstatic fromProof(address: string, proof: ZkLoginSignatureInputs) {\n\t\tconst { issBase64Details, addressSeed } = proof;\n\t\tconst iss = extractClaimValue<string>(issBase64Details, 'iss');\n\n\t\tconst legacyPublicKey = toZkLoginPublicIdentifier(BigInt(addressSeed), iss, {\n\t\t\tlegacyAddress: true,\n\t\t});\n\n\t\tif (legacyPublicKey.toSuiAddress() === address) {\n\t\t\treturn legacyPublicKey;\n\t\t}\n\n\t\tconst publicKey = toZkLoginPublicIdentifier(BigInt(addressSeed), iss, {\n\t\t\tlegacyAddress: false,\n\t\t});\n\n\t\tif (publicKey.toSuiAddress() !== address) {\n\t\t\tthrow new Error('Proof does not match address');\n\t\t}\n\n\t\treturn publicKey;\n\t}\n\n\t/**\n\t * Checks if two zkLogin public identifiers are equal\n\t */\n\toverride equals(publicKey: ZkLoginPublicIdentifier): boolean {\n\t\treturn super.equals(publicKey);\n\t}\n\n\toverride toSuiAddress(): string {\n\t\tif (this.#legacyAddress) {\n\t\t\treturn this.#toLegacyAddress();\n\t\t}\n\n\t\treturn super.toSuiAddress();\n\t}\n\n\t#toLegacyAddress() {\n\t\tconst legacyBytes = normalizeZkLoginPublicKeyBytes(this.#data, true);\n\t\tconst addressBytes = new Uint8Array(legacyBytes.length + 1);\n\t\taddressBytes[0] = this.flag();\n\t\taddressBytes.set(legacyBytes, 1);\n\t\treturn normalizeSuiAddress(\n\t\t\tbytesToHex(blake2b(addressBytes, { dkLen: 32 })).slice(0, SUI_ADDRESS_LENGTH * 2),\n\t\t);\n\t}\n\n\t/**\n\t * Return the byte array representation of the zkLogin public identifier\n\t */\n\ttoRawBytes(): Uint8Array<ArrayBuffer> {\n\t\treturn this.#data;\n\t}\n\n\t/**\n\t * Return the Sui address associated with this ZkLogin public identifier\n\t */\n\tflag(): number {\n\t\treturn SIGNATURE_SCHEME_TO_FLAG['ZkLogin'];\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided message\n\t */\n\tasync verify(_message: Uint8Array, _signature: Uint8Array | string): Promise<boolean> {\n\t\tthrow Error('does not support');\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided PersonalMessage\n\t */\n\tverifyPersonalMessage(message: Uint8Array, signature: Uint8Array | string): Promise<boolean> {\n\t\tconst parsedSignature = parseSerializedZkLoginSignature(signature);\n\t\tconst address = new ZkLoginPublicIdentifier(parsedSignature.publicKey).toSuiAddress();\n\n\t\treturn graphqlVerifyZkLoginSignature({\n\t\t\taddress: address,\n\t\t\tbytes: toBase64(message),\n\t\t\tsignature: parsedSignature.serializedSignature,\n\t\t\tintentScope: 'PersonalMessage',\n\t\t\tclient: this.#client,\n\t\t});\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided Transaction\n\t */\n\tverifyTransaction(transaction: Uint8Array, signature: Uint8Array | string): Promise<boolean> {\n\t\tconst parsedSignature = parseSerializedZkLoginSignature(signature);\n\t\tconst address = new ZkLoginPublicIdentifier(parsedSignature.publicKey).toSuiAddress();\n\t\treturn graphqlVerifyZkLoginSignature({\n\t\t\taddress: address,\n\t\t\tbytes: toBase64(transaction),\n\t\t\tsignature: parsedSignature.serializedSignature,\n\t\t\tintentScope: 'TransactionData',\n\t\t\tclient: this.#client,\n\t\t});\n\t}\n\n\t/**\n\t * Verifies that the public key is associated with the provided address\n\t */\n\toverride verifyAddress(address: string): boolean {\n\t\treturn address === super.toSuiAddress() || address === this.#toLegacyAddress();\n\t}\n}\n\n// Derive the public identifier for zklogin based on address seed and iss.\nexport function toZkLoginPublicIdentifier(\n\taddressSeed: bigint,\n\tiss: string,\n\toptions: { client?: ClientWithCoreApi; legacyAddress: boolean },\n): ZkLoginPublicIdentifier {\n\tif (options.legacyAddress === undefined) {\n\t\tthrow new Error('legacyAddress parameter must be specified');\n\t}\n\t// Consists of iss_bytes_len || iss_bytes || padded_32_byte_address_seed.\n\tconst addressSeedBytesBigEndian = options.legacyAddress\n\t\t? toBigEndianBytes(addressSeed, 32)\n\t\t: toPaddedBigEndianBytes(addressSeed, 32);\n\n\tconst issBytes = new TextEncoder().encode(normalizeZkLoginIssuer(iss));\n\tconst tmp = new Uint8Array(1 + issBytes.length + addressSeedBytesBigEndian.length);\n\ttmp.set([issBytes.length], 0);\n\ttmp.set(issBytes, 1);\n\ttmp.set(addressSeedBytesBigEndian, 1 + issBytes.length);\n\treturn new ZkLoginPublicIdentifier(tmp, options);\n}\n\nfunction normalizeZkLoginPublicKeyBytes(bytes: Uint8Array, legacyAddress: boolean) {\n\tconst issByteLength = bytes[0] + 1;\n\tconst addressSeed = BigInt(`0x${toHex(bytes.slice(issByteLength))}`);\n\tconst seedBytes = legacyAddress\n\t\t? toBigEndianBytes(addressSeed, 32)\n\t\t: toPaddedBigEndianBytes(addressSeed, 32);\n\tconst data = new Uint8Array(issByteLength + seedBytes.length);\n\tdata.set(bytes.slice(0, issByteLength), 0);\n\tdata.set(seedBytes, issByteLength);\n\treturn data;\n}\n\nasync function graphqlVerifyZkLoginSignature({\n\taddress,\n\tbytes,\n\tsignature,\n\tintentScope,\n\tclient,\n}: {\n\taddress: string;\n\tbytes: string;\n\tsignature: string;\n\tintentScope: 'PersonalMessage' | 'TransactionData';\n\tclient?: ClientWithCoreApi;\n}) {\n\tif (!client) {\n\t\tthrow new Error(\n\t\t\t'A Sui Client (GRPC, GraphQL, or JSON RPC) is required to verify zkLogin signatures',\n\t\t);\n\t}\n\tconst resp = await client.core.verifyZkLoginSignature({\n\t\tbytes,\n\t\tsignature,\n\t\tintentScope,\n\t\taddress: address,\n\t});\n\n\treturn resp.success === true && resp.errors.length === 0;\n}\n\nexport function parseSerializedZkLoginSignature(signature: Uint8Array | string) {\n\tconst bytes = typeof signature === 'string' ? fromBase64(signature) : signature;\n\n\tif (bytes[0] !== SIGNATURE_SCHEME_TO_FLAG.ZkLogin) {\n\t\tthrow new Error('Invalid signature scheme');\n\t}\n\n\tconst signatureBytes = bytes.slice(1);\n\tconst { inputs, maxEpoch, userSignature } = parseZkLoginSignature(signatureBytes);\n\tconst { issBase64Details, addressSeed } = inputs;\n\tconst iss = extractClaimValue<string>(issBase64Details, 'iss');\n\tconst publicIdentifier = toZkLoginPublicIdentifier(BigInt(addressSeed), iss, {\n\t\tlegacyAddress: false,\n\t});\n\treturn {\n\t\tserializedSignature: toBase64(bytes),\n\t\tsignatureScheme: 'ZkLogin' as const,\n\t\tzkLogin: {\n\t\t\tinputs,\n\t\t\tmaxEpoch,\n\t\t\tuserSignature,\n\t\t\tiss,\n\t\t\taddressSeed: BigInt(addressSeed),\n\t\t},\n\t\tsignature: bytes,\n\t\tpublicKey: publicIdentifier.toRawBytes(),\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"publickey.mjs","names":["#client","#data","#legacyAddress","#toLegacyAddress"],"sources":["../../src/zklogin/publickey.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64, toHex } from '@mysten/bcs';\nimport { blake2b } from '@noble/hashes/blake2.js';\nimport { bytesToHex } from '@noble/hashes/utils.js';\n\nimport { PublicKey } from '../cryptography/publickey.js';\nimport type { PublicKeyInitData } from '../cryptography/publickey.js';\nimport { SIGNATURE_SCHEME_TO_FLAG } from '../cryptography/signature-scheme.js';\nimport { normalizeSuiAddress, SUI_ADDRESS_LENGTH } from '../utils/sui-types.js';\nimport type { ZkLoginSignatureInputs } from './bcs.js';\nimport { extractClaimValue } from './jwt-utils.js';\nimport { parseZkLoginSignature } from './signature.js';\nimport { normalizeZkLoginIssuer, toBigEndianBytes, toPaddedBigEndianBytes } from './utils.js';\nimport type { ClientWithCoreApi } from '../client/core.js';\n\n/**\n * A zkLogin public identifier\n */\nexport class ZkLoginPublicIdentifier extends PublicKey {\n\t#data: Uint8Array<ArrayBuffer>;\n\t#client?: ClientWithCoreApi;\n\t#legacyAddress: boolean;\n\n\t/**\n\t * Create a new ZkLoginPublicIdentifier object\n\t * @param value zkLogin public identifier as buffer or base-64 encoded string\n\t */\n\tconstructor(value: PublicKeyInitData, { client }: { client?: ClientWithCoreApi } = {}) {\n\t\tsuper();\n\n\t\tthis.#client = client;\n\n\t\tif (typeof value === 'string') {\n\t\t\tthis.#data = fromBase64(value);\n\t\t} else if (value instanceof Uint8Array) {\n\t\t\tthis.#data = value as Uint8Array<ArrayBuffer>;\n\t\t} else {\n\t\t\tthis.#data = Uint8Array.from(value);\n\t\t}\n\t\tthis.#legacyAddress = this.#data.length !== this.#data[0] + 1 + 32;\n\n\t\tif (this.#legacyAddress) {\n\t\t\tthis.#data = normalizeZkLoginPublicKeyBytes(this.#data, false);\n\t\t}\n\t}\n\n\t/**\n\t * Whether this identifier resolves to the deprecated legacy address derivation.\n\t */\n\tget legacyAddress(): boolean {\n\t\treturn this.#legacyAddress;\n\t}\n\n\tstatic fromBytes(\n\t\tbytes: Uint8Array,\n\t\t{\n\t\t\tclient,\n\t\t\taddress,\n\t\t\tlegacyAddress,\n\t\t}: { client?: ClientWithCoreApi; address?: string; legacyAddress?: boolean } = {},\n\t) {\n\t\tlet publicKey: ZkLoginPublicIdentifier;\n\n\t\tif (legacyAddress === true) {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, true), {\n\t\t\t\tclient,\n\t\t\t});\n\t\t} else if (legacyAddress === false) {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, false), {\n\t\t\t\tclient,\n\t\t\t});\n\t\t} else if (address) {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, false), {\n\t\t\t\tclient,\n\t\t\t});\n\n\t\t\tif (publicKey.toSuiAddress() !== address) {\n\t\t\t\tpublicKey = new ZkLoginPublicIdentifier(normalizeZkLoginPublicKeyBytes(bytes, true), {\n\t\t\t\t\tclient,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tpublicKey = new ZkLoginPublicIdentifier(bytes, {\n\t\t\t\tclient,\n\t\t\t});\n\t\t}\n\n\t\tif (address && publicKey.toSuiAddress() !== address) {\n\t\t\tthrow new Error('Public key bytes do not match the provided address');\n\t\t}\n\n\t\treturn publicKey;\n\t}\n\n\tstatic fromProof(address: string, proof: ZkLoginSignatureInputs) {\n\t\tconst { issBase64Details, addressSeed } = proof;\n\t\tconst iss = extractClaimValue<string>(issBase64Details, 'iss');\n\n\t\tconst legacyPublicKey = toZkLoginPublicIdentifier(BigInt(addressSeed), iss, {\n\t\t\tlegacyAddress: true,\n\t\t});\n\n\t\tif (legacyPublicKey.toSuiAddress() === address) {\n\t\t\treturn legacyPublicKey;\n\t\t}\n\n\t\tconst publicKey = toZkLoginPublicIdentifier(BigInt(addressSeed), iss, {\n\t\t\tlegacyAddress: false,\n\t\t});\n\n\t\tif (publicKey.toSuiAddress() !== address) {\n\t\t\tthrow new Error('Proof does not match address');\n\t\t}\n\n\t\treturn publicKey;\n\t}\n\n\t/**\n\t * Checks if two zkLogin public identifiers are equal\n\t */\n\toverride equals(publicKey: ZkLoginPublicIdentifier): boolean {\n\t\treturn super.equals(publicKey);\n\t}\n\n\toverride toSuiAddress(): string {\n\t\tif (this.#legacyAddress) {\n\t\t\treturn this.#toLegacyAddress();\n\t\t}\n\n\t\treturn super.toSuiAddress();\n\t}\n\n\t#toLegacyAddress() {\n\t\tconst legacyBytes = normalizeZkLoginPublicKeyBytes(this.#data, true);\n\t\tconst addressBytes = new Uint8Array(legacyBytes.length + 1);\n\t\taddressBytes[0] = this.flag();\n\t\taddressBytes.set(legacyBytes, 1);\n\t\treturn normalizeSuiAddress(\n\t\t\tbytesToHex(blake2b(addressBytes, { dkLen: 32 })).slice(0, SUI_ADDRESS_LENGTH * 2),\n\t\t);\n\t}\n\n\t/**\n\t * Return the byte array representation of the zkLogin public identifier\n\t */\n\ttoRawBytes(): Uint8Array<ArrayBuffer> {\n\t\treturn this.#data;\n\t}\n\n\t/**\n\t * Return the Sui address associated with this ZkLogin public identifier\n\t */\n\tflag(): number {\n\t\treturn SIGNATURE_SCHEME_TO_FLAG['ZkLogin'];\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided message\n\t */\n\tasync verify(_message: Uint8Array, _signature: Uint8Array | string): Promise<boolean> {\n\t\tthrow Error('does not support');\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided PersonalMessage\n\t */\n\tverifyPersonalMessage(message: Uint8Array, signature: Uint8Array | string): Promise<boolean> {\n\t\tconst parsedSignature = parseSerializedZkLoginSignature(signature);\n\t\tconst address = new ZkLoginPublicIdentifier(parsedSignature.publicKey).toSuiAddress();\n\n\t\treturn graphqlVerifyZkLoginSignature({\n\t\t\taddress: address,\n\t\t\tbytes: toBase64(message),\n\t\t\tsignature: parsedSignature.serializedSignature,\n\t\t\tintentScope: 'PersonalMessage',\n\t\t\tclient: this.#client,\n\t\t});\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided Transaction\n\t */\n\tverifyTransaction(transaction: Uint8Array, signature: Uint8Array | string): Promise<boolean> {\n\t\tconst parsedSignature = parseSerializedZkLoginSignature(signature);\n\t\tconst address = new ZkLoginPublicIdentifier(parsedSignature.publicKey).toSuiAddress();\n\t\treturn graphqlVerifyZkLoginSignature({\n\t\t\taddress: address,\n\t\t\tbytes: toBase64(transaction),\n\t\t\tsignature: parsedSignature.serializedSignature,\n\t\t\tintentScope: 'TransactionData',\n\t\t\tclient: this.#client,\n\t\t});\n\t}\n\n\t/**\n\t * Verifies that the public key is associated with the provided address\n\t */\n\toverride verifyAddress(address: string): boolean {\n\t\treturn address === super.toSuiAddress() || address === this.#toLegacyAddress();\n\t}\n}\n\n// Derive the public identifier for zklogin based on address seed and iss.\nexport function toZkLoginPublicIdentifier(\n\taddressSeed: bigint,\n\tiss: string,\n\toptions: { client?: ClientWithCoreApi; legacyAddress: boolean },\n): ZkLoginPublicIdentifier {\n\tif (options.legacyAddress === undefined) {\n\t\tthrow new Error('legacyAddress parameter must be specified');\n\t}\n\t// Consists of iss_bytes_len || iss_bytes || padded_32_byte_address_seed.\n\tconst addressSeedBytesBigEndian = options.legacyAddress\n\t\t? toBigEndianBytes(addressSeed, 32)\n\t\t: toPaddedBigEndianBytes(addressSeed, 32);\n\n\tconst issBytes = new TextEncoder().encode(normalizeZkLoginIssuer(iss));\n\tconst tmp = new Uint8Array(1 + issBytes.length + addressSeedBytesBigEndian.length);\n\ttmp.set([issBytes.length], 0);\n\ttmp.set(issBytes, 1);\n\ttmp.set(addressSeedBytesBigEndian, 1 + issBytes.length);\n\treturn new ZkLoginPublicIdentifier(tmp, options);\n}\n\nfunction normalizeZkLoginPublicKeyBytes(bytes: Uint8Array, legacyAddress: boolean) {\n\tconst issByteLength = bytes[0] + 1;\n\tconst addressSeed = BigInt(`0x${toHex(bytes.slice(issByteLength))}`);\n\tconst seedBytes = legacyAddress\n\t\t? toBigEndianBytes(addressSeed, 32)\n\t\t: toPaddedBigEndianBytes(addressSeed, 32);\n\tconst data = new Uint8Array(issByteLength + seedBytes.length);\n\tdata.set(bytes.slice(0, issByteLength), 0);\n\tdata.set(seedBytes, issByteLength);\n\treturn data;\n}\n\nasync function graphqlVerifyZkLoginSignature({\n\taddress,\n\tbytes,\n\tsignature,\n\tintentScope,\n\tclient,\n}: {\n\taddress: string;\n\tbytes: string;\n\tsignature: string;\n\tintentScope: 'PersonalMessage' | 'TransactionData';\n\tclient?: ClientWithCoreApi;\n}) {\n\tif (!client) {\n\t\tthrow new Error(\n\t\t\t'A Sui Client (GRPC, GraphQL, or JSON RPC) is required to verify zkLogin signatures',\n\t\t);\n\t}\n\tconst resp = await client.core.verifyZkLoginSignature({\n\t\tbytes,\n\t\tsignature,\n\t\tintentScope,\n\t\taddress: address,\n\t});\n\n\treturn resp.success === true && resp.errors.length === 0;\n}\n\nexport function parseSerializedZkLoginSignature(signature: Uint8Array | string) {\n\tconst bytes = typeof signature === 'string' ? fromBase64(signature) : signature;\n\n\tif (bytes[0] !== SIGNATURE_SCHEME_TO_FLAG.ZkLogin) {\n\t\tthrow new Error('Invalid signature scheme');\n\t}\n\n\tconst signatureBytes = bytes.slice(1);\n\tconst { inputs, maxEpoch, userSignature } = parseZkLoginSignature(signatureBytes);\n\tconst { issBase64Details, addressSeed } = inputs;\n\tconst iss = extractClaimValue<string>(issBase64Details, 'iss');\n\tconst publicIdentifier = toZkLoginPublicIdentifier(BigInt(addressSeed), iss, {\n\t\tlegacyAddress: false,\n\t});\n\treturn {\n\t\tserializedSignature: toBase64(bytes),\n\t\tsignatureScheme: 'ZkLogin' as const,\n\t\tzkLogin: {\n\t\t\tinputs,\n\t\t\tmaxEpoch,\n\t\t\tuserSignature,\n\t\t\tiss,\n\t\t\taddressSeed: BigInt(addressSeed),\n\t\t},\n\t\tsignature: bytes,\n\t\tpublicKey: publicIdentifier.toRawBytes(),\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { IntentScope } from "../cryptography/intent.mjs";
|
|
2
|
+
import { SignatureScheme } from "../cryptography/signature-scheme.mjs";
|
|
3
|
+
import { SignatureWithBytes, Signer } from "../cryptography/keypair.mjs";
|
|
4
|
+
import { ClientWithCoreApi } from "../client/core.mjs";
|
|
5
|
+
import { ZkLoginSignatureInputs } from "./bcs.mjs";
|
|
6
|
+
import { ZkLoginPublicIdentifier } from "./publickey.mjs";
|
|
7
|
+
|
|
8
|
+
//#region src/zklogin/signer.d.ts
|
|
9
|
+
interface ZkLoginSignerOptions {
|
|
10
|
+
/** The ephemeral signer whose signature is wrapped by the zkLogin proof. */
|
|
11
|
+
ephemeralSigner: Signer;
|
|
12
|
+
/** The maxEpoch the proof was generated for. */
|
|
13
|
+
maxEpoch: number;
|
|
14
|
+
/** The zkLogin proof inputs, including the `addressSeed`. */
|
|
15
|
+
inputs: ZkLoginSignatureInputs;
|
|
16
|
+
/**
|
|
17
|
+
* Whether this account uses the deprecated legacy address derivation. The zkLogin address is
|
|
18
|
+
* derived from the proof inputs; this flag disambiguates legacy vs. current derivation, matching
|
|
19
|
+
* the rest of the zkLogin address API (e.g. `jwtToAddress`, `toZkLoginPublicIdentifier`).
|
|
20
|
+
*
|
|
21
|
+
* A wrong flag silently yields a signer for the wrong address; pass `address` to guard against it.
|
|
22
|
+
*/
|
|
23
|
+
legacyAddress: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* The expected zkLogin address. When provided, the address derived from `inputs` + `legacyAddress`
|
|
26
|
+
* is validated against it and the constructor throws on mismatch — guarding against a wrong
|
|
27
|
+
* `legacyAddress` flag producing a signer for the wrong address.
|
|
28
|
+
*/
|
|
29
|
+
address?: string;
|
|
30
|
+
/** Optional client, threaded into the derived public key so it can verify signatures. */
|
|
31
|
+
client?: ClientWithCoreApi;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A transport- and provider-agnostic zkLogin signer.
|
|
35
|
+
*
|
|
36
|
+
* It wraps any ephemeral {@link Signer} and, for every signing operation, transforms the ephemeral
|
|
37
|
+
* signature into a zkLogin signature using the supplied proof inputs and `maxEpoch`. Because every
|
|
38
|
+
* signing method on {@link Signer} funnels through `signWithIntent`, overriding that single method is
|
|
39
|
+
* enough to cover `signTransaction`, `signPersonalMessage`, and `signAndExecuteTransaction`.
|
|
40
|
+
*/
|
|
41
|
+
declare class ZkLoginSigner extends Signer {
|
|
42
|
+
#private;
|
|
43
|
+
constructor(options: ZkLoginSignerOptions);
|
|
44
|
+
/**
|
|
45
|
+
* The single extension point: the ephemeral signature is produced with the requested intent and
|
|
46
|
+
* then wrapped in a zkLogin signature.
|
|
47
|
+
*/
|
|
48
|
+
signWithIntent(bytes: Uint8Array, intent: IntentScope): Promise<SignatureWithBytes>;
|
|
49
|
+
sign(_data: Uint8Array): never;
|
|
50
|
+
getKeyScheme(): SignatureScheme;
|
|
51
|
+
getPublicKey(): ZkLoginPublicIdentifier;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { ZkLoginSigner, ZkLoginSignerOptions };
|
|
55
|
+
//# sourceMappingURL=signer.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.d.mts","names":[],"sources":["../../src/zklogin/signer.ts"],"mappings":";;;;;;;;UAaiB,oBAAA;EAAA;EAEhB,eAAA,EAAiB,MAAA;;EAEjB,QAAA;EAEQ;EAAR,MAAA,EAAQ,sBAAA;EAgBkB;;;;;;;EAR1B,aAAA;EAMA;;;;;EAAA,OAAA;EAa0B;EAX1B,MAAA,GAAS,iBAAA;AAAA;;;;;;;;;cAWG,aAAA,SAAsB,MAAA;EAAA;cAQtB,OAAA,EAAS,oBAAA;;;;;EAoCN,cAAA,CACd,KAAA,EAAO,UAAA,EACP,MAAA,EAAQ,WAAA,GACN,OAAA,CAAQ,kBAAA;EAcX,IAAA,CAAK,KAAA,EAAO,UAAA;EAMZ,YAAA,CAAA,GAAgB,eAAA;EAIhB,YAAA,CAAA,GAAgB,uBAAA;AAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { extractClaimValue } from "./jwt-utils.mjs";
|
|
2
|
+
import { getZkLoginSignature } from "./signature.mjs";
|
|
3
|
+
import { toZkLoginPublicIdentifier } from "./publickey.mjs";
|
|
4
|
+
import { Signer } from "../cryptography/keypair.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/zklogin/signer.ts
|
|
7
|
+
/**
|
|
8
|
+
* A transport- and provider-agnostic zkLogin signer.
|
|
9
|
+
*
|
|
10
|
+
* It wraps any ephemeral {@link Signer} and, for every signing operation, transforms the ephemeral
|
|
11
|
+
* signature into a zkLogin signature using the supplied proof inputs and `maxEpoch`. Because every
|
|
12
|
+
* signing method on {@link Signer} funnels through `signWithIntent`, overriding that single method is
|
|
13
|
+
* enough to cover `signTransaction`, `signPersonalMessage`, and `signAndExecuteTransaction`.
|
|
14
|
+
*/
|
|
15
|
+
var ZkLoginSigner = class extends Signer {
|
|
16
|
+
#ephemeralSigner;
|
|
17
|
+
#maxEpoch;
|
|
18
|
+
#inputs;
|
|
19
|
+
#legacyAddress;
|
|
20
|
+
#client;
|
|
21
|
+
#publicKey;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
super();
|
|
24
|
+
this.#ephemeralSigner = options.ephemeralSigner;
|
|
25
|
+
this.#maxEpoch = options.maxEpoch;
|
|
26
|
+
this.#inputs = options.inputs;
|
|
27
|
+
this.#legacyAddress = options.legacyAddress;
|
|
28
|
+
this.#client = options.client;
|
|
29
|
+
if (options.address !== void 0) {
|
|
30
|
+
const derived = this.#derivePublicKey().toSuiAddress();
|
|
31
|
+
if (derived !== options.address) throw new Error(`zkLogin proof does not match the provided address (derived ${derived}, expected ${options.address}) — check the \`legacyAddress\` flag`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
#derivePublicKey() {
|
|
35
|
+
return this.#publicKey ??= toZkLoginPublicIdentifier(BigInt(this.#inputs.addressSeed), extractClaimValue(this.#inputs.issBase64Details, "iss"), {
|
|
36
|
+
legacyAddress: this.#legacyAddress,
|
|
37
|
+
client: this.#client
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The single extension point: the ephemeral signature is produced with the requested intent and
|
|
42
|
+
* then wrapped in a zkLogin signature.
|
|
43
|
+
*/
|
|
44
|
+
async signWithIntent(bytes, intent) {
|
|
45
|
+
const { bytes: signedBytes, signature: userSignature } = await this.#ephemeralSigner.signWithIntent(bytes, intent);
|
|
46
|
+
return {
|
|
47
|
+
bytes: signedBytes,
|
|
48
|
+
signature: getZkLoginSignature({
|
|
49
|
+
inputs: this.#inputs,
|
|
50
|
+
maxEpoch: this.#maxEpoch,
|
|
51
|
+
userSignature
|
|
52
|
+
})
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
sign(_data) {
|
|
56
|
+
throw new Error("ZkLoginSigner does not support signing directly. Use signTransaction or signPersonalMessage instead");
|
|
57
|
+
}
|
|
58
|
+
getKeyScheme() {
|
|
59
|
+
return "ZkLogin";
|
|
60
|
+
}
|
|
61
|
+
getPublicKey() {
|
|
62
|
+
return this.#derivePublicKey();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { ZkLoginSigner };
|
|
68
|
+
//# sourceMappingURL=signer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.mjs","names":["#ephemeralSigner","#maxEpoch","#inputs","#legacyAddress","#client","#derivePublicKey","#publicKey"],"sources":["../../src/zklogin/signer.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '../client/core.js';\nimport type { IntentScope } from '../cryptography/intent.js';\nimport type { SignatureWithBytes } from '../cryptography/keypair.js';\nimport { Signer } from '../cryptography/keypair.js';\nimport type { SignatureScheme } from '../cryptography/signature-scheme.js';\nimport type { ZkLoginSignatureInputs } from './bcs.js';\nimport { extractClaimValue } from './jwt-utils.js';\nimport { toZkLoginPublicIdentifier, ZkLoginPublicIdentifier } from './publickey.js';\nimport { getZkLoginSignature } from './signature.js';\n\nexport interface ZkLoginSignerOptions {\n\t/** The ephemeral signer whose signature is wrapped by the zkLogin proof. */\n\tephemeralSigner: Signer;\n\t/** The maxEpoch the proof was generated for. */\n\tmaxEpoch: number;\n\t/** The zkLogin proof inputs, including the `addressSeed`. */\n\tinputs: ZkLoginSignatureInputs;\n\t/**\n\t * Whether this account uses the deprecated legacy address derivation. The zkLogin address is\n\t * derived from the proof inputs; this flag disambiguates legacy vs. current derivation, matching\n\t * the rest of the zkLogin address API (e.g. `jwtToAddress`, `toZkLoginPublicIdentifier`).\n\t *\n\t * A wrong flag silently yields a signer for the wrong address; pass `address` to guard against it.\n\t */\n\tlegacyAddress: boolean;\n\t/**\n\t * The expected zkLogin address. When provided, the address derived from `inputs` + `legacyAddress`\n\t * is validated against it and the constructor throws on mismatch — guarding against a wrong\n\t * `legacyAddress` flag producing a signer for the wrong address.\n\t */\n\taddress?: string;\n\t/** Optional client, threaded into the derived public key so it can verify signatures. */\n\tclient?: ClientWithCoreApi;\n}\n\n/**\n * A transport- and provider-agnostic zkLogin signer.\n *\n * It wraps any ephemeral {@link Signer} and, for every signing operation, transforms the ephemeral\n * signature into a zkLogin signature using the supplied proof inputs and `maxEpoch`. Because every\n * signing method on {@link Signer} funnels through `signWithIntent`, overriding that single method is\n * enough to cover `signTransaction`, `signPersonalMessage`, and `signAndExecuteTransaction`.\n */\nexport class ZkLoginSigner extends Signer {\n\t#ephemeralSigner: Signer;\n\t#maxEpoch: number;\n\t#inputs: ZkLoginSignatureInputs;\n\t#legacyAddress: boolean;\n\t#client?: ClientWithCoreApi;\n\t#publicKey?: ZkLoginPublicIdentifier;\n\n\tconstructor(options: ZkLoginSignerOptions) {\n\t\tsuper();\n\t\tthis.#ephemeralSigner = options.ephemeralSigner;\n\t\tthis.#maxEpoch = options.maxEpoch;\n\t\tthis.#inputs = options.inputs;\n\t\tthis.#legacyAddress = options.legacyAddress;\n\t\tthis.#client = options.client;\n\n\t\tif (options.address !== undefined) {\n\t\t\tconst derived = this.#derivePublicKey().toSuiAddress();\n\t\t\tif (derived !== options.address) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`zkLogin proof does not match the provided address (derived ${derived}, expected ` +\n\t\t\t\t\t\t`${options.address}) — check the \\`legacyAddress\\` flag`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Shared derive-and-memoize used by both the constructor's address validation and getPublicKey().\n\t// It is `#private` (non-virtual) on purpose: the constructor must derive the *base* address even\n\t// when a subclass overrides getPublicKey() — calling the overridable getPublicKey() from the\n\t// constructor would dispatch to the subclass before its fields are initialized. Laziness also\n\t// means subclasses that override getPublicKey() (e.g. EnokiKeypair) never pay for this derivation.\n\t#derivePublicKey(): ZkLoginPublicIdentifier {\n\t\treturn (this.#publicKey ??= toZkLoginPublicIdentifier(\n\t\t\tBigInt(this.#inputs.addressSeed),\n\t\t\textractClaimValue<string>(this.#inputs.issBase64Details, 'iss'),\n\t\t\t{ legacyAddress: this.#legacyAddress, client: this.#client },\n\t\t));\n\t}\n\n\t/**\n\t * The single extension point: the ephemeral signature is produced with the requested intent and\n\t * then wrapped in a zkLogin signature.\n\t */\n\toverride async signWithIntent(\n\t\tbytes: Uint8Array,\n\t\tintent: IntentScope,\n\t): Promise<SignatureWithBytes> {\n\t\tconst { bytes: signedBytes, signature: userSignature } =\n\t\t\tawait this.#ephemeralSigner.signWithIntent(bytes, intent);\n\n\t\treturn {\n\t\t\tbytes: signedBytes,\n\t\t\tsignature: getZkLoginSignature({\n\t\t\t\tinputs: this.#inputs,\n\t\t\t\tmaxEpoch: this.#maxEpoch,\n\t\t\t\tuserSignature,\n\t\t\t}),\n\t\t};\n\t}\n\n\tsign(_data: Uint8Array): never {\n\t\tthrow new Error(\n\t\t\t'ZkLoginSigner does not support signing directly. Use signTransaction or signPersonalMessage instead',\n\t\t);\n\t}\n\n\tgetKeyScheme(): SignatureScheme {\n\t\treturn 'ZkLogin';\n\t}\n\n\tgetPublicKey(): ZkLoginPublicIdentifier {\n\t\treturn this.#derivePublicKey();\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AA8CA,IAAa,gBAAb,cAAmC,OAAO;CACzC;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAA+B;AAC1C,SAAO;AACP,QAAKA,kBAAmB,QAAQ;AAChC,QAAKC,WAAY,QAAQ;AACzB,QAAKC,SAAU,QAAQ;AACvB,QAAKC,gBAAiB,QAAQ;AAC9B,QAAKC,SAAU,QAAQ;AAEvB,MAAI,QAAQ,YAAY,QAAW;GAClC,MAAM,UAAU,MAAKC,iBAAkB,CAAC,cAAc;AACtD,OAAI,YAAY,QAAQ,QACvB,OAAM,IAAI,MACT,8DAA8D,QAAQ,aAClE,QAAQ,QAAQ,sCACpB;;;CAUJ,mBAA4C;AAC3C,SAAQ,MAAKC,cAAe,0BAC3B,OAAO,MAAKJ,OAAQ,YAAY,EAChC,kBAA0B,MAAKA,OAAQ,kBAAkB,MAAM,EAC/D;GAAE,eAAe,MAAKC;GAAgB,QAAQ,MAAKC;GAAS,CAC5D;;;;;;CAOF,MAAe,eACd,OACA,QAC8B;EAC9B,MAAM,EAAE,OAAO,aAAa,WAAW,kBACtC,MAAM,MAAKJ,gBAAiB,eAAe,OAAO,OAAO;AAE1D,SAAO;GACN,OAAO;GACP,WAAW,oBAAoB;IAC9B,QAAQ,MAAKE;IACb,UAAU,MAAKD;IACf;IACA,CAAC;GACF;;CAGF,KAAK,OAA0B;AAC9B,QAAM,IAAI,MACT,sGACA;;CAGF,eAAgC;AAC/B,SAAO;;CAGR,eAAwC;AACvC,SAAO,MAAKI,iBAAkB"}
|
|
@@ -185,7 +185,11 @@ The built-in mutation hooks have been removed. Use TanStack Query's `useMutation
|
|
|
185
185
|
|
|
186
186
|
In the old dApp kit, you could optionally pass a `chain` parameter (for example, `sui:mainnet`) to
|
|
187
187
|
methods like `signTransaction` and `signAndExecuteTransaction`. In the new dApp kit, use the
|
|
188
|
-
`network` parameter instead - the chain is automatically derived from the network.
|
|
188
|
+
`network` parameter instead - the chain is automatically derived from the network. It is optional
|
|
189
|
+
and defaults to the active network, so you only need it when targeting a network other than the
|
|
190
|
+
active one (for example, an app that operates on both mainnet and testnet). Likewise, the
|
|
191
|
+
per-account `account` override is preserved as an optional parameter that defaults to the connected
|
|
192
|
+
account.
|
|
189
193
|
|
|
190
194
|
```diff
|
|
191
195
|
- const { mutateAsync: signAndExecute } = useSignAndExecuteTransaction();
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Mysten Labs <build@mystenlabs.com>",
|
|
4
4
|
"description": "Sui TypeScript API",
|
|
5
5
|
"homepage": "https://sdk.mystenlabs.com",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.20.0",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"files": [
|
|
@@ -168,8 +168,8 @@
|
|
|
168
168
|
"graphql": "^16.14.2",
|
|
169
169
|
"poseidon-lite": "0.2.1",
|
|
170
170
|
"valibot": "^1.4.1",
|
|
171
|
-
"@mysten/
|
|
172
|
-
"@mysten/
|
|
171
|
+
"@mysten/bcs": "^2.1.0",
|
|
172
|
+
"@mysten/utils": "^0.4.0"
|
|
173
173
|
},
|
|
174
174
|
"scripts": {
|
|
175
175
|
"clean": "rm -rf tsconfig.tsbuildinfo ./dist",
|
package/src/verify/index.ts
CHANGED
package/src/verify/verify.ts
CHANGED
|
@@ -13,24 +13,65 @@ import { MultiSigPublicKey } from '../multisig/publickey.js';
|
|
|
13
13
|
import { ZkLoginPublicIdentifier } from '../zklogin/publickey.js';
|
|
14
14
|
import type { ClientWithCoreApi } from '../client/core.js';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Whether `signature` is a valid signature over `bytes` (and, if `options.address`
|
|
18
|
+
* is given, was produced by that address). Returns `false` for a malformed or
|
|
19
|
+
* cryptographically invalid signature, or one that doesn't match the address;
|
|
20
|
+
* only an *environmental* failure (e.g. a zkLogin JWK/epoch lookup) throws, so a
|
|
21
|
+
* network blip is never reported as an invalid signature.
|
|
22
|
+
*/
|
|
23
|
+
export async function isValidSignature(
|
|
24
|
+
bytes: Uint8Array,
|
|
25
|
+
signature: string,
|
|
26
|
+
options: { address?: string } = {},
|
|
27
|
+
): Promise<boolean> {
|
|
28
|
+
const parsed = tryParseSignature(signature);
|
|
29
|
+
if (!parsed) return false;
|
|
30
|
+
if (!(await parsed.publicKey.verify(bytes, parsed.serializedSignature))) return false;
|
|
31
|
+
return options.address ? parsed.publicKey.verifyAddress(options.address) : true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Like {@link isValidSignature}, for a personal message. */
|
|
35
|
+
export async function isValidPersonalMessageSignature(
|
|
36
|
+
message: Uint8Array,
|
|
37
|
+
signature: string,
|
|
38
|
+
options: { client?: ClientWithCoreApi; address?: string } = {},
|
|
39
|
+
): Promise<boolean> {
|
|
40
|
+
const parsed = tryParseSignature(signature, { client: options.client });
|
|
41
|
+
if (!parsed) return false;
|
|
42
|
+
if (!(await parsed.publicKey.verifyPersonalMessage(message, parsed.serializedSignature))) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return options.address ? parsed.publicKey.verifyAddress(options.address) : true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Like {@link isValidSignature}, for transaction bytes. */
|
|
49
|
+
export async function isValidTransactionSignature(
|
|
50
|
+
transaction: Uint8Array,
|
|
51
|
+
signature: string,
|
|
52
|
+
options: { client?: ClientWithCoreApi; address?: string } = {},
|
|
53
|
+
): Promise<boolean> {
|
|
54
|
+
const parsed = tryParseSignature(signature, { client: options.client });
|
|
55
|
+
if (!parsed) return false;
|
|
56
|
+
if (!(await parsed.publicKey.verifyTransaction(transaction, parsed.serializedSignature))) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return options.address ? parsed.publicKey.verifyAddress(options.address) : true;
|
|
60
|
+
}
|
|
61
|
+
|
|
16
62
|
export async function verifySignature(
|
|
17
63
|
bytes: Uint8Array,
|
|
18
64
|
signature: string,
|
|
19
|
-
options?: {
|
|
20
|
-
address?: string;
|
|
21
|
-
},
|
|
65
|
+
options: { address?: string } = {},
|
|
22
66
|
): Promise<PublicKey> {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
if (!(await parsedSignature.publicKey.verify(bytes, parsedSignature.serializedSignature))) {
|
|
67
|
+
const { publicKey } = parseSignature(signature);
|
|
68
|
+
if (!(await isValidSignature(bytes, signature))) {
|
|
26
69
|
throw new Error(`Signature is not valid for the provided data`);
|
|
27
70
|
}
|
|
28
|
-
|
|
29
|
-
if (options?.address && !parsedSignature.publicKey.verifyAddress(options.address)) {
|
|
71
|
+
if (options.address && !publicKey.verifyAddress(options.address)) {
|
|
30
72
|
throw new Error(`Signature is not valid for the provided address`);
|
|
31
73
|
}
|
|
32
|
-
|
|
33
|
-
return parsedSignature.publicKey;
|
|
74
|
+
return publicKey;
|
|
34
75
|
}
|
|
35
76
|
|
|
36
77
|
export async function verifyPersonalMessageSignature(
|
|
@@ -38,22 +79,14 @@ export async function verifyPersonalMessageSignature(
|
|
|
38
79
|
signature: string,
|
|
39
80
|
options: { client?: ClientWithCoreApi; address?: string } = {},
|
|
40
81
|
): Promise<PublicKey> {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
!(await parsedSignature.publicKey.verifyPersonalMessage(
|
|
45
|
-
message,
|
|
46
|
-
parsedSignature.serializedSignature,
|
|
47
|
-
))
|
|
48
|
-
) {
|
|
82
|
+
const { publicKey } = parseSignature(signature, options);
|
|
83
|
+
if (!(await isValidPersonalMessageSignature(message, signature, { client: options.client }))) {
|
|
49
84
|
throw new Error(`Signature is not valid for the provided message`);
|
|
50
85
|
}
|
|
51
|
-
|
|
52
|
-
if (options?.address && !parsedSignature.publicKey.verifyAddress(options.address)) {
|
|
86
|
+
if (options.address && !publicKey.verifyAddress(options.address)) {
|
|
53
87
|
throw new Error(`Signature is not valid for the provided address`);
|
|
54
88
|
}
|
|
55
|
-
|
|
56
|
-
return parsedSignature.publicKey;
|
|
89
|
+
return publicKey;
|
|
57
90
|
}
|
|
58
91
|
|
|
59
92
|
export async function verifyTransactionSignature(
|
|
@@ -61,22 +94,14 @@ export async function verifyTransactionSignature(
|
|
|
61
94
|
signature: string,
|
|
62
95
|
options: { client?: ClientWithCoreApi; address?: string } = {},
|
|
63
96
|
): Promise<PublicKey> {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
!(await parsedSignature.publicKey.verifyTransaction(
|
|
68
|
-
transaction,
|
|
69
|
-
parsedSignature.serializedSignature,
|
|
70
|
-
))
|
|
71
|
-
) {
|
|
97
|
+
const { publicKey } = parseSignature(signature, options);
|
|
98
|
+
if (!(await isValidTransactionSignature(transaction, signature, { client: options.client }))) {
|
|
72
99
|
throw new Error(`Signature is not valid for the provided Transaction`);
|
|
73
100
|
}
|
|
74
|
-
|
|
75
|
-
if (options?.address && !parsedSignature.publicKey.verifyAddress(options.address)) {
|
|
101
|
+
if (options.address && !publicKey.verifyAddress(options.address)) {
|
|
76
102
|
throw new Error(`Signature is not valid for the provided address`);
|
|
77
103
|
}
|
|
78
|
-
|
|
79
|
-
return parsedSignature.publicKey;
|
|
104
|
+
return publicKey;
|
|
80
105
|
}
|
|
81
106
|
|
|
82
107
|
function parseSignature(signature: string, options: { client?: ClientWithCoreApi } = {}) {
|
|
@@ -100,6 +125,15 @@ function parseSignature(signature: string, options: { client?: ClientWithCoreApi
|
|
|
100
125
|
};
|
|
101
126
|
}
|
|
102
127
|
|
|
128
|
+
/** {@link parseSignature}, returning `null` instead of throwing on a malformed signature. */
|
|
129
|
+
function tryParseSignature(signature: string, options: { client?: ClientWithCoreApi } = {}) {
|
|
130
|
+
try {
|
|
131
|
+
return parseSignature(signature, options);
|
|
132
|
+
} catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
103
137
|
export function publicKeyFromRawBytes(
|
|
104
138
|
signatureScheme: SignatureScheme,
|
|
105
139
|
bytes: Uint8Array,
|
package/src/version.ts
CHANGED
package/src/zklogin/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export {
|
|
|
12
12
|
export { computeZkLoginAddressFromSeed, computeZkLoginAddress, jwtToAddress } from './address.js';
|
|
13
13
|
export type { ComputeZkLoginAddressOptions } from './address.js';
|
|
14
14
|
export { toZkLoginPublicIdentifier, ZkLoginPublicIdentifier } from './publickey.js';
|
|
15
|
+
export { ZkLoginSigner } from './signer.js';
|
|
16
|
+
export type { ZkLoginSignerOptions } from './signer.js';
|
|
15
17
|
export type { ZkLoginSignatureInputs } from './bcs.js';
|
|
16
18
|
export { poseidonHash } from './poseidon.js';
|
|
17
19
|
export { generateNonce, generateRandomness } from './nonce.js';
|
package/src/zklogin/publickey.ts
CHANGED
|
@@ -46,6 +46,13 @@ export class ZkLoginPublicIdentifier extends PublicKey {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Whether this identifier resolves to the deprecated legacy address derivation.
|
|
51
|
+
*/
|
|
52
|
+
get legacyAddress(): boolean {
|
|
53
|
+
return this.#legacyAddress;
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
static fromBytes(
|
|
50
57
|
bytes: Uint8Array,
|
|
51
58
|
{
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { ClientWithCoreApi } from '../client/core.js';
|
|
5
|
+
import type { IntentScope } from '../cryptography/intent.js';
|
|
6
|
+
import type { SignatureWithBytes } from '../cryptography/keypair.js';
|
|
7
|
+
import { Signer } from '../cryptography/keypair.js';
|
|
8
|
+
import type { SignatureScheme } from '../cryptography/signature-scheme.js';
|
|
9
|
+
import type { ZkLoginSignatureInputs } from './bcs.js';
|
|
10
|
+
import { extractClaimValue } from './jwt-utils.js';
|
|
11
|
+
import { toZkLoginPublicIdentifier, ZkLoginPublicIdentifier } from './publickey.js';
|
|
12
|
+
import { getZkLoginSignature } from './signature.js';
|
|
13
|
+
|
|
14
|
+
export interface ZkLoginSignerOptions {
|
|
15
|
+
/** The ephemeral signer whose signature is wrapped by the zkLogin proof. */
|
|
16
|
+
ephemeralSigner: Signer;
|
|
17
|
+
/** The maxEpoch the proof was generated for. */
|
|
18
|
+
maxEpoch: number;
|
|
19
|
+
/** The zkLogin proof inputs, including the `addressSeed`. */
|
|
20
|
+
inputs: ZkLoginSignatureInputs;
|
|
21
|
+
/**
|
|
22
|
+
* Whether this account uses the deprecated legacy address derivation. The zkLogin address is
|
|
23
|
+
* derived from the proof inputs; this flag disambiguates legacy vs. current derivation, matching
|
|
24
|
+
* the rest of the zkLogin address API (e.g. `jwtToAddress`, `toZkLoginPublicIdentifier`).
|
|
25
|
+
*
|
|
26
|
+
* A wrong flag silently yields a signer for the wrong address; pass `address` to guard against it.
|
|
27
|
+
*/
|
|
28
|
+
legacyAddress: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* The expected zkLogin address. When provided, the address derived from `inputs` + `legacyAddress`
|
|
31
|
+
* is validated against it and the constructor throws on mismatch — guarding against a wrong
|
|
32
|
+
* `legacyAddress` flag producing a signer for the wrong address.
|
|
33
|
+
*/
|
|
34
|
+
address?: string;
|
|
35
|
+
/** Optional client, threaded into the derived public key so it can verify signatures. */
|
|
36
|
+
client?: ClientWithCoreApi;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A transport- and provider-agnostic zkLogin signer.
|
|
41
|
+
*
|
|
42
|
+
* It wraps any ephemeral {@link Signer} and, for every signing operation, transforms the ephemeral
|
|
43
|
+
* signature into a zkLogin signature using the supplied proof inputs and `maxEpoch`. Because every
|
|
44
|
+
* signing method on {@link Signer} funnels through `signWithIntent`, overriding that single method is
|
|
45
|
+
* enough to cover `signTransaction`, `signPersonalMessage`, and `signAndExecuteTransaction`.
|
|
46
|
+
*/
|
|
47
|
+
export class ZkLoginSigner extends Signer {
|
|
48
|
+
#ephemeralSigner: Signer;
|
|
49
|
+
#maxEpoch: number;
|
|
50
|
+
#inputs: ZkLoginSignatureInputs;
|
|
51
|
+
#legacyAddress: boolean;
|
|
52
|
+
#client?: ClientWithCoreApi;
|
|
53
|
+
#publicKey?: ZkLoginPublicIdentifier;
|
|
54
|
+
|
|
55
|
+
constructor(options: ZkLoginSignerOptions) {
|
|
56
|
+
super();
|
|
57
|
+
this.#ephemeralSigner = options.ephemeralSigner;
|
|
58
|
+
this.#maxEpoch = options.maxEpoch;
|
|
59
|
+
this.#inputs = options.inputs;
|
|
60
|
+
this.#legacyAddress = options.legacyAddress;
|
|
61
|
+
this.#client = options.client;
|
|
62
|
+
|
|
63
|
+
if (options.address !== undefined) {
|
|
64
|
+
const derived = this.#derivePublicKey().toSuiAddress();
|
|
65
|
+
if (derived !== options.address) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`zkLogin proof does not match the provided address (derived ${derived}, expected ` +
|
|
68
|
+
`${options.address}) — check the \`legacyAddress\` flag`,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Shared derive-and-memoize used by both the constructor's address validation and getPublicKey().
|
|
75
|
+
// It is `#private` (non-virtual) on purpose: the constructor must derive the *base* address even
|
|
76
|
+
// when a subclass overrides getPublicKey() — calling the overridable getPublicKey() from the
|
|
77
|
+
// constructor would dispatch to the subclass before its fields are initialized. Laziness also
|
|
78
|
+
// means subclasses that override getPublicKey() (e.g. EnokiKeypair) never pay for this derivation.
|
|
79
|
+
#derivePublicKey(): ZkLoginPublicIdentifier {
|
|
80
|
+
return (this.#publicKey ??= toZkLoginPublicIdentifier(
|
|
81
|
+
BigInt(this.#inputs.addressSeed),
|
|
82
|
+
extractClaimValue<string>(this.#inputs.issBase64Details, 'iss'),
|
|
83
|
+
{ legacyAddress: this.#legacyAddress, client: this.#client },
|
|
84
|
+
));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The single extension point: the ephemeral signature is produced with the requested intent and
|
|
89
|
+
* then wrapped in a zkLogin signature.
|
|
90
|
+
*/
|
|
91
|
+
override async signWithIntent(
|
|
92
|
+
bytes: Uint8Array,
|
|
93
|
+
intent: IntentScope,
|
|
94
|
+
): Promise<SignatureWithBytes> {
|
|
95
|
+
const { bytes: signedBytes, signature: userSignature } =
|
|
96
|
+
await this.#ephemeralSigner.signWithIntent(bytes, intent);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
bytes: signedBytes,
|
|
100
|
+
signature: getZkLoginSignature({
|
|
101
|
+
inputs: this.#inputs,
|
|
102
|
+
maxEpoch: this.#maxEpoch,
|
|
103
|
+
userSignature,
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
sign(_data: Uint8Array): never {
|
|
109
|
+
throw new Error(
|
|
110
|
+
'ZkLoginSigner does not support signing directly. Use signTransaction or signPersonalMessage instead',
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getKeyScheme(): SignatureScheme {
|
|
115
|
+
return 'ZkLogin';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
getPublicKey(): ZkLoginPublicIdentifier {
|
|
119
|
+
return this.#derivePublicKey();
|
|
120
|
+
}
|
|
121
|
+
}
|