@pythnetwork/pyth-lazer-sui-js 0.1.2 → 0.3.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/README.md +40 -32
- package/dist/cjs/index.cjs +51 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/package.json +1 -1
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.mjs +41 -0
- package/dist/esm/package.json +1 -1
- package/package.json +43 -29
- package/dist/cjs/examples/fetch-and-verify-update.d.ts +0 -1
- package/dist/cjs/examples/fetch-and-verify-update.js +0 -91
- package/dist/cjs/src/client.d.ts +0 -10
- package/dist/cjs/src/client.js +0 -16
- package/dist/esm/examples/fetch-and-verify-update.d.ts +0 -1
- package/dist/esm/examples/fetch-and-verify-update.js +0 -86
- package/dist/esm/src/client.d.ts +0 -10
- package/dist/esm/src/client.js +0 -14
package/README.md
CHANGED
|
@@ -20,16 +20,22 @@ A runnable example is provided at `examples/FetchAndVerifyUpdate.ts`. It:
|
|
|
20
20
|
|
|
21
21
|
### Run the example
|
|
22
22
|
|
|
23
|
-
Install `tsx` to run TypeScript scripts:
|
|
24
|
-
|
|
25
23
|
```sh
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
# Your Sui private key in Bech32 format
|
|
25
|
+
# SUI_KEY=
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
# Lazer contract state ID
|
|
28
|
+
# STATE_ID=
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
# Your Lazer API token
|
|
31
|
+
# LAZER_TOKEN=
|
|
32
|
+
|
|
33
|
+
SUI_FULLNODE_URL="https://fullnode.mainnet.sui.io:443"
|
|
34
|
+
|
|
35
|
+
pnpm run example:fetch-and-verify \
|
|
36
|
+
--fullnode-url "$SUI_FULLNODE_URL" \
|
|
37
|
+
--state-id "$STATE_ID" \
|
|
38
|
+
--lazer-token "$LAZER_TOKEN"
|
|
33
39
|
```
|
|
34
40
|
|
|
35
41
|
The script's core logic is summarized below:
|
|
@@ -37,38 +43,40 @@ The script's core logic is summarized below:
|
|
|
37
43
|
```ts
|
|
38
44
|
import { SuiClient } from "@mysten/sui/client";
|
|
39
45
|
import { Transaction } from "@mysten/sui/transactions";
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
);
|
|
46
|
+
import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk";
|
|
47
|
+
import { addParseAndVerifyLeEcdsaUpdateCall } from "@pythnetwork/pyth-lazer-sui-js";
|
|
48
|
+
|
|
49
|
+
// 1. Fetch the price update from Pyth Lazer in "leEcdsa" format:
|
|
50
|
+
const lazer = await PythLazerClient.create({ token: lazerToken });
|
|
51
|
+
const latestPrice = await lazer.getLatestPrice({
|
|
52
|
+
priceFeedIds: [1],
|
|
53
|
+
properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"],
|
|
54
|
+
formats: ["leEcdsa"],
|
|
55
|
+
channel: "fixed_rate@200ms",
|
|
56
|
+
jsonBinaryEncoding: "hex",
|
|
57
|
+
});
|
|
58
|
+
const update = Buffer.from(latestPrice.leEcdsa?.data ?? "", "hex");
|
|
53
59
|
|
|
54
|
-
//
|
|
60
|
+
// 2. Create a new Sui transaction:
|
|
61
|
+
const client = new SuiClient({ url: fullnodeUrl });
|
|
55
62
|
const tx = new Transaction();
|
|
56
|
-
const packageId = "<pyth_lazer_package_id>";
|
|
57
|
-
const stateObjectId = "<pyth_lazer_state_object_id>";
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
// 3. Add the parse and verify call:
|
|
65
|
+
const verifiedUpdate = await addParseAndVerifyLeEcdsaUpdateCall({
|
|
66
|
+
client,
|
|
60
67
|
tx,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
updateBytes: leEcdsa,
|
|
68
|
+
stateObjectId: stateId,
|
|
69
|
+
update,
|
|
64
70
|
});
|
|
65
71
|
|
|
66
|
-
//
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Notes
|
|
72
|
+
// 4. Consume `verifiedUpdate` in your own contract with additional calls...
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
// 5. Sign and execute the transaction:
|
|
75
|
+
const result = await client.signAndExecuteTransaction({
|
|
76
|
+
transaction: tx,
|
|
77
|
+
signer,
|
|
78
|
+
});
|
|
79
|
+
```
|
|
72
80
|
|
|
73
81
|
## References
|
|
74
82
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "addParseAndVerifyLeEcdsaUpdateCall", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return addParseAndVerifyLeEcdsaUpdateCall;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
async function addParseAndVerifyLeEcdsaUpdateCall(opts) {
|
|
12
|
+
const { client, tx, stateObjectId, update } = opts;
|
|
13
|
+
const latestPackageId = await getLatestPackageId(client, stateObjectId);
|
|
14
|
+
return tx.moveCall({
|
|
15
|
+
target: `${latestPackageId}::pyth_lazer::parse_and_verify_le_ecdsa_update`,
|
|
16
|
+
arguments: [
|
|
17
|
+
tx.object(stateObjectId),
|
|
18
|
+
tx.object.clock(),
|
|
19
|
+
tx.pure.vector("u8", update)
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async function getLatestPackageId(client, stateObjectId) {
|
|
24
|
+
const { data: stateObject, error } = await client.getObject({
|
|
25
|
+
id: stateObjectId,
|
|
26
|
+
options: {
|
|
27
|
+
showContent: true
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
if (!stateObject?.content || error) {
|
|
31
|
+
throw new Error(`Failed to get Sui Lazer State: ${error?.code ?? "undefined"}`);
|
|
32
|
+
}
|
|
33
|
+
if (stateObject.content.dataType !== "moveObject") {
|
|
34
|
+
throw new Error(`Sui Lazer State must be an object, got: ${stateObject.content.dataType}`);
|
|
35
|
+
}
|
|
36
|
+
const state = stateObject.content;
|
|
37
|
+
if (!hasStructField(state, "upgrade_cap")) {
|
|
38
|
+
throw new Error("Missing 'upgrade_cap' in Sui Lazer State");
|
|
39
|
+
}
|
|
40
|
+
const upgradeCap = state.fields.upgrade_cap;
|
|
41
|
+
if (!hasStructField(upgradeCap, "package") || typeof upgradeCap.fields.package !== "string") {
|
|
42
|
+
throw new Error("Could not find 'package' string in Sui Lazer UpgradeCap");
|
|
43
|
+
}
|
|
44
|
+
return upgradeCap.fields.package;
|
|
45
|
+
}
|
|
46
|
+
function hasStructField(value, name) {
|
|
47
|
+
return hasProperty(value, "fields") && hasProperty(value.fields, name);
|
|
48
|
+
}
|
|
49
|
+
function hasProperty(value, name) {
|
|
50
|
+
return typeof value === "object" && !!value && name in value;
|
|
51
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SuiClient } from "@mysten/sui/client";
|
|
2
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
3
|
+
export declare function addParseAndVerifyLeEcdsaUpdateCall(opts: {
|
|
4
|
+
client: SuiClient;
|
|
5
|
+
tx: Transaction;
|
|
6
|
+
stateObjectId: string;
|
|
7
|
+
update: Uint8Array;
|
|
8
|
+
}): Promise<import("@mysten/sui/transactions").TransactionResult>;
|
package/dist/cjs/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"commonjs"}
|
|
1
|
+
{ "type": "commonjs" }
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SuiClient } from "@mysten/sui/client";
|
|
2
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
3
|
+
export declare function addParseAndVerifyLeEcdsaUpdateCall(opts: {
|
|
4
|
+
client: SuiClient;
|
|
5
|
+
tx: Transaction;
|
|
6
|
+
stateObjectId: string;
|
|
7
|
+
update: Uint8Array;
|
|
8
|
+
}): Promise<import("@mysten/sui/transactions").TransactionResult>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export async function addParseAndVerifyLeEcdsaUpdateCall(opts) {
|
|
2
|
+
const { client, tx, stateObjectId, update } = opts;
|
|
3
|
+
const latestPackageId = await getLatestPackageId(client, stateObjectId);
|
|
4
|
+
return tx.moveCall({
|
|
5
|
+
target: `${latestPackageId}::pyth_lazer::parse_and_verify_le_ecdsa_update`,
|
|
6
|
+
arguments: [
|
|
7
|
+
tx.object(stateObjectId),
|
|
8
|
+
tx.object.clock(),
|
|
9
|
+
tx.pure.vector("u8", update)
|
|
10
|
+
]
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
async function getLatestPackageId(client, stateObjectId) {
|
|
14
|
+
const { data: stateObject, error } = await client.getObject({
|
|
15
|
+
id: stateObjectId,
|
|
16
|
+
options: {
|
|
17
|
+
showContent: true
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
if (!stateObject?.content || error) {
|
|
21
|
+
throw new Error(`Failed to get Sui Lazer State: ${error?.code ?? "undefined"}`);
|
|
22
|
+
}
|
|
23
|
+
if (stateObject.content.dataType !== "moveObject") {
|
|
24
|
+
throw new Error(`Sui Lazer State must be an object, got: ${stateObject.content.dataType}`);
|
|
25
|
+
}
|
|
26
|
+
const state = stateObject.content;
|
|
27
|
+
if (!hasStructField(state, "upgrade_cap")) {
|
|
28
|
+
throw new Error("Missing 'upgrade_cap' in Sui Lazer State");
|
|
29
|
+
}
|
|
30
|
+
const upgradeCap = state.fields.upgrade_cap;
|
|
31
|
+
if (!hasStructField(upgradeCap, "package") || typeof upgradeCap.fields.package !== "string") {
|
|
32
|
+
throw new Error("Could not find 'package' string in Sui Lazer UpgradeCap");
|
|
33
|
+
}
|
|
34
|
+
return upgradeCap.fields.package;
|
|
35
|
+
}
|
|
36
|
+
function hasStructField(value, name) {
|
|
37
|
+
return hasProperty(value, "fields") && hasProperty(value.fields, name);
|
|
38
|
+
}
|
|
39
|
+
function hasProperty(value, name) {
|
|
40
|
+
return typeof value === "object" && !!value && name in value;
|
|
41
|
+
}
|
package/dist/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module"}
|
|
1
|
+
{ "type": "module" }
|
package/package.json
CHANGED
|
@@ -1,53 +1,67 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pythnetwork/pyth-lazer-sui-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "TypeScript SDK for the Pyth Lazer Sui contract",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": "22"
|
|
9
|
-
},
|
|
10
7
|
"files": [
|
|
11
|
-
"dist"
|
|
8
|
+
"dist/**"
|
|
12
9
|
],
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"default": "./dist/esm/client.js"
|
|
18
|
-
},
|
|
19
|
-
"require": {
|
|
20
|
-
"types": "./dist/cjs/client.d.ts",
|
|
21
|
-
"default": "./dist/cjs/client.js"
|
|
22
|
-
}
|
|
23
|
-
}
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/pyth-network/pyth-crosschain",
|
|
13
|
+
"directory": "lazer/contracts/pyth-lazer-sui-js"
|
|
24
14
|
},
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
"@mysten/sui": "^1.3.0",
|
|
28
|
-
"@types/yargs": "^17.0.33",
|
|
29
|
-
"yargs": "^18.0.0",
|
|
30
|
-
"@pythnetwork/pyth-lazer-sdk": "4.0.0"
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": "^24.0.0"
|
|
31
17
|
},
|
|
18
|
+
"sideEffects": false,
|
|
32
19
|
"devDependencies": {
|
|
33
20
|
"@cprussin/eslint-config": "^4.0.2",
|
|
21
|
+
"@cprussin/prettier-config": "^2.2.2",
|
|
34
22
|
"@cprussin/tsconfig": "^3.1.2",
|
|
23
|
+
"@pythnetwork/jest-config": "",
|
|
24
|
+
"@types/jest": "^29.5.14",
|
|
35
25
|
"@types/node": "^22.14.0",
|
|
26
|
+
"@types/yargs": "^17.0.33",
|
|
36
27
|
"eslint": "^9.23.0",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
28
|
+
"jest": "^29.7.0",
|
|
29
|
+
"tsx": "4.20.6",
|
|
30
|
+
"yargs": "^18.0.0",
|
|
31
|
+
"@pythnetwork/pyth-lazer-sdk": "5.2.1"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@mysten/sui": "^1.3.0"
|
|
39
35
|
},
|
|
36
|
+
"private": false,
|
|
40
37
|
"publishConfig": {
|
|
41
38
|
"access": "public"
|
|
42
39
|
},
|
|
40
|
+
"exports": {
|
|
41
|
+
".": {
|
|
42
|
+
"require": {
|
|
43
|
+
"types": "./dist/cjs/index.d.ts",
|
|
44
|
+
"default": "./dist/cjs/index.cjs"
|
|
45
|
+
},
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./dist/esm/index.d.ts",
|
|
48
|
+
"default": "./dist/esm/index.mjs"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"./package.json": "./package.json"
|
|
52
|
+
},
|
|
53
|
+
"module": "./dist/esm/index.mjs",
|
|
54
|
+
"types": "./dist/cjs/index.d.ts",
|
|
55
|
+
"main": "./dist/cjs/index.cjs",
|
|
43
56
|
"scripts": {
|
|
44
|
-
"build
|
|
45
|
-
"
|
|
57
|
+
"build": "ts-duality --copyOtherFiles",
|
|
58
|
+
"clean": "rm -rf ./dist",
|
|
59
|
+
"fix:lint": "eslint --fix . --max-warnings 0",
|
|
46
60
|
"fix:format": "prettier --write .",
|
|
47
|
-
"fix:lint": "eslint --fix .",
|
|
48
|
-
"test:format": "prettier --check .",
|
|
49
61
|
"test:lint": "eslint . --max-warnings 0",
|
|
62
|
+
"test:format": "prettier --check .",
|
|
50
63
|
"test:types": "tsc",
|
|
51
|
-
"
|
|
64
|
+
"test:unit": "test-unit",
|
|
65
|
+
"example:fetch-and-verify": "tsx src/examples/fetch-and-verify.ts"
|
|
52
66
|
}
|
|
53
67
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,91 +0,0 @@
|
|
|
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(token) {
|
|
14
|
-
const lazer = await pyth_lazer_sdk_1.PythLazerClient.create({
|
|
15
|
-
token,
|
|
16
|
-
});
|
|
17
|
-
const latestPrice = await lazer.getLatestPrice({
|
|
18
|
-
priceFeedIds: [1],
|
|
19
|
-
properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"],
|
|
20
|
-
formats: ["leEcdsa"],
|
|
21
|
-
channel: "fixed_rate@200ms",
|
|
22
|
-
jsonBinaryEncoding: "hex",
|
|
23
|
-
});
|
|
24
|
-
return latestPrice;
|
|
25
|
-
}
|
|
26
|
-
async function main() {
|
|
27
|
-
const args = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
28
|
-
.option("fullnodeUrl", {
|
|
29
|
-
type: "string",
|
|
30
|
-
description: "URL of the full Sui node RPC endpoint. e.g: https://fullnode.testnet.sui.io:443",
|
|
31
|
-
demandOption: true,
|
|
32
|
-
})
|
|
33
|
-
.option("packageId", {
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "Lazer contract package ID",
|
|
36
|
-
demandOption: true,
|
|
37
|
-
})
|
|
38
|
-
.option("stateObjectId", {
|
|
39
|
-
type: "string",
|
|
40
|
-
description: "Lazer contract shared State object ID",
|
|
41
|
-
demandOption: true,
|
|
42
|
-
})
|
|
43
|
-
.option("lazerUrls", {
|
|
44
|
-
type: "array",
|
|
45
|
-
string: true,
|
|
46
|
-
description: "Lazer WebSocket URLs",
|
|
47
|
-
default: [
|
|
48
|
-
"wss://pyth-lazer-0.dourolabs.app/v1/stream",
|
|
49
|
-
"wss://pyth-lazer-1.dourolabs.app/v1/stream",
|
|
50
|
-
],
|
|
51
|
-
})
|
|
52
|
-
.option("lazerToken", {
|
|
53
|
-
type: "string",
|
|
54
|
-
description: "Lazer authentication token",
|
|
55
|
-
demandOption: true,
|
|
56
|
-
})
|
|
57
|
-
.help()
|
|
58
|
-
.parseAsync();
|
|
59
|
-
// Defined as a dependency in turbo.json
|
|
60
|
-
// eslint-disable-next-line n/no-process-env
|
|
61
|
-
if (process.env.SUI_KEY === undefined) {
|
|
62
|
-
throw new Error(`SUI_KEY environment variable should be set to your Sui private key in hex format.`);
|
|
63
|
-
}
|
|
64
|
-
const provider = new client_1.SuiClient({ url: args.fullnodeUrl });
|
|
65
|
-
// Fetch the price update
|
|
66
|
-
const update = await getOneLeEcdsaUpdate(args.lazerToken);
|
|
67
|
-
// Build the Sui transaction
|
|
68
|
-
const tx = new transactions_1.Transaction();
|
|
69
|
-
// Add the parse and verify call
|
|
70
|
-
(0, client_js_1.addParseAndVerifyLeEcdsaUpdateCall)({
|
|
71
|
-
tx,
|
|
72
|
-
packageId: args.packageId,
|
|
73
|
-
stateObjectId: args.stateObjectId,
|
|
74
|
-
updateBytes: Buffer.from(update.leEcdsa?.data ?? "", "hex"),
|
|
75
|
-
});
|
|
76
|
-
// --- You can add more calls to the transaction that consume the parsed update here ---
|
|
77
|
-
const wallet = ed25519_1.Ed25519Keypair.fromSecretKey(
|
|
78
|
-
// eslint-disable-next-line n/no-process-env
|
|
79
|
-
Buffer.from(process.env.SUI_KEY, "hex"));
|
|
80
|
-
const res = await provider.signAndExecuteTransaction({
|
|
81
|
-
signer: wallet,
|
|
82
|
-
transaction: tx,
|
|
83
|
-
options: { showEffects: true, showEvents: true },
|
|
84
|
-
});
|
|
85
|
-
// eslint-disable-next-line no-console
|
|
86
|
-
console.log("Execution result:", JSON.stringify(res, undefined, 2));
|
|
87
|
-
}
|
|
88
|
-
// eslint-disable-next-line unicorn/prefer-top-level-await
|
|
89
|
-
main().catch((error) => {
|
|
90
|
-
throw error;
|
|
91
|
-
});
|
package/dist/cjs/src/client.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
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;
|
package/dist/cjs/src/client.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,86 +0,0 @@
|
|
|
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(token) {
|
|
9
|
-
const lazer = await PythLazerClient.create({
|
|
10
|
-
token,
|
|
11
|
-
});
|
|
12
|
-
const latestPrice = await lazer.getLatestPrice({
|
|
13
|
-
priceFeedIds: [1],
|
|
14
|
-
properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"],
|
|
15
|
-
formats: ["leEcdsa"],
|
|
16
|
-
channel: "fixed_rate@200ms",
|
|
17
|
-
jsonBinaryEncoding: "hex",
|
|
18
|
-
});
|
|
19
|
-
return latestPrice;
|
|
20
|
-
}
|
|
21
|
-
async function main() {
|
|
22
|
-
const args = await yargs(hideBin(process.argv))
|
|
23
|
-
.option("fullnodeUrl", {
|
|
24
|
-
type: "string",
|
|
25
|
-
description: "URL of the full Sui node RPC endpoint. e.g: https://fullnode.testnet.sui.io:443",
|
|
26
|
-
demandOption: true,
|
|
27
|
-
})
|
|
28
|
-
.option("packageId", {
|
|
29
|
-
type: "string",
|
|
30
|
-
description: "Lazer contract package ID",
|
|
31
|
-
demandOption: true,
|
|
32
|
-
})
|
|
33
|
-
.option("stateObjectId", {
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "Lazer contract shared State object ID",
|
|
36
|
-
demandOption: true,
|
|
37
|
-
})
|
|
38
|
-
.option("lazerUrls", {
|
|
39
|
-
type: "array",
|
|
40
|
-
string: true,
|
|
41
|
-
description: "Lazer WebSocket URLs",
|
|
42
|
-
default: [
|
|
43
|
-
"wss://pyth-lazer-0.dourolabs.app/v1/stream",
|
|
44
|
-
"wss://pyth-lazer-1.dourolabs.app/v1/stream",
|
|
45
|
-
],
|
|
46
|
-
})
|
|
47
|
-
.option("lazerToken", {
|
|
48
|
-
type: "string",
|
|
49
|
-
description: "Lazer authentication token",
|
|
50
|
-
demandOption: true,
|
|
51
|
-
})
|
|
52
|
-
.help()
|
|
53
|
-
.parseAsync();
|
|
54
|
-
// Defined as a dependency in turbo.json
|
|
55
|
-
// eslint-disable-next-line n/no-process-env
|
|
56
|
-
if (process.env.SUI_KEY === undefined) {
|
|
57
|
-
throw new Error(`SUI_KEY environment variable should be set to your Sui private key in hex format.`);
|
|
58
|
-
}
|
|
59
|
-
const provider = new SuiClient({ url: args.fullnodeUrl });
|
|
60
|
-
// Fetch the price update
|
|
61
|
-
const update = await getOneLeEcdsaUpdate(args.lazerToken);
|
|
62
|
-
// Build the Sui transaction
|
|
63
|
-
const tx = new Transaction();
|
|
64
|
-
// Add the parse and verify call
|
|
65
|
-
addParseAndVerifyLeEcdsaUpdateCall({
|
|
66
|
-
tx,
|
|
67
|
-
packageId: args.packageId,
|
|
68
|
-
stateObjectId: args.stateObjectId,
|
|
69
|
-
updateBytes: Buffer.from(update.leEcdsa?.data ?? "", "hex"),
|
|
70
|
-
});
|
|
71
|
-
// --- You can add more calls to the transaction that consume the parsed update here ---
|
|
72
|
-
const wallet = Ed25519Keypair.fromSecretKey(
|
|
73
|
-
// eslint-disable-next-line n/no-process-env
|
|
74
|
-
Buffer.from(process.env.SUI_KEY, "hex"));
|
|
75
|
-
const res = await provider.signAndExecuteTransaction({
|
|
76
|
-
signer: wallet,
|
|
77
|
-
transaction: tx,
|
|
78
|
-
options: { showEffects: true, showEvents: true },
|
|
79
|
-
});
|
|
80
|
-
// eslint-disable-next-line no-console
|
|
81
|
-
console.log("Execution result:", JSON.stringify(res, undefined, 2));
|
|
82
|
-
}
|
|
83
|
-
// eslint-disable-next-line unicorn/prefer-top-level-await
|
|
84
|
-
main().catch((error) => {
|
|
85
|
-
throw error;
|
|
86
|
-
});
|
package/dist/esm/src/client.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
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;
|
package/dist/esm/src/client.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
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
|
-
}
|