Fix sui js sdk and bump contract (#1071)

* Bump sui version

* Add sui cli package to lerna

* Fix bug in fetching price feed object ids after upgrade
This commit is contained in:
Amin Moghaddam 2023-09-29 10:52:41 +02:00 committed by GitHub
parent 916d9463b2
commit 061f6a028d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1199 additions and 88 deletions

View File

@ -14,6 +14,7 @@ import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
export class SuiContract extends Contract { export class SuiContract extends Contract {
static type = "SuiContract"; static type = "SuiContract";
private client: SuiPythClient;
/** /**
* Given the ids of the pyth state and wormhole state, create a new SuiContract * Given the ids of the pyth state and wormhole state, create a new SuiContract
@ -29,6 +30,11 @@ export class SuiContract extends Contract {
public wormholeStateId: string public wormholeStateId: string
) { ) {
super(); super();
this.client = new SuiPythClient(
this.getProvider(),
this.stateId,
this.wormholeStateId
);
} }
static fromJson( static fromJson(
@ -63,8 +69,7 @@ export class SuiContract extends Contract {
* @param objectId * @param objectId
*/ */
async getPackageId(objectId: ObjectId): Promise<ObjectId> { async getPackageId(objectId: ObjectId): Promise<ObjectId> {
const client = this.getSdkClient(); return this.client.getPackageId(objectId);
return client.getPackageId(objectId);
} }
async getPythPackageId(): Promise<ObjectId> { async getPythPackageId(): Promise<ObjectId> {
@ -79,24 +84,6 @@ export class SuiContract extends Contract {
return `${this.chain.getId()}_${this.stateId}`; return `${this.chain.getId()}_${this.stateId}`;
} }
/**
* Fetches the price table object id for the current state id
*/
async getPriceTableId(): Promise<ObjectId> {
const provider = this.getProvider();
const result = await provider.getDynamicFieldObject({
parentId: this.stateId,
name: {
type: "vector<u8>",
value: "price_info",
},
});
if (!result.data) {
throw new Error("Price Table not found, contract may not be initialized");
}
return result.data.objectId;
}
private async parsePrice(priceInfo: { private async parsePrice(priceInfo: {
type: string; type: string;
fields: { fields: {
@ -125,30 +112,9 @@ export class SuiContract extends Contract {
}; };
} }
async getPriceFeedObjectId(feedId: string): Promise<ObjectId | undefined> {
const tableId = await this.getPriceTableId();
const provider = this.getProvider();
const result = await provider.getDynamicFieldObject({
parentId: tableId,
name: {
type: `${await this.getPythPackageId()}::price_identifier::PriceIdentifier`,
value: {
bytes: Array.from(Buffer.from(feedId, "hex")),
},
},
});
if (!result.data || !result.data.content) {
return undefined;
}
if (result.data.content.dataType !== "moveObject") {
throw new Error("Price feed type mismatch");
}
return result.data.content.fields.value;
}
async getPriceFeed(feedId: string) { async getPriceFeed(feedId: string) {
const provider = this.getProvider(); const provider = this.getProvider();
const priceInfoObjectId = await this.getPriceFeedObjectId(feedId); const priceInfoObjectId = await this.client.getPriceFeedObjectId(feedId);
if (!priceInfoObjectId) return undefined; if (!priceInfoObjectId) return undefined;
const priceInfo = await provider.getObject({ const priceInfo = await provider.getObject({
id: priceInfoObjectId, id: priceInfoObjectId,
@ -206,22 +172,13 @@ export class SuiContract extends Contract {
throw new Error("Use executeUpdatePriceFeedWithFeeds instead"); throw new Error("Use executeUpdatePriceFeedWithFeeds instead");
} }
getSdkClient(): SuiPythClient {
return new SuiPythClient(
this.getProvider(),
this.stateId,
this.wormholeStateId
);
}
async executeUpdatePriceFeedWithFeeds( async executeUpdatePriceFeedWithFeeds(
senderPrivateKey: string, senderPrivateKey: string,
vaas: Buffer[], vaas: Buffer[],
feedIds: string[] feedIds: string[]
): Promise<TxResult> { ): Promise<TxResult> {
const tx = new TransactionBlock(); const tx = new TransactionBlock();
const client = this.getSdkClient(); await this.client.updatePriceFeeds(tx, vaas, feedIds);
await client.updatePriceFeeds(tx, vaas, feedIds);
const keypair = Ed25519Keypair.fromSecretKey( const keypair = Ed25519Keypair.fromSecretKey(
Buffer.from(senderPrivateKey, "hex") Buffer.from(senderPrivateKey, "hex")
); );
@ -233,8 +190,7 @@ export class SuiContract extends Contract {
vaas: Buffer[] vaas: Buffer[]
): Promise<TxResult> { ): Promise<TxResult> {
const tx = new TransactionBlock(); const tx = new TransactionBlock();
const client = this.getSdkClient(); await this.client.createPriceFeed(tx, vaas);
await client.createPriceFeed(tx, vaas);
const keypair = Ed25519Keypair.fromSecretKey( const keypair = Ed25519Keypair.fromSecretKey(
Buffer.from(senderPrivateKey, "hex") Buffer.from(senderPrivateKey, "hex")
); );

1182
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
"target_chains/ethereum/sdk/solidity", "target_chains/ethereum/sdk/solidity",
"target_chains/ethereum/examples/oracle_swap/app", "target_chains/ethereum/examples/oracle_swap/app",
"target_chains/sui/sdk/js", "target_chains/sui/sdk/js",
"target_chains/sui/cli",
"third_party/pyth/p2w-relay", "third_party/pyth/p2w-relay",
"wormhole_attester/sdk/js", "wormhole_attester/sdk/js",
"contract_manager" "contract_manager"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "Pyth" name = "Pyth"
version = "0.0.1" version = "0.0.2"
[dependencies.Sui] [dependencies.Sui]
git = "https://github.com/MystenLabs/sui.git" git = "https://github.com/MystenLabs/sui.git"

View File

@ -18,12 +18,12 @@ module pyth::version_control {
// //
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
public(friend) fun current_version(): V__0_1_1 { public(friend) fun current_version(): V__0_1_2 {
V__0_1_1 {} V__0_1_2 {}
} }
public(friend) fun previous_version(): V__DUMMY { public(friend) fun previous_version(): V__0_1_1 {
V__DUMMY {} V__0_1_1 {}
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -35,6 +35,11 @@ module pyth::version_control {
// //
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
/// RELEASE NOTES
///
/// - Gas optimizations on merkle tree verifications
struct V__0_1_2 has store, drop, copy {}
/// RELEASE NOTES /// RELEASE NOTES
/// ///
/// - Refactor state to use package management via /// - Refactor state to use package management via
@ -70,7 +75,7 @@ module pyth::version_control {
} }
#[test_only] #[test_only]
public fun previous_version_test_only(): V__DUMMY { public fun previous_version_test_only(): V__0_1_1 {
previous_version() previous_version()
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@pythnetwork/pyth-sui-js", "name": "@pythnetwork/pyth-sui-js",
"version": "1.2.1", "version": "1.2.2",
"description": "Pyth Network Sui Utilities", "description": "Pyth Network Sui Utilities",
"homepage": "https://pyth.network", "homepage": "https://pyth.network",
"author": { "author": {

View File

@ -13,7 +13,7 @@ const MAX_ARGUMENT_SIZE = 16 * 1024;
export class SuiPythClient { export class SuiPythClient {
private pythPackageId: ObjectId | undefined; private pythPackageId: ObjectId | undefined;
private wormholePackageId: ObjectId | undefined; private wormholePackageId: ObjectId | undefined;
private priceTableId: ObjectId | undefined; private priceTableInfo: { id: ObjectId; fieldType: ObjectId } | undefined;
private priceFeedObjectIdCache: Map<HexString, ObjectId> = new Map(); private priceFeedObjectIdCache: Map<HexString, ObjectId> = new Map();
private baseUpdateFee: number | undefined; private baseUpdateFee: number | undefined;
constructor( constructor(
@ -260,11 +260,11 @@ export class SuiPythClient {
async getPriceFeedObjectId(feedId: HexString): Promise<ObjectId | undefined> { async getPriceFeedObjectId(feedId: HexString): Promise<ObjectId | undefined> {
const normalizedFeedId = feedId.replace("0x", ""); const normalizedFeedId = feedId.replace("0x", "");
if (!this.priceFeedObjectIdCache.has(normalizedFeedId)) { if (!this.priceFeedObjectIdCache.has(normalizedFeedId)) {
const tableId = await this.getPriceTableId(); const { id: tableId, fieldType } = await this.getPriceTableInfo();
const result = await this.provider.getDynamicFieldObject({ const result = await this.provider.getDynamicFieldObject({
parentId: tableId, parentId: tableId,
name: { name: {
type: `${await this.getPythPackageId()}::price_identifier::PriceIdentifier`, type: `${fieldType}::price_identifier::PriceIdentifier`,
value: { value: {
bytes: Array.from(Buffer.from(normalizedFeedId, "hex")), bytes: Array.from(Buffer.from(normalizedFeedId, "hex")),
}, },
@ -288,8 +288,8 @@ export class SuiPythClient {
* Fetches the price table object id for the current state id if not cached * Fetches the price table object id for the current state id if not cached
* @returns price table object id * @returns price table object id
*/ */
async getPriceTableId(): Promise<ObjectId> { async getPriceTableInfo(): Promise<{ id: ObjectId; fieldType: ObjectId }> {
if (this.priceTableId === undefined) { if (this.priceTableInfo === undefined) {
const result = await this.provider.getDynamicFieldObject({ const result = await this.provider.getDynamicFieldObject({
parentId: this.pythStateId, parentId: this.pythStateId,
name: { name: {
@ -297,14 +297,19 @@ export class SuiPythClient {
value: "price_info", value: "price_info",
}, },
}); });
if (!result.data) { if (!result.data || !result.data.type) {
throw new Error( throw new Error(
"Price Table not found, contract may not be initialized" "Price Table not found, contract may not be initialized"
); );
} }
this.priceTableId = result.data.objectId; let type = result.data.type.replace("0x2::table::Table<", "");
type = type.replace(
"::price_identifier::PriceIdentifier, 0x2::object::ID>",
""
);
this.priceTableInfo = { id: result.data.objectId, fieldType: type };
} }
return this.priceTableId; return this.priceTableInfo;
} }
/** /**