@mysten/sui 2.17.0 → 2.19.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 +29 -0
- package/dist/bcs/bcs.d.mts +6 -6
- package/dist/bcs/index.d.mts +20 -20
- package/dist/cryptography/signature.d.mts +6 -6
- package/dist/transactions/Transaction.d.mts +25 -11
- package/dist/transactions/Transaction.d.mts.map +1 -1
- package/dist/transactions/Transaction.mjs +8 -3
- package/dist/transactions/Transaction.mjs.map +1 -1
- package/dist/transactions/index.d.mts +2 -2
- 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/jwt-utils.d.mts.map +1 -1
- package/dist/zklogin/jwt-utils.mjs.map +1 -1
- package/dist/zklogin/utils.d.mts.map +1 -1
- package/dist/zklogin/utils.mjs +9 -0
- package/dist/zklogin/utils.mjs.map +1 -1
- package/docs/bcs.md +11 -6
- package/docs/clients/core.md +10 -9
- package/docs/clients/grpc.md +1 -1
- package/docs/index.md +176 -22
- package/docs/llms-index.md +6 -9
- package/docs/migrations/0.38.md +2 -2
- package/docs/migrations/sui-1.0.md +2 -2
- package/docs/migrations/sui-2.0/dapp-kit.md +5 -1
- package/docs/migrations/sui-2.0/json-rpc-migration.md +76 -33
- package/docs/plugins.md +29 -5
- package/docs/transactions/basics.md +279 -0
- package/docs/transactions/coins-and-balances.md +293 -0
- package/docs/transactions/offline.md +192 -0
- package/docs/transactions/reference.md +380 -0
- package/docs/transactions/signing-and-execution.md +401 -0
- package/package.json +26 -26
- package/src/transactions/Transaction.ts +36 -5
- package/src/transactions/index.ts +1 -0
- package/src/verify/index.ts +3 -0
- package/src/verify/verify.ts +68 -34
- package/src/version.ts +1 -1
- package/src/zklogin/jwt-utils.ts +3 -0
- package/src/zklogin/utils.ts +17 -0
- package/docs/faucet.md +0 -26
- package/docs/hello-sui.md +0 -115
- package/docs/install.md +0 -61
- package/docs/transaction-building/basics.md +0 -299
- package/docs/transaction-building/gas.md +0 -61
- package/docs/transaction-building/intents.md +0 -62
- package/docs/transaction-building/offline.md +0 -73
- package/docs/transaction-building/sponsored-transactions.md +0 -22
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/jwt-utils.ts
CHANGED
|
@@ -116,6 +116,9 @@ export function extractClaimValue<R>(claim: Claim, claimName: string): R {
|
|
|
116
116
|
return value;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// TODO: root cause of the claim-escaping bug — jwtDecode resolves JSON escapes, but the
|
|
120
|
+
// circuit derives the address seed from raw JWT bytes, so escaped claim values decode
|
|
121
|
+
// differently here than the circuit hashes. Real fix: parse claims over raw bytes.
|
|
119
122
|
export function decodeJwt(jwt: string): Omit<JwtPayload, 'iss' | 'aud' | 'sub'> & {
|
|
120
123
|
iss: string;
|
|
121
124
|
aud: string;
|
package/src/zklogin/utils.ts
CHANGED
|
@@ -87,6 +87,20 @@ export function hashASCIIStrToField(str: string, maxSize: number) {
|
|
|
87
87
|
return poseidonHash(packed);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// Reject claim inputs whose decoded form reveals a JSON escape ('"', '\', control char):
|
|
91
|
+
// the circuit hashes raw JWT bytes, so an escaped value would derive a different address.
|
|
92
|
+
function assertNoJsonEscape(value: string, label: string) {
|
|
93
|
+
for (let i = 0; i < value.length; i++) {
|
|
94
|
+
const c = value.charCodeAt(i);
|
|
95
|
+
if (c < 0x20 || c === 0x22 || c === 0x5c) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`zkLogin ${label} contains a JSON-escaped character (code ${c}); the circuit ` +
|
|
98
|
+
`hashes raw JWT bytes, so claim values with escapes are not supported`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
90
104
|
export function genAddressSeed(
|
|
91
105
|
salt: string | bigint,
|
|
92
106
|
name: string,
|
|
@@ -96,6 +110,9 @@ export function genAddressSeed(
|
|
|
96
110
|
max_value_length = MAX_KEY_CLAIM_VALUE_LENGTH,
|
|
97
111
|
max_aud_length = MAX_AUD_VALUE_LENGTH,
|
|
98
112
|
): bigint {
|
|
113
|
+
assertNoJsonEscape(name, 'key claim name');
|
|
114
|
+
assertNoJsonEscape(value, 'key claim value');
|
|
115
|
+
assertNoJsonEscape(aud, 'aud');
|
|
99
116
|
return poseidonHash([
|
|
100
117
|
hashASCIIStrToField(name, max_name_length),
|
|
101
118
|
hashASCIIStrToField(value, max_value_length),
|
package/docs/faucet.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Faucet
|
|
2
|
-
|
|
3
|
-
> Request test SUI tokens from the faucet on Devnet, Testnet, or local networks.
|
|
4
|
-
|
|
5
|
-
Devnet, Testnet, and local networks include faucets that mint SUI. You can use the Sui TypeScript
|
|
6
|
-
SDK to call a network's faucet and provide SUI to the address you provide.
|
|
7
|
-
|
|
8
|
-
To request SUI from a faucet, import the `requestSuiFromFaucetV2` function from the
|
|
9
|
-
`@mysten/sui/faucet` package to your project.
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Use `requestSuiFromFaucetV2` in your TypeScript code to request SUI from the network's faucet.
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
await requestSuiFromFaucetV2({
|
|
19
|
-
host: getFaucetHost('testnet'),
|
|
20
|
-
recipient: <RECIPIENT_ADDRESS>,
|
|
21
|
-
});
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
> **Note:** Faucets on Devnet and Testnet are rate limited. If you run the script too many times, you surpass
|
|
25
|
-
> the limit and must wait to successfully run it again. For Testnet, the best way to get SUI is
|
|
26
|
-
> through the Web UI: `faucet.sui.io`.
|
package/docs/hello-sui.md
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# Hello Sui
|
|
2
|
-
|
|
3
|
-
> Build your first Sui application with the TypeScript SDK.
|
|
4
|
-
|
|
5
|
-
This basic example introduces you to the Sui TypeScript SDK. The Node.js example mints SUI on a Sui
|
|
6
|
-
network and then queries the address to get a sum for the owned SUI. You don't need to use an IDE to
|
|
7
|
-
complete the example, but one like Microsoft Visual Studio Code helps centralize more advanced
|
|
8
|
-
projects.
|
|
9
|
-
|
|
10
|
-
## Before you begin
|
|
11
|
-
|
|
12
|
-
You need an address on a Sui development network (Devnet, Testnet, or local). If you don't already
|
|
13
|
-
have an address, use the [Sui Client CLI](https://docs.sui.io/references/cli/client) or the
|
|
14
|
-
[Sui Wallet browser extension](https://docs.mystenlabs.com) to create one.
|
|
15
|
-
|
|
16
|
-
You also need [Node.js](https://nodejs.org/en/download/current) and a package manager like
|
|
17
|
-
[pnpm](https://pnpm.io/installation) to follow this example, so install them on your system if you
|
|
18
|
-
haven't already.
|
|
19
|
-
|
|
20
|
-
## Start a project
|
|
21
|
-
|
|
22
|
-
Using a Terminal or Console, create a folder on your system (`hello-sui` in this example) and make
|
|
23
|
-
it the working directory.
|
|
24
|
-
|
|
25
|
-
```sh
|
|
26
|
-
mkdir hello-sui
|
|
27
|
-
cd hello-sui
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
When you use a package manager to install the necessary packages, it downloads the modules to your
|
|
31
|
-
`node_modules` folder and adds the references to your `package.json` file, creating the file if it
|
|
32
|
-
doesn't already exist. For this example, you need only the Sui TypeScript SDK:
|
|
33
|
-
|
|
34
|
-
```sh npm2yarn
|
|
35
|
-
npm i -D @mysten/sui
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
The SDK is published as an ESM only package, so you also need to set `"type": "module"` in your
|
|
39
|
-
`package.json`. Your `package.json` file should look like this:
|
|
40
|
-
|
|
41
|
-
```json
|
|
42
|
-
{
|
|
43
|
-
"type": "module",
|
|
44
|
-
"dependencies": {
|
|
45
|
-
"@mysten/sui": "^<VERSION_NUMBER>"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Get some SUI for your account
|
|
51
|
-
|
|
52
|
-
Instead of a 'Hello World' output to your console, this example introduces some SUI to your wallet
|
|
53
|
-
address. You must be on Devnet, Testnet, or a local network to use a faucet for minting SUI.
|
|
54
|
-
|
|
55
|
-
Create a new `index.js` file in the root of your project with the following code.
|
|
56
|
-
|
|
57
|
-
```js
|
|
58
|
-
|
|
59
|
-
// replace <YOUR_SUI_ADDRESS> with your actual address, which is in the form 0x123...
|
|
60
|
-
const MY_ADDRESS = '<YOUR_SUI_ADDRESS>';
|
|
61
|
-
|
|
62
|
-
// create a new SuiGrpcClient object pointing to the network you want to use
|
|
63
|
-
const suiClient = new SuiGrpcClient({
|
|
64
|
-
network: 'devnet',
|
|
65
|
-
baseUrl: 'https://fullnode.devnet.sui.io:443',
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Convert MIST to Sui
|
|
69
|
-
const balance = (balance) => {
|
|
70
|
-
return Number.parseInt(balance.totalBalance) / Number(MIST_PER_SUI);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// store the JSON representation for the SUI the address owns before using faucet
|
|
74
|
-
const suiBefore = await suiClient.getBalance({
|
|
75
|
-
owner: MY_ADDRESS,
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
await requestSuiFromFaucetV2({
|
|
79
|
-
// use getFaucetHost to make sure you're using correct faucet address
|
|
80
|
-
// you can also just use the address (see Sui TypeScript SDK Quick Start for values)
|
|
81
|
-
host: getFaucetHost('devnet'),
|
|
82
|
-
recipient: MY_ADDRESS,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// store the JSON representation for the SUI the address owns after using faucet
|
|
86
|
-
const suiAfter = await suiClient.getBalance({
|
|
87
|
-
owner: MY_ADDRESS,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Output result to console.
|
|
91
|
-
console.log(
|
|
92
|
-
`Balance before faucet: ${balance(suiBefore)} SUI. Balance after: ${balance(
|
|
93
|
-
suiAfter,
|
|
94
|
-
)} SUI. Hello, SUI!`,
|
|
95
|
-
);
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Save the file, then use Node.js to run it in your Console or Terminal:
|
|
99
|
-
|
|
100
|
-
```sh
|
|
101
|
-
node index.js
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
The code imports the `requestSuiFromFaucetV2` function from the SDK and calls it to mint SUI for the
|
|
105
|
-
provided address. The code also imports `SuiGrpcClient` to create a new client on the Sui network
|
|
106
|
-
that it uses to query the address and output the amount of SUI the address owns before and after
|
|
107
|
-
using the faucet. You can check the total SUI for your address using the Sui Wallet or Sui Client
|
|
108
|
-
CLI.
|
|
109
|
-
|
|
110
|
-
> **Note:** Faucets on Devnet and Testnet are rate limited. If you run the script too many times, you surpass
|
|
111
|
-
> the limit and must wait to successfully run it again. For Testnet, the best way to get SUI is
|
|
112
|
-
> through the Web UI: `faucet.sui.io`.
|
|
113
|
-
|
|
114
|
-
You can also use the [Sui Client CLI](https://docs.sui.io/references/cli/client) to perform client
|
|
115
|
-
calls on a Sui network.
|
package/docs/install.md
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# Install Sui TypeScript SDK
|
|
2
|
-
|
|
3
|
-
> Install the @mysten/sui package and configure your project.
|
|
4
|
-
|
|
5
|
-
The Sui TypeScript SDK is available in the
|
|
6
|
-
[Sui TS SDK monorepo](https://github.com/MystenLabs/ts-sdks) and NPM.
|
|
7
|
-
|
|
8
|
-
## Install from NPM
|
|
9
|
-
|
|
10
|
-
To use the Sui TypeScript SDK in your project, run the following command in your project root:
|
|
11
|
-
|
|
12
|
-
```sh npm2yarn
|
|
13
|
-
npm i @mysten/sui
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
The SDK is published as an ESM only package. Make sure your `package.json` includes
|
|
17
|
-
`"type": "module"`:
|
|
18
|
-
|
|
19
|
-
```json
|
|
20
|
-
{
|
|
21
|
-
"type": "module"
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
If you are using TypeScript, your `tsconfig.json` should use a compatible `moduleResolution` setting
|
|
26
|
-
such as `"NodeNext"`, `"Node16"`, or `"Bundler"`. See the
|
|
27
|
-
[2.0 migration guide](/sui/migrations/sui-2.0#esm-migration) for more details.
|
|
28
|
-
|
|
29
|
-
## Experimental tag for use with a local Sui network
|
|
30
|
-
|
|
31
|
-
Projects developing against one of the onchain Sui networks (Devnet, Testnet, Mainnet) should use
|
|
32
|
-
the base SDK published in the NPM registry (previous section) because the code aligns with the
|
|
33
|
-
relevant JSON-RPC. If you are developing against a
|
|
34
|
-
[local network](https://docs.sui.io/guides/developer/getting-started/local-network) built from the
|
|
35
|
-
`main` branch of the Sui monorepo, however, you should use the `experimental`-tagged SDK package as
|
|
36
|
-
it contains the latest features (or a local build detailed in the section that follows).
|
|
37
|
-
|
|
38
|
-
```sh npm2yarn
|
|
39
|
-
npm i @mysten/sui@experimental
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Install from local build
|
|
43
|
-
|
|
44
|
-
To build the SDK from the Sui monorepo, you must use [pnpm](https://pnpm.io/). With pnpm installed,
|
|
45
|
-
run the following command from the `sui` root directory:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
# Install all dependencies
|
|
49
|
-
pnpm install
|
|
50
|
-
# Run the build for the TypeScript SDK
|
|
51
|
-
pnpm sdk build
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
With the SDK built, you can import the library from your `sui` project. To do so, use a path to the
|
|
55
|
-
`ts-sdks/packages/sui` directory that is relative to your project. For example, if you created a
|
|
56
|
-
folder `my-sui-project` at the same level as `sui`, use the following to import the locally built
|
|
57
|
-
Sui TypeScript package:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
pnpm add ../ts-sdks/packages/sui
|
|
61
|
-
```
|