@pythnetwork/pyth-lazer-sui-js 0.1.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/LICENSE +13 -0
- package/README.md +77 -0
- package/dist/cjs/examples/fetch-and-verify-update.d.ts +1 -0
- package/dist/cjs/examples/fetch-and-verify-update.js +106 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/client.d.ts +10 -0
- package/dist/cjs/src/client.js +16 -0
- package/dist/esm/examples/fetch-and-verify-update.d.ts +1 -0
- package/dist/esm/examples/fetch-and-verify-update.js +101 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/src/client.d.ts +10 -0
- package/dist/esm/src/client.js +14 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2025 Pyth Data Association.
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Pyth Lazer Sui JS SDK
|
|
2
|
+
|
|
3
|
+
This package provides utilities to create a Sui Programmable Transaction to parse & verify a Pyth Lazer price update on-chain.
|
|
4
|
+
|
|
5
|
+
## Build
|
|
6
|
+
|
|
7
|
+
From the repository root:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm turbo build -F @pythnetwork/pyth-lazer-sui-js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
A runnable example is provided at `examples/FetchAndVerifyUpdate.ts`. It:
|
|
16
|
+
|
|
17
|
+
- connects to Lazer via `@pythnetwork/pyth-lazer-sdk`,
|
|
18
|
+
- fetches a single `leEcdsa` payload,
|
|
19
|
+
- composes a Sui transaction calling `parse_and_verify_le_ecdsa_update`.
|
|
20
|
+
|
|
21
|
+
### Run the example
|
|
22
|
+
|
|
23
|
+
Install `tsx` to run TypeScript scripts:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm install -g tsx
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Execute the example script:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
SUI_KEY=<YOUR_SUI_PRIVATE_KEY> pnpm -F @pythnetwork/pyth-lazer-sui-js example:fetch-and-verify --fullnodeUrl <SUI_FULLNODE_URL> --packageId <PYTH_LAZER_PACKAGE_ID> --stateObjectId <PYTH_LAZER_STATE_OBJECT_ID> --token <LAZER_TOKEN>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The script's core logic is summarized below:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { SuiClient } from "@mysten/sui/client";
|
|
39
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
40
|
+
import { SuiLazerClient } from "@pythnetwork/pyth-lazer-sui-js";
|
|
41
|
+
|
|
42
|
+
// Prepare Mysten Sui client
|
|
43
|
+
const provider = new SuiClient({ url: "<sui-fullnode-url>" });
|
|
44
|
+
|
|
45
|
+
// Create SDK client
|
|
46
|
+
const client = new SuiLazerClient(provider);
|
|
47
|
+
|
|
48
|
+
// Obtain a Lazer leEcdsa payload using @pythnetwork/pyth-lazer-sdk.
|
|
49
|
+
// See examples/FetchAndVerifyUpdate.ts for a runnable end-to-end example.
|
|
50
|
+
const leEcdsa: Buffer = /* fetch via @pythnetwork/pyth-lazer-sdk */ Buffer.from(
|
|
51
|
+
[],
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Build transaction calling parse_and_verify_le_ecdsa_update
|
|
55
|
+
const tx = new Transaction();
|
|
56
|
+
const packageId = "<pyth_lazer_package_id>";
|
|
57
|
+
const stateObjectId = "<pyth_lazer_state_object_id>";
|
|
58
|
+
|
|
59
|
+
const updateVal = client.addParseAndVerifyLeEcdsaUpdateCall({
|
|
60
|
+
tx,
|
|
61
|
+
packageId,
|
|
62
|
+
stateObjectId,
|
|
63
|
+
updateBytes: leEcdsa,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Sign and execute the transaction using your signer.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Notes
|
|
70
|
+
|
|
71
|
+
- FIXME: Automatic `packageId` management is coming soon. The Lazer contract doesn't support upgradeability yet.
|
|
72
|
+
|
|
73
|
+
## References
|
|
74
|
+
|
|
75
|
+
- Pyth Lazer Sui contract: `lazer/contracts/sui/`
|
|
76
|
+
- Lazer JS SDK (data source): `lazer/sdk/js/`
|
|
77
|
+
- Mysten Sui TS SDK docs: https://sdk.mystenlabs.com/typescript/transaction-building/basics
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const client_1 = require("@mysten/sui/client");
|
|
7
|
+
const ed25519_1 = require("@mysten/sui/keypairs/ed25519");
|
|
8
|
+
const transactions_1 = require("@mysten/sui/transactions");
|
|
9
|
+
const pyth_lazer_sdk_1 = require("@pythnetwork/pyth-lazer-sdk");
|
|
10
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
11
|
+
const helpers_1 = require("yargs/helpers");
|
|
12
|
+
const client_js_1 = require("../src/client.js");
|
|
13
|
+
async function getOneLeEcdsaUpdate(urls, token) {
|
|
14
|
+
const lazer = await pyth_lazer_sdk_1.PythLazerClient.create({
|
|
15
|
+
urls,
|
|
16
|
+
token,
|
|
17
|
+
numConnections: 1,
|
|
18
|
+
});
|
|
19
|
+
const subscription = {
|
|
20
|
+
subscriptionId: 1,
|
|
21
|
+
type: "subscribe",
|
|
22
|
+
priceFeedIds: [1],
|
|
23
|
+
properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"],
|
|
24
|
+
formats: ["leEcdsa"],
|
|
25
|
+
channel: "fixed_rate@200ms",
|
|
26
|
+
deliveryFormat: "binary",
|
|
27
|
+
jsonBinaryEncoding: "hex",
|
|
28
|
+
};
|
|
29
|
+
lazer.subscribe(subscription);
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
lazer.addMessageListener((event) => {
|
|
32
|
+
if (event.type === "binary" && event.value.leEcdsa) {
|
|
33
|
+
const buf = event.value.leEcdsa;
|
|
34
|
+
// For the purposes of this example, we only need one update.
|
|
35
|
+
lazer.shutdown();
|
|
36
|
+
resolve(buf);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async function main() {
|
|
42
|
+
const args = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
43
|
+
.option("fullnodeUrl", {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "URL of the full Sui node RPC endpoint. e.g: https://fullnode.testnet.sui.io:443",
|
|
46
|
+
demandOption: true,
|
|
47
|
+
})
|
|
48
|
+
.option("packageId", {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Lazer contract package ID",
|
|
51
|
+
demandOption: true,
|
|
52
|
+
})
|
|
53
|
+
.option("stateObjectId", {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Lazer contract shared State object ID",
|
|
56
|
+
demandOption: true,
|
|
57
|
+
})
|
|
58
|
+
.option("lazerUrls", {
|
|
59
|
+
type: "array",
|
|
60
|
+
string: true,
|
|
61
|
+
description: "Lazer WebSocket URLs",
|
|
62
|
+
default: [
|
|
63
|
+
"wss://pyth-lazer-0.dourolabs.app/v1/stream",
|
|
64
|
+
"wss://pyth-lazer-1.dourolabs.app/v1/stream",
|
|
65
|
+
],
|
|
66
|
+
})
|
|
67
|
+
.option("lazerToken", {
|
|
68
|
+
type: "string",
|
|
69
|
+
description: "Lazer authentication token",
|
|
70
|
+
demandOption: true,
|
|
71
|
+
})
|
|
72
|
+
.help()
|
|
73
|
+
.parseAsync();
|
|
74
|
+
// Defined as a dependency in turbo.json
|
|
75
|
+
// eslint-disable-next-line n/no-process-env
|
|
76
|
+
if (process.env.SUI_KEY === undefined) {
|
|
77
|
+
throw new Error(`SUI_KEY environment variable should be set to your Sui private key in hex format.`);
|
|
78
|
+
}
|
|
79
|
+
const provider = new client_1.SuiClient({ url: args.fullnodeUrl });
|
|
80
|
+
// Fetch the price update
|
|
81
|
+
const updateBytes = await getOneLeEcdsaUpdate(args.lazerUrls, args.lazerToken);
|
|
82
|
+
// Build the Sui transaction
|
|
83
|
+
const tx = new transactions_1.Transaction();
|
|
84
|
+
// Add the parse and verify call
|
|
85
|
+
(0, client_js_1.addParseAndVerifyLeEcdsaUpdateCall)({
|
|
86
|
+
tx,
|
|
87
|
+
packageId: args.packageId,
|
|
88
|
+
stateObjectId: args.stateObjectId,
|
|
89
|
+
updateBytes,
|
|
90
|
+
});
|
|
91
|
+
// --- You can add more calls to the transaction that consume the parsed update here ---
|
|
92
|
+
const wallet = ed25519_1.Ed25519Keypair.fromSecretKey(
|
|
93
|
+
// eslint-disable-next-line n/no-process-env
|
|
94
|
+
Buffer.from(process.env.SUI_KEY, "hex"));
|
|
95
|
+
const res = await provider.signAndExecuteTransaction({
|
|
96
|
+
signer: wallet,
|
|
97
|
+
transaction: tx,
|
|
98
|
+
options: { showEffects: true, showEvents: true },
|
|
99
|
+
});
|
|
100
|
+
// eslint-disable-next-line no-console
|
|
101
|
+
console.log("Execution result:", JSON.stringify(res, undefined, 2));
|
|
102
|
+
}
|
|
103
|
+
// eslint-disable-next-line unicorn/prefer-top-level-await
|
|
104
|
+
main().catch((error) => {
|
|
105
|
+
throw error;
|
|
106
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
2
|
+
export declare function addParseAndVerifyLeEcdsaUpdateCall({ tx, packageId, stateObjectId, updateBytes, }: {
|
|
3
|
+
tx: Transaction;
|
|
4
|
+
packageId: string;
|
|
5
|
+
stateObjectId: string;
|
|
6
|
+
updateBytes: Uint8Array;
|
|
7
|
+
}): {
|
|
8
|
+
$kind: "NestedResult";
|
|
9
|
+
NestedResult: [number, number];
|
|
10
|
+
} | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addParseAndVerifyLeEcdsaUpdateCall = addParseAndVerifyLeEcdsaUpdateCall;
|
|
4
|
+
const bcs_1 = require("@mysten/sui/bcs");
|
|
5
|
+
const utils_1 = require("@mysten/sui/utils");
|
|
6
|
+
function addParseAndVerifyLeEcdsaUpdateCall({ tx, packageId, stateObjectId, updateBytes, }) {
|
|
7
|
+
const [updateObj] = tx.moveCall({
|
|
8
|
+
target: `${packageId}::pyth_lazer::parse_and_verify_le_ecdsa_update`,
|
|
9
|
+
arguments: [
|
|
10
|
+
tx.object(stateObjectId),
|
|
11
|
+
tx.object(utils_1.SUI_CLOCK_OBJECT_ID),
|
|
12
|
+
tx.pure(bcs_1.bcs.vector(bcs_1.bcs.U8).serialize(updateBytes).toBytes()),
|
|
13
|
+
],
|
|
14
|
+
});
|
|
15
|
+
return updateObj;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { SuiClient } from "@mysten/sui/client";
|
|
2
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
|
|
3
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
4
|
+
import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk";
|
|
5
|
+
import yargs from "yargs";
|
|
6
|
+
import { hideBin } from "yargs/helpers";
|
|
7
|
+
import { addParseAndVerifyLeEcdsaUpdateCall } from "../src/client.js";
|
|
8
|
+
async function getOneLeEcdsaUpdate(urls, token) {
|
|
9
|
+
const lazer = await PythLazerClient.create({
|
|
10
|
+
urls,
|
|
11
|
+
token,
|
|
12
|
+
numConnections: 1,
|
|
13
|
+
});
|
|
14
|
+
const subscription = {
|
|
15
|
+
subscriptionId: 1,
|
|
16
|
+
type: "subscribe",
|
|
17
|
+
priceFeedIds: [1],
|
|
18
|
+
properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"],
|
|
19
|
+
formats: ["leEcdsa"],
|
|
20
|
+
channel: "fixed_rate@200ms",
|
|
21
|
+
deliveryFormat: "binary",
|
|
22
|
+
jsonBinaryEncoding: "hex",
|
|
23
|
+
};
|
|
24
|
+
lazer.subscribe(subscription);
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
lazer.addMessageListener((event) => {
|
|
27
|
+
if (event.type === "binary" && event.value.leEcdsa) {
|
|
28
|
+
const buf = event.value.leEcdsa;
|
|
29
|
+
// For the purposes of this example, we only need one update.
|
|
30
|
+
lazer.shutdown();
|
|
31
|
+
resolve(buf);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function main() {
|
|
37
|
+
const args = await yargs(hideBin(process.argv))
|
|
38
|
+
.option("fullnodeUrl", {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "URL of the full Sui node RPC endpoint. e.g: https://fullnode.testnet.sui.io:443",
|
|
41
|
+
demandOption: true,
|
|
42
|
+
})
|
|
43
|
+
.option("packageId", {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Lazer contract package ID",
|
|
46
|
+
demandOption: true,
|
|
47
|
+
})
|
|
48
|
+
.option("stateObjectId", {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Lazer contract shared State object ID",
|
|
51
|
+
demandOption: true,
|
|
52
|
+
})
|
|
53
|
+
.option("lazerUrls", {
|
|
54
|
+
type: "array",
|
|
55
|
+
string: true,
|
|
56
|
+
description: "Lazer WebSocket URLs",
|
|
57
|
+
default: [
|
|
58
|
+
"wss://pyth-lazer-0.dourolabs.app/v1/stream",
|
|
59
|
+
"wss://pyth-lazer-1.dourolabs.app/v1/stream",
|
|
60
|
+
],
|
|
61
|
+
})
|
|
62
|
+
.option("lazerToken", {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "Lazer authentication token",
|
|
65
|
+
demandOption: true,
|
|
66
|
+
})
|
|
67
|
+
.help()
|
|
68
|
+
.parseAsync();
|
|
69
|
+
// Defined as a dependency in turbo.json
|
|
70
|
+
// eslint-disable-next-line n/no-process-env
|
|
71
|
+
if (process.env.SUI_KEY === undefined) {
|
|
72
|
+
throw new Error(`SUI_KEY environment variable should be set to your Sui private key in hex format.`);
|
|
73
|
+
}
|
|
74
|
+
const provider = new SuiClient({ url: args.fullnodeUrl });
|
|
75
|
+
// Fetch the price update
|
|
76
|
+
const updateBytes = await getOneLeEcdsaUpdate(args.lazerUrls, args.lazerToken);
|
|
77
|
+
// Build the Sui transaction
|
|
78
|
+
const tx = new Transaction();
|
|
79
|
+
// Add the parse and verify call
|
|
80
|
+
addParseAndVerifyLeEcdsaUpdateCall({
|
|
81
|
+
tx,
|
|
82
|
+
packageId: args.packageId,
|
|
83
|
+
stateObjectId: args.stateObjectId,
|
|
84
|
+
updateBytes,
|
|
85
|
+
});
|
|
86
|
+
// --- You can add more calls to the transaction that consume the parsed update here ---
|
|
87
|
+
const wallet = Ed25519Keypair.fromSecretKey(
|
|
88
|
+
// eslint-disable-next-line n/no-process-env
|
|
89
|
+
Buffer.from(process.env.SUI_KEY, "hex"));
|
|
90
|
+
const res = await provider.signAndExecuteTransaction({
|
|
91
|
+
signer: wallet,
|
|
92
|
+
transaction: tx,
|
|
93
|
+
options: { showEffects: true, showEvents: true },
|
|
94
|
+
});
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
console.log("Execution result:", JSON.stringify(res, undefined, 2));
|
|
97
|
+
}
|
|
98
|
+
// eslint-disable-next-line unicorn/prefer-top-level-await
|
|
99
|
+
main().catch((error) => {
|
|
100
|
+
throw error;
|
|
101
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
2
|
+
export declare function addParseAndVerifyLeEcdsaUpdateCall({ tx, packageId, stateObjectId, updateBytes, }: {
|
|
3
|
+
tx: Transaction;
|
|
4
|
+
packageId: string;
|
|
5
|
+
stateObjectId: string;
|
|
6
|
+
updateBytes: Uint8Array;
|
|
7
|
+
}): {
|
|
8
|
+
$kind: "NestedResult";
|
|
9
|
+
NestedResult: [number, number];
|
|
10
|
+
} | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
2
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
3
|
+
import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils";
|
|
4
|
+
export function addParseAndVerifyLeEcdsaUpdateCall({ tx, packageId, stateObjectId, updateBytes, }) {
|
|
5
|
+
const [updateObj] = tx.moveCall({
|
|
6
|
+
target: `${packageId}::pyth_lazer::parse_and_verify_le_ecdsa_update`,
|
|
7
|
+
arguments: [
|
|
8
|
+
tx.object(stateObjectId),
|
|
9
|
+
tx.object(SUI_CLOCK_OBJECT_ID),
|
|
10
|
+
tx.pure(bcs.vector(bcs.U8).serialize(updateBytes).toBytes()),
|
|
11
|
+
],
|
|
12
|
+
});
|
|
13
|
+
return updateObj;
|
|
14
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pythnetwork/pyth-lazer-sui-js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript SDK for the Pyth Lazer Sui contract",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": "22"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": {
|
|
16
|
+
"types": "./dist/esm/client.d.ts",
|
|
17
|
+
"default": "./dist/esm/client.js"
|
|
18
|
+
},
|
|
19
|
+
"require": {
|
|
20
|
+
"types": "./dist/cjs/client.d.ts",
|
|
21
|
+
"default": "./dist/cjs/client.js"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@mysten/sui": "^1.3.0",
|
|
28
|
+
"@types/yargs": "^17.0.33",
|
|
29
|
+
"yargs": "^18.0.0",
|
|
30
|
+
"@pythnetwork/pyth-lazer-sdk": "2.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@cprussin/eslint-config": "^4.0.2",
|
|
34
|
+
"@cprussin/tsconfig": "^3.1.2",
|
|
35
|
+
"@types/node": "^22.14.0",
|
|
36
|
+
"eslint": "^9.23.0",
|
|
37
|
+
"prettier": "^3.5.3",
|
|
38
|
+
"typescript": "^5.8.2"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build:cjs": "tsc --project tsconfig.build.json --verbatimModuleSyntax false --module commonjs --outDir ./dist/cjs && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
45
|
+
"build:esm": "tsc --project tsconfig.build.json --outDir ./dist/esm && echo '{\"type\":\"module\"}' > dist/esm/package.json",
|
|
46
|
+
"fix:format": "prettier --write .",
|
|
47
|
+
"fix:lint": "eslint --fix .",
|
|
48
|
+
"test:format": "prettier --check .",
|
|
49
|
+
"test:lint": "eslint . --max-warnings 0",
|
|
50
|
+
"test:types": "tsc",
|
|
51
|
+
"example:fetch-and-verify": "tsx examples/fetch-and-verify-update.ts"
|
|
52
|
+
}
|
|
53
|
+
}
|