@mysten/docs 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +24 -0
  2. package/dist/bcs/index.md +358 -0
  3. package/dist/bcs/llms-index.md +4 -0
  4. package/dist/codegen/index.md +441 -0
  5. package/dist/codegen/llms-index.md +4 -0
  6. package/dist/dapp-kit/actions/connect-wallet.md +69 -0
  7. package/dist/dapp-kit/actions/disconnect-wallet.md +38 -0
  8. package/dist/dapp-kit/actions/sign-and-execute-transaction.md +96 -0
  9. package/dist/dapp-kit/actions/sign-personal-message.md +58 -0
  10. package/dist/dapp-kit/actions/sign-transaction.md +65 -0
  11. package/dist/dapp-kit/actions/switch-account.md +37 -0
  12. package/dist/dapp-kit/actions/switch-network.md +37 -0
  13. package/dist/dapp-kit/dapp-kit-instance.md +162 -0
  14. package/dist/dapp-kit/getting-started/create-dapp.md +151 -0
  15. package/dist/dapp-kit/getting-started/next-js.md +162 -0
  16. package/dist/dapp-kit/getting-started/react.md +172 -0
  17. package/dist/dapp-kit/getting-started/vue.md +193 -0
  18. package/dist/dapp-kit/index.md +70 -0
  19. package/dist/dapp-kit/llms-index.md +26 -0
  20. package/dist/dapp-kit/react/components/connect-button.md +42 -0
  21. package/dist/dapp-kit/react/components/connect-modal.md +51 -0
  22. package/dist/dapp-kit/react/components/index.md +13 -0
  23. package/dist/dapp-kit/react/dapp-kit-provider.md +86 -0
  24. package/dist/dapp-kit/react/hooks/index.md +25 -0
  25. package/dist/dapp-kit/react/hooks/use-current-account.md +33 -0
  26. package/dist/dapp-kit/react/hooks/use-current-client.md +36 -0
  27. package/dist/dapp-kit/react/hooks/use-current-network.md +28 -0
  28. package/dist/dapp-kit/react/hooks/use-current-wallet.md +36 -0
  29. package/dist/dapp-kit/react/hooks/use-dapp-kit.md +100 -0
  30. package/dist/dapp-kit/react/hooks/use-wallet-connection.md +48 -0
  31. package/dist/dapp-kit/react/hooks/use-wallets.md +33 -0
  32. package/dist/dapp-kit/state.md +169 -0
  33. package/dist/dapp-kit/theming.md +196 -0
  34. package/dist/dapp-kit/web-components/connect-button.md +89 -0
  35. package/dist/dapp-kit/web-components/connect-modal.md +177 -0
  36. package/dist/kiosk/advanced-examples.md +101 -0
  37. package/dist/kiosk/from-v1.md +320 -0
  38. package/dist/kiosk/index.md +22 -0
  39. package/dist/kiosk/kiosk-client/introduction.md +52 -0
  40. package/dist/kiosk/kiosk-client/kiosk-transaction/examples.md +119 -0
  41. package/dist/kiosk/kiosk-client/kiosk-transaction/kiosk-transaction.md +103 -0
  42. package/dist/kiosk/kiosk-client/kiosk-transaction/managing.md +235 -0
  43. package/dist/kiosk/kiosk-client/kiosk-transaction/purchasing.md +110 -0
  44. package/dist/kiosk/kiosk-client/querying.md +237 -0
  45. package/dist/kiosk/kiosk-client/transfer-policy-transaction/introduction.md +79 -0
  46. package/dist/kiosk/kiosk-client/transfer-policy-transaction/using-the-manager.md +115 -0
  47. package/dist/kiosk/llms-index.md +8 -0
  48. package/dist/llms-index.md +125 -0
  49. package/dist/payment-kit/getting-started.md +256 -0
  50. package/dist/payment-kit/index.md +132 -0
  51. package/dist/payment-kit/llms-index.md +8 -0
  52. package/dist/payment-kit/payment-kit-sdk.md +747 -0
  53. package/dist/payment-kit/payment-processing.md +372 -0
  54. package/dist/payment-kit/registry-management.md +529 -0
  55. package/dist/seal/index.md +85 -0
  56. package/dist/seal/llms-index.md +4 -0
  57. package/dist/slush-wallet/dapp.md +95 -0
  58. package/dist/slush-wallet/deep-linking.md +465 -0
  59. package/dist/slush-wallet/index.md +7 -0
  60. package/dist/slush-wallet/llms-index.md +6 -0
  61. package/dist/sui/bcs.md +134 -0
  62. package/dist/sui/clients/core.md +606 -0
  63. package/dist/sui/clients/graphql.md +101 -0
  64. package/dist/sui/clients/grpc.md +155 -0
  65. package/dist/sui/clients/index.md +95 -0
  66. package/dist/sui/clients/json-rpc.md +239 -0
  67. package/dist/sui/cryptography/keypairs.md +267 -0
  68. package/dist/sui/cryptography/multisig.md +194 -0
  69. package/dist/sui/cryptography/passkey.md +111 -0
  70. package/dist/sui/cryptography/webcrypto-signer.md +81 -0
  71. package/dist/sui/executors.md +148 -0
  72. package/dist/sui/faucet.md +26 -0
  73. package/dist/sui/hello-sui.md +115 -0
  74. package/dist/sui/index.md +53 -0
  75. package/dist/sui/install.md +61 -0
  76. package/dist/sui/llm-docs.md +32 -0
  77. package/dist/sui/llms-index.md +44 -0
  78. package/dist/sui/migrations/0.38.md +58 -0
  79. package/dist/sui/migrations/sui-1.0.md +455 -0
  80. package/dist/sui/migrations/sui-2.0/agent-prompt.md +42 -0
  81. package/dist/sui/migrations/sui-2.0/dapp-kit.md +350 -0
  82. package/dist/sui/migrations/sui-2.0/deepbook-v3.md +33 -0
  83. package/dist/sui/migrations/sui-2.0/index.md +158 -0
  84. package/dist/sui/migrations/sui-2.0/json-rpc-migration.md +386 -0
  85. package/dist/sui/migrations/sui-2.0/kiosk.md +120 -0
  86. package/dist/sui/migrations/sui-2.0/sdk-maintainers.md +90 -0
  87. package/dist/sui/migrations/sui-2.0/seal.md +14 -0
  88. package/dist/sui/migrations/sui-2.0/sui.md +341 -0
  89. package/dist/sui/migrations/sui-2.0/suins.md +43 -0
  90. package/dist/sui/migrations/sui-2.0/wallet-builders.md +66 -0
  91. package/dist/sui/migrations/sui-2.0/walrus.md +41 -0
  92. package/dist/sui/migrations/sui-2.0/zksend.md +95 -0
  93. package/dist/sui/plugins.md +258 -0
  94. package/dist/sui/sdk-building.md +344 -0
  95. package/dist/sui/transaction-building/basics.md +299 -0
  96. package/dist/sui/transaction-building/gas.md +62 -0
  97. package/dist/sui/transaction-building/intents.md +62 -0
  98. package/dist/sui/transaction-building/offline.md +73 -0
  99. package/dist/sui/transaction-building/sponsored-transactions.md +22 -0
  100. package/dist/sui/utils/derived_objects.md +59 -0
  101. package/dist/sui/utils/index.md +52 -0
  102. package/dist/sui/zklogin.md +83 -0
  103. package/dist/walrus/index.md +527 -0
  104. package/dist/walrus/llms-index.md +4 -0
  105. package/dist/zksend/index.md +27 -0
  106. package/dist/zksend/link-builder.md +192 -0
  107. package/dist/zksend/llms-index.md +5 -0
  108. package/package.json +66 -0
@@ -0,0 +1,267 @@
1
+ # Key pairs
2
+
3
+ > Create and manage Ed25519, Secp256k1, and Secp256r1 keypairs
4
+
5
+ The Sui TypeScript SDK provides `Keypair` classes that handle logic for signing and verification
6
+ using the cryptographic key pairs associated with a Sui address.
7
+
8
+ The Sui TypeScript SDK supports three signing schemes:
9
+
10
+ | Sign scheme | Class name | Import folder |
11
+ | --------------- | ------------------ | -------------------------------- |
12
+ | Ed25519 | `Ed25519Keypair` | `@mysten/sui/keypairs/ed25519` |
13
+ | ECDSA Secp256k1 | `Secp256k1Keypair` | `@mysten/sui/keypairs/secp256k1` |
14
+ | ECDSA Secp256r1 | `Secp256r1Keypair` | `@mysten/sui/keypairs/secp256r1` |
15
+
16
+ For information on these schemes, see the
17
+ [Signatures](https://docs.sui.io/concepts/cryptography/transaction-auth/signatures) topic.
18
+
19
+ To use, import the key pair class your project uses from the `@mysten/sui/keypairs` folder. For
20
+ example, to use the Ed25519 scheme, import the `Ed25519Keypair` class from
21
+ `@mysten/sui/keypairs/ed25519`.
22
+
23
+ ```typescript
24
+
25
+ ```
26
+
27
+ To create a random key pair (which identifies a Sui address), instantiate a new `Keypair` class. To
28
+ reference a key pair from an existing secret key, pass the secret to the `fromSecretKey` function.
29
+
30
+ ```typescript
31
+ // random Keypair
32
+ const keypair = new Ed25519Keypair();
33
+ // Keypair from an existing secret key (Uint8Array)
34
+ const keypair = Ed25519Keypair.fromSecretKey(secretKey);
35
+ ```
36
+
37
+ With your key pair created, you can reference it when performing actions on the network. For
38
+ example, you can use it to sign transactions, like the following code that creates and signs a
39
+ personal message using the public key from the key pair created in the previous code:
40
+
41
+ ```typescript
42
+ const publicKey = keypair.getPublicKey();
43
+ const message = new TextEncoder().encode('hello world');
44
+
45
+ const { signature } = await keypair.signPersonalMessage(message);
46
+ const isValid = await publicKey.verifyPersonalMessage(message, signature);
47
+ ```
48
+
49
+ ## Public keys
50
+
51
+ Each `Keypair` has an associated `PublicKey` class. You use the public key to verify signatures or
52
+ to retrieve its associated Sui address. You can access a `Keypair` from its `PublicKey` or construct
53
+ it from the bytes (as a `Uint8Array`) of the `PublicKey`, as in the following code:
54
+
55
+ ```typescript
56
+
57
+ const keypair = new Ed25519Keypair();
58
+
59
+ // method 1
60
+ const bytes = keypair.getPublicKey().toRawBytes();
61
+ const publicKey = new Ed25519PublicKey(bytes);
62
+ const address = publicKey.toSuiAddress();
63
+
64
+ // method 2
65
+ const address = keypair.getPublicKey().toSuiAddress();
66
+ // or use `toSuiAddress()` directly
67
+ const address = keypair.toSuiAddress();
68
+ ```
69
+
70
+ ## Verifying signatures without a key pair
71
+
72
+ When you have an existing public key, you can use it to verify a signature. Verification ensures the
73
+ signature is valid for the provided message and is signed with the appropriate secret key.
74
+
75
+ The following code creates a key pair in the Ed25519 scheme, creates and signs a message with it,
76
+ then verifies the message to retrieve the public key. The code then uses `toSuiAddress()` to check
77
+ if the address associated with the public key matches the address that the key pair defines.
78
+
79
+ ```typescript
80
+
81
+ const keypair = new Ed25519Keypair();
82
+ const message = new TextEncoder().encode('hello world');
83
+ const { signature } = await keypair.signPersonalMessage(message);
84
+
85
+ const publicKey = await verifyPersonalMessageSignature(message, signature);
86
+
87
+ if (!publicKey.verifyAddress(keypair.toSuiAddress())) {
88
+ throw new Error('Signature was valid, but was signed by a different key pair');
89
+ }
90
+ ```
91
+
92
+ ## Verifying that a signature is valid for a specific address
93
+
94
+ `verifyPersonalMessageSignature` and `verifyTransactionSignature` accept an optional `address`, and
95
+ will throw an error if the signature is not valid for the provided address.
96
+
97
+ ```typescript
98
+
99
+ const keypair = new Ed25519Keypair();
100
+ const message = new TextEncoder().encode('hello world');
101
+ const { signature } = await keypair.signPersonalMessage(message);
102
+
103
+ await verifyPersonalMessageSignature(message, signature, {
104
+ address: keypair.toSuiAddress(),
105
+ });
106
+ ```
107
+
108
+ ## Verifying transaction signatures
109
+
110
+ Verifying transaction signatures is similar to personal message signature verification, except you
111
+ use `verifyTransactionSignature`:
112
+
113
+ ```typescript
114
+ // import SuiGrpcClient to create a network client
115
+
116
+ // create a client connected to testnet
117
+ const client = new SuiGrpcClient({
118
+ network: 'testnet',
119
+ baseUrl: 'https://fullnode.testnet.sui.io:443',
120
+ });
121
+ const tx = new Transaction();
122
+ // ... add some transactions...
123
+ const bytes = await tx.build({ client });
124
+
125
+ const keypair = new Ed25519Keypair();
126
+ const { signature } = await keypair.signTransaction(bytes);
127
+
128
+ await verifyTransactionSignature(bytes, signature, {
129
+ // optionally verify that the signature is valid for a specific address
130
+ address: keypair.toSuiAddress(),
131
+ });
132
+ ```
133
+
134
+ ## Verifying zkLogin signatures
135
+
136
+ ZkLogin signatures can't be verified purely on the client. When verifying a zkLogin signature, the
137
+ SDK uses the GraphQL API to verify the signature. This will work for mainnet signatures without any
138
+ additional configuration.
139
+
140
+ For testnet signatures, you will need to provide a testnet GraphQL Client:
141
+
142
+ ```typescript
143
+
144
+ const publicKey = await verifyPersonalMessageSignature(message, zkSignature, {
145
+ client: new SuiGraphQLClient({
146
+ url: 'https://graphql.testnet.sui.io/graphql',
147
+ }),
148
+ });
149
+ ```
150
+
151
+ For some zklogin accounts, there are 2 valid addresses for a given set of inputs. This means you may
152
+ run into issues if you try to compare the address returned by `publicKey.toSuiAddress()` directly
153
+ with an expected address.
154
+
155
+ Instead, you can either pass in the expected address during verification, or use the
156
+ `publicKey.verifyAddress(address)` method:
157
+
158
+ ```typescript
159
+
160
+ const publicKey = await verifyPersonalMessageSignature(message, zkSignature, {
161
+ client: new SuiGraphQLClient({
162
+ url: 'https://graphql.testnet.sui.io/graphql',
163
+ }),
164
+ // Pass in the expected address, and the verification method will throw an error if the signature is not valid for the provided address
165
+ address: '0x...expectedAddress',
166
+ });
167
+ // or
168
+
169
+ if (!publicKey.verifyAddress('0x...expectedAddress')) {
170
+ throw new Error('Signature was valid, but was signed by a different key pair');
171
+ }
172
+ ```
173
+
174
+ Both of these methods will check the signature against both the standard and
175
+ [legacy versions of the zklogin address](https://sdk.mystenlabs.com/sui/zklogin#legacy-addresses).
176
+
177
+ ## Deriving a key pair from a mnemonic
178
+
179
+ The Sui TypeScript SDK supports deriving a key pair from a mnemonic phrase. This can be useful when
180
+ building wallets or other tools that allow a user to import their private keys.
181
+
182
+ ```typescript
183
+ const exampleMnemonic = 'result crisp session latin ...';
184
+
185
+ const keyPair = Ed25519Keypair.deriveKeypair(exampleMnemonic);
186
+ ```
187
+
188
+ ## Deriving a `Keypair` from a Bech32 encoded secret key
189
+
190
+ If you know the Keypair scheme for your secret key, you can use the `fromSecretKey` method of the
191
+ appropriate `Keypair` class to derive the keypair from the secret key.
192
+
193
+ ```typescript
194
+
195
+ // Example bech32 encoded secret key (which always starts with 'suiprivkey')
196
+ const secretKey = 'suiprivkey1qzse89atw7d3zum8ujep76d2cxmgduyuast0y9fu23xcl0mpafgkktllhyc';
197
+
198
+ const keypair = Ed25519Keypair.fromSecretKey(secretKey);
199
+ ```
200
+
201
+ You can also use the `decodeSuiPrivateKey` function to decode the secret key and determine the
202
+ keyScheme, and get the keypairs private key bytes, which can be used to instantiate the appropriate
203
+ `Keypair` class.
204
+
205
+ ```typescript
206
+
207
+ const { scheme, secretKey } = decodeSuiPrivateKey(encoded);
208
+
209
+ // use scheme to choose the correct key pair
210
+ switch (scheme) {
211
+ case 'ED25519':
212
+ keypair = Ed25519Keypair.fromSecretKey(secretKey);
213
+ break;
214
+ case 'Secp256r1':
215
+ keypair = Secp256r1Keypair.fromSecretKey(secretKey);
216
+ break;
217
+ case 'Secp256k1':
218
+ keypair = Secp256k1Keypair.fromSecretKey(secretKey);
219
+ break;
220
+ default:
221
+ throw new Error(`Unsupported key pair scheme: ${scheme}`);
222
+ }
223
+ ```
224
+
225
+ See [SIP-15](https://github.com/sui-foundation/sips/blob/main/sips/sip-15.md) for additional context
226
+ and motivation.
227
+
228
+ If you know your keypair scheme, you can use the `fromSecretKey` method of the appropriate keypair
229
+ to directly derive the keypair from the secret key.
230
+
231
+ ```typescript
232
+ const secretKey = 'suiprivkey1qzse89atw7d3zum8ujep76d2cxmgduyuast0y9fu23xcl0mpafgkktllhyc';
233
+
234
+ const keypair = Ed25519Keypair.fromSecretKey(secretKey);
235
+ ```
236
+
237
+ You can also export a keypair to a Bech32 encoded secret key using the `getSecretKey` method.
238
+
239
+ ```typescript
240
+ const secretKey = keypair.getSecretKey();
241
+ ```
242
+
243
+ If you have only the raw private key bytes for your keypair, you can encode to the Bech32 format
244
+ using the `encodeSuiPrivateKey` function.
245
+
246
+ ```typescript
247
+
248
+ const encoded = encodeSuiPrivateKey(
249
+ new Uint8Array([
250
+ 59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253, 102,
251
+ 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
252
+ ]),
253
+ 'ED25519',
254
+ );
255
+ ```
256
+
257
+ ## Deriving a `Keypair` from a hex encoded secret key
258
+
259
+ If you have an existing secret key formatted as a hex encoded string, you can derive a `Keypair` by
260
+ converting the secret key to a `Uint8Array` and passing it to the `fromSecretKey` method of a
261
+ `Keypair` class.
262
+
263
+ ```typescript
264
+
265
+ const secret = '0x...';
266
+ const keypair = Ed25519Keypair.fromSecretKey(fromHex(secret));
267
+ ```
@@ -0,0 +1,194 @@
1
+ # Multi-Signature Transactions
2
+
3
+ > Create multi-signature transactions with multiple signers
4
+
5
+ The Sui TypeScript SDK provides a `MultiSigPublicKey` class to support
6
+ [Multi-Signature](https://docs.sui.io/concepts/cryptography/transaction-auth/multisig) (MultiSig)
7
+ transaction and personal message signing.
8
+
9
+ This class implements the same interface as the `PublicKey` classes that [Keypairs](./keypairs) uses
10
+ and you call the same methods to verify signatures for `PersonalMessages` and `Transactions`.
11
+
12
+ ## Creating a MultiSigPublicKey
13
+
14
+ To create a `MultiSigPublicKey`, you provide a `threshold`(u16) value and an array of objects that
15
+ contain `publicKey` and `weight`(u8) values. If the combined weight of valid signatures for a
16
+ transaction is equal to or greater than the threshold value, then the Sui network considers the
17
+ transdaction valid.
18
+
19
+ ```typescript
20
+
21
+ const kp1 = new Ed25519Keypair();
22
+ const kp2 = new Ed25519Keypair();
23
+ const kp3 = new Ed25519Keypair();
24
+
25
+ const multiSigPublicKey = MultiSigPublicKey.fromPublicKeys({
26
+ threshold: 2,
27
+ publicKeys: [
28
+ {
29
+ publicKey: kp1.getPublicKey(),
30
+ weight: 1,
31
+ },
32
+ {
33
+ publicKey: kp2.getPublicKey(),
34
+ weight: 1,
35
+ },
36
+ {
37
+ publicKey: kp3.getPublicKey(),
38
+ weight: 2,
39
+ },
40
+ ],
41
+ });
42
+
43
+ const multisigAddress = multiSigPublicKey.toSuiAddress();
44
+ ```
45
+
46
+ The `multiSigPublicKey` in the preceding code enables you to verify that signatures have a combined
47
+ weight of at least `2`. A signature signed with only `kp1` or `kp2` is not valid, but a signature
48
+ signed with both `kp1` and `kp2`, or just `kp3` is valid.
49
+
50
+ ## Combining signatures with a MultiSigPublicKey
51
+
52
+ To sign a message or transaction for a MultiSig address, you must collect signatures from the
53
+ individual key pairs, and then combine them into a signature using the `MultiSigPublicKey` class for
54
+ the address.
55
+
56
+ ```typescript
57
+ // This example uses the same imports, key pairs, and multiSigPublicKey from the previous example
58
+ const message = new TextEncoder().encode('hello world');
59
+
60
+ const signature1 = (await kp1.signPersonalMessage(message)).signature;
61
+ const signature2 = (await kp2.signPersonalMessage(message)).signature;
62
+
63
+ const combinedSignature = multiSigPublicKey.combinePartialSignatures([signature1, signature2]);
64
+
65
+ const isValid = await multiSigPublicKey.verifyPersonalMessage(message, combinedSignature);
66
+ ```
67
+
68
+ ## Creating a MultiSigSigner
69
+
70
+ The `MultiSigSigner` class allows you to create a Signer that can be used to sign personal messages
71
+ and Transactions like any other keypair or signer class. This is often easier than manually
72
+ combining signatures, since many methods accept Signers and handle signing directly.
73
+
74
+ A `MultiSigSigner` is created by providing the underlying Signers to the `getSigner` method on the
75
+ `MultiSigPublicKey`. You can provide a subset of the Signers that make up the public key, so long as
76
+ their combined weight is equal to or greater than the threshold.
77
+
78
+ ```typescript
79
+
80
+ const kp1 = new Ed25519Keypair();
81
+ const kp2 = new Ed25519Keypair();
82
+
83
+ const multiSigPublicKey = MultiSigPublicKey.fromPublicKeys({
84
+ threshold: 1,
85
+ publicKeys: [
86
+ {
87
+ publicKey: kp1.getPublicKey(),
88
+ weight: 1,
89
+ },
90
+ {
91
+ publicKey: kp2.getPublicKey(),
92
+ weight: 1,
93
+ },
94
+ ],
95
+ });
96
+
97
+ const signer = multiSigPublicKey.getSigner(kp1);
98
+
99
+ const message = new TextEncoder().encode('hello world');
100
+ const { signature } = await signer.signPersonalMessage(message);
101
+ const isValid = await multiSigPublicKey.verifyPersonalMessage(message, signature);
102
+ ```
103
+
104
+ ## Multisig with zkLogin
105
+
106
+ You can use zkLogin to participate in multisig just like keys for other signature schemes. Unlike
107
+ other keys that come with a public key, you define a public identifier for zkLogin.
108
+
109
+ For example, the following example creates a 1-out-of-2 multisig with a single key and a zkLogin
110
+ public identifier:
111
+
112
+ ```typescript
113
+ // a single Ed25519 keypair and its public key.
114
+ const kp1 = new Ed25519Keypair();
115
+ const pkSingle = kp1.getPublicKey();
116
+
117
+ // compute the address seed based on user salt and jwt token values.
118
+ const decodedJWT = decodeJwt('a valid jwt token here');
119
+ const userSalt = BigInt('123'); // a valid user salt
120
+ const addressSeed = genAddressSeed(userSalt, 'sub', decodedJwt.sub, decodedJwt.aud).toString();
121
+
122
+ // a zkLogin public identifier derived from an address seed and an iss string.
123
+ let pkZklogin = toZkLoginPublicIdentifier(addressSeed, decodedJwt.iss);
124
+
125
+ // derive multisig address from multisig public key defined by the single key and zkLogin public
126
+ // identifier with weight and threshold.
127
+ const multiSigPublicKey = MultiSigPublicKey.fromPublicKeys({
128
+ threshold: 1,
129
+ publicKeys: [
130
+ { publicKey: pkSingle, weight: 1 },
131
+ { publicKey: pkZklogin, weight: 1 },
132
+ ],
133
+ });
134
+
135
+ // this is the sender of any transactions from this multisig account.
136
+ const multisigAddress = multiSigPublicKey.toSuiAddress();
137
+
138
+ // create a regular zklogin signature from the zkproof and ephemeral signature for zkLogin.
139
+ // see zklogin-integration.mdx for more details.
140
+ const zkLoginSig = getZkLoginSignature({
141
+ inputs: zkLoginInputs,
142
+ maxEpoch: '2',
143
+ userSignature: fromBase64(ephemeralSig),
144
+ });
145
+
146
+ // a valid multisig with just the zklogin signature.
147
+ const multisig = multiSigPublicKey.combinePartialSignatures([zkLoginSig]);
148
+ ```
149
+
150
+ ### Benefits and Design for zkLogin in Multisig
151
+
152
+ Because zkLogin assumes the application client ID and its issuer (such as Google) liveliness, using
153
+ zkLogin with multisig provides improved recoverability to a zkLogin account. In the previous example
154
+ of 1-out-of-2 multisig, users can use zkLogin in their regular wallet flow, but if the application
155
+ or the issuer is deprecated, the user can still use the regular private key account to access funds
156
+ in the multisig wallet.
157
+
158
+ This also opens the door to design multisig across any number of zkLogin accounts and of different
159
+ providers (max number is capped at 10 accounts) with customizable weights and thresholds. For
160
+ example, you can set up a multisig address with threshold of 2, where the public keys or identifiers
161
+ are defined as:
162
+
163
+ 1. Charlie's own Google account with weight 2
164
+ 2. Charlie's friend Alice's Apple account with weight 1
165
+ 3. Charlie's friend Bob's Facebook account with weight 1
166
+
167
+ In this case, Charlie can always use their Google account for transactions out of the multisig
168
+ address for the threshold. At the same time, Charlie still has access to his account by combining
169
+ partial signatures from Alice and Bob.
170
+
171
+ ## Multisig with Passkey
172
+
173
+ You can use a `PasskeyKeypair` (a `Keypair`) and `PasskeyPublicKey` (a `PublicKey`) as components in
174
+ a Multisig setup. Once initialized, they support both Multisig address derivation and transaction
175
+ signing.
176
+
177
+ ```typescript
178
+ const passkeyKeypair = await PasskeyKeypair.getPasskeyInstance(
179
+ new BrowserPasskeyProvider('Sui Passkey Example', {
180
+ rpName: 'Sui Passkey Example',
181
+ rpId: window.location.hostname,
182
+ } as BrowserPasswordProviderOptions),
183
+ );
184
+
185
+ const passkeyPublicKey = passkeyKeypair.getPublicKey();
186
+
187
+ const multiSigPublicKey = MultiSigPublicKey.fromPublicKeys({
188
+ threshold: 1,
189
+ publicKeys: [
190
+ { publicKey: passkeyPublicKey, weight: 1 },
191
+ // other keys
192
+ ],
193
+ });
194
+ ```
@@ -0,0 +1,111 @@
1
+ # Passkey
2
+
3
+ > Use WebAuthn passkeys for Sui transaction signing
4
+
5
+ Similar to other Keypair classes, the Sui TypeScript SDK provides the `PasskeyKeypair` that handles
6
+ communication with the passkey device and signing with it. This SDK defines the address and
7
+ signatures according to [SIP-9](https://github.com/sui-foundation/sips/blob/main/sips/sip-9.md).
8
+
9
+ To use, import the `PasskeyKeypair` class from `@mysten/sui/keypairs/passkey`.
10
+
11
+ ```typescript
12
+
13
+ BrowserPasskeyProvider,
14
+ BrowserPasswordProviderOptions,
15
+ PasskeyKeypair,
16
+ } from '@mysten/sui/keypairs/passkey';
17
+ ```
18
+
19
+ ## Create a new passkey
20
+
21
+ To create a new passkey with the passkey device, and initialize a `PasskeyKeypair`, you can use the
22
+ `PasskeyProvider` and provide the `rpName`, `rpId` and additional options. Note that
23
+ `getPasskeyInstance` call will initialize a new passkey wallet for the origin.
24
+
25
+ ```typescript
26
+ const keypair = await PasskeyKeypair.getPasskeyInstance(
27
+ new BrowserPasskeyProvider('Sui Passkey Example', {
28
+ rpName: 'Sui Passkey Example',
29
+ rpId: window.location.hostname,
30
+ authenticatorSelection: {
31
+ authenticatorAttachment: 'cross-platform', // or "platform"
32
+ },
33
+ } as BrowserPasswordProviderOptions),
34
+ );
35
+ ```
36
+
37
+ You can optionally specify the `authenticatorSelection` parameter when creating a passkey instance:
38
+
39
+ - `cross-platform`: Use this for authenticators that work across devices, such as hardware security
40
+ keys or mobile phones.
41
+ - `platform`: Use this for authenticators tied to a specific device, such as Touch ID, Face ID, or
42
+ Windows Hello.
43
+
44
+ Because a passkey device will only return the public key upon creation, but not upon signing, it is
45
+ recommended for the frontend to always cache the `PasskeyKeypair` instance that contains the public
46
+ key in the wallet. When a user tries to sign a transaction, it will just call signTransaction on the
47
+ same instance and the public key is available when constructing the passkey signature.
48
+
49
+ It is recommended that the user should only be allowed to create a passkey wallet once per origin.
50
+ If the user ended up with multiple passkeys for the same origin, the passkey UI would show a list of
51
+ all passkeys of the same origin and the user can choose which one to use. This can be a confusing
52
+ experience since they do not remember which passkey is the way that the wallet was created for.
53
+
54
+ ## Recover a passkey
55
+
56
+ However, if the user is logged out or uses a different browser or device, or the `PasskeyKeypair`
57
+ instance is no longer present for any reason, the user should be prompt to recover the public key
58
+ (e.g. "Log in to existing passkey wallet") to be able to use the passkey wallet again. If the user
59
+ is prompted to create a new key in passkey device, a fresh new wallet with new address will be
60
+ created.
61
+
62
+ One can recover the unique public key with exactly two passkey signatures on two messages. This
63
+ means that if the user is asked to sign two messages, the developer can recover an unique public key
64
+ and its Sui address.
65
+
66
+ ```typescript
67
+ let provider = new BrowserPasskeyProvider('Sui Passkey Example', {
68
+ rpName: 'Sui Passkey Example',
69
+ rpId: window.location.hostname,
70
+ } as BrowserPasswordProviderOptions);
71
+
72
+ const testMessage = new TextEncoder().encode('Hello world!');
73
+ const possiblePks = await PasskeyKeypair.signAndRecover(provider, testMessage);
74
+
75
+ const testMessage2 = new TextEncoder().encode('Hello world 2!');
76
+ const possiblePks2 = await PasskeyKeypair.signAndRecover(provider, testMessage2);
77
+
78
+ const commonPk = findCommonPublicKey(possiblePks, possiblePks2);
79
+ const keypair = new PasskeyKeypair(commonPk.toRawBytes(), provider);
80
+ ```
81
+
82
+ Alternatively, the developer can choose to ask the user to only sign one personal message that
83
+ returns two possible public keys. Then the frontend may derive the addresses for both, and check
84
+ onchain for the unique address that contains assets. Or the frontend may retrieve additional
85
+ signatures from past transaction history for the given address. This may a preferred user experience
86
+ since the user is only prompted to sign one message, but the frontend needs to do extra work.
87
+
88
+ ## Usage
89
+
90
+ The usage for a passkey keypair is the same as any other keypair. You can derive the public key,
91
+ derive the address, sign personal messages, sign transactions and verify signatures. See the
92
+ [Key pairs](./keypairs) documentation for more details.
93
+
94
+ ```typescript
95
+ const publicKey = keypair.getPublicKey();
96
+ const address = publicKey.toSuiAddress();
97
+
98
+ const message = new TextEncoder().encode('hello world');
99
+ const { signature } = await keypair.signPersonalMessage(message);
100
+
101
+ const txSignature = await passkey.signTransaction(txBytes);
102
+ ```
103
+
104
+ An example implemention can be found [here](https://github.com/MystenLabs/passkey-example).
105
+
106
+ ## Supported Platforms
107
+
108
+ Sui supports passkey wallets on any device that complies with the WebAuthn standard. This includes
109
+ most modern browsers and operating systems across desktop and mobile. To check which platforms and
110
+ authenticators are compatible, see the
111
+ [Passkeys.dev device support list](https://passkeys.dev/device-support/).
@@ -0,0 +1,81 @@
1
+ # Web Crypto Signer
2
+
3
+ > Sign transactions using the Web Crypto API
4
+
5
+ For cases where you need to create keypairs directly within client dapps, we recommend using the Web
6
+ Crypto Signer. This signer leverages the
7
+ [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) to provide a
8
+ secure and efficient way to generate and manage cryptographic keys in the browser. The generated
9
+ keys are `Secp256r1` keys which can be persisted between sessions, and are not extractable by
10
+ client-side code (including extensions).
11
+
12
+ Common use cases for the Web Crypto Signer include:
13
+
14
+ - zkLogin ephemeral keypairs
15
+ - Session-based keypairs
16
+
17
+ ## Installation
18
+
19
+ To use the Web Crypto Signer, you need to install the `@mysten/signers` package.
20
+
21
+ ```sh npm2yarn
22
+ npm i @mysten/signers
23
+ ```
24
+
25
+ You can then import the `WebCryptoSigner` class from the package:
26
+
27
+ ```typescript
28
+
29
+ ```
30
+
31
+ ## Create a new signer
32
+
33
+ To generate a new signer, you can invoke the `generate()` static method on the `WebCryptoSigner`
34
+ class.
35
+
36
+ ```typescript
37
+ const keypair = await WebCryptoSigner.generate();
38
+ ```
39
+
40
+ ## Persisting and recovering the keypair
41
+
42
+ The private key for the signer is not extractable, but you can persist the keypair using the
43
+ browser's IndexedDB storage. To streamline this process, the keypair provides an `export()` method
44
+ which returns an object containing the public key and a reference to the private key:
45
+
46
+ ```typescript
47
+ // Get the exported keypair:
48
+ const exported = keypair.export();
49
+
50
+ // Write the keypair to IndexedDB.
51
+ // This method does not exist, you need to implement it yourself. We recommend `idb-keyval` for simplicity.
52
+ await writeToIndexedDB('keypair', exported);
53
+ ```
54
+
55
+ You can then recover the keypair by reading it from IndexedDB and passing it to the `import()`
56
+ method.
57
+
58
+ ```typescript
59
+ // Read the keypair from IndexedDB.
60
+ const exported = await readFromIndexedDB('keypair');
61
+
62
+ const keypair = await WebCryptoSigner.import(exported);
63
+ ```
64
+
65
+ > **Warning:** Ensure that you do not call `JSON.stringify` on the exported keypair before persisting it to
66
+ > IndexedDB, as it will throw an error and fail to persist.
67
+
68
+ ## Usage
69
+
70
+ The usage for a Web Crypto signer is the same as any other keypair. You can derive the public key,
71
+ derive the address, sign personal messages, sign transactions and verify signatures. See the
72
+ [Key pairs](./keypairs) documentation for more details.
73
+
74
+ ```typescript
75
+ const publicKey = keypair.getPublicKey();
76
+ const address = publicKey.toSuiAddress();
77
+
78
+ const message = new TextEncoder().encode('hello world');
79
+ await keypair.signPersonalMessage(message);
80
+ await keypair.signTransaction(txBytes);
81
+ ```