Skip to content

Commit

Permalink
[sui] Sui dx improvement (pyth-network#1011)
Browse files Browse the repository at this point in the history
* Use the actual wormhole deployment on testnet for sui testnet config

* Simpler deployment script

* Bugfix in upgrade payload deserialization

* Bugfix in fetching upgrade digest

* Small contract manager refactoring and more integration for upgrade script in sui

* Remove old scripts

* Add script for just generating the sui contract digest

* Restrict HotPotatoVector borrow access

The return value of `create_price_infos_hot_potato` should not be inspectable
outside of the package.

* Reorganize the cli lib for sui

* Add minimal README for sui cli

* Update the general README for sui

* Reuse sui sdk logic in contract manager


* Manual serialization of accumulator updates for increasing payload size

Default payload size seems to be 1024 bytes which is not enough for messages
with multiple feeds

* Bump sdk version
  • Loading branch information
m30m authored Aug 15, 2023
1 parent 55129e5 commit b189937
Show file tree
Hide file tree
Showing 49 changed files with 763 additions and 18,568 deletions.
3 changes: 2 additions & 1 deletion contract_manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
"url": "git+https://github.com/pyth-network/pyth-crosschain.git"
},
"dependencies": {
"@mysten/sui.js": "^0.37.1",
"@mysten/sui.js": "^0.32.2",
"@certusone/wormhole-sdk": "^0.9.8",
"@pythnetwork/cosmwasm-deploy-tools": "*",
"@pythnetwork/price-service-client": "*",
"@pythnetwork/pyth-sui-js": "*",
"@injectivelabs/networks": "1.0.68",
"bs58": "^5.0.0",
"ts-node": "^10.9.1",
Expand Down
117 changes: 75 additions & 42 deletions contract_manager/src/contracts/sui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { Chain, SuiChain } from "../chains";
import { DataSource } from "xc_admin_common";
import { Contract } from "../base";
import { SuiPythClient } from "@pythnetwork/pyth-sui-js";

export class SuiContract extends Contract {
static type = "SuiContract";
Expand Down Expand Up @@ -59,27 +60,8 @@ export class SuiContract extends Contract {
* @param objectId
*/
async getPackageId(objectId: ObjectId): Promise<ObjectId> {
const provider = this.getProvider();
const state = await provider
.getObject({
id: objectId,
options: {
showContent: true,
},
})
.then((result) => {
if (result.data?.content?.dataType == "moveObject") {
return result.data.content.fields;
}

throw new Error("not move object");
});

if ("upgrade_cap" in state) {
return state.upgrade_cap.fields.package;
}

throw new Error("upgrade_cap not found");
const client = this.getSdkClient();
return client.getPackageId(objectId);
}

async getPythPackageId(): Promise<ObjectId> {
Expand Down Expand Up @@ -132,7 +114,7 @@ export class SuiContract extends Contract {
};
}

async getPriceFeed(feedId: string) {
async getPriceFeedObjectId(feedId: string): Promise<ObjectId | undefined> {
const tableId = await this.getPriceTableId();
const provider = this.getProvider();
let result = await provider.getDynamicFieldObject({
Expand All @@ -150,7 +132,13 @@ export class SuiContract extends Contract {
if (result.data.content.dataType !== "moveObject") {
throw new Error("Price feed type mismatch");
}
let priceInfoObjectId = result.data.content.fields.value;
return result.data.content.fields.value;
}

async getPriceFeed(feedId: string) {
const provider = this.getProvider();
let priceInfoObjectId = await this.getPriceFeedObjectId(feedId);
if (!priceInfoObjectId) return undefined;
let priceInfo = await provider.getObject({
id: priceInfoObjectId,
options: { showContent: true },
Expand Down Expand Up @@ -185,18 +173,60 @@ export class SuiContract extends Contract {
async executeMigrateInstruction(vaa: Buffer, keypair: Ed25519Keypair) {
const tx = new TransactionBlock();
const packageId = await this.getPythPackageId();
let decreeReceipt = await this.getVaaDecreeReceipt(tx, packageId, vaa);
let verificationReceipt = await this.getVaaVerificationReceipt(
tx,
packageId,
vaa
);

tx.moveCall({
target: `${packageId}::migrate::migrate`,
arguments: [tx.object(this.stateId), decreeReceipt],
arguments: [tx.object(this.stateId), verificationReceipt],
});

return this.executeTransaction(tx, keypair);
}

async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
throw new Error("Not implemented");
// We need the feed ids to be able to execute the transaction
// it may be possible to get them from the VAA but in batch transactions,
// it is also possible to hava fewer feeds that user wants to update compared to
// what exists in the VAA.
throw new Error("Use executeUpdatePriceFeedWithFeeds instead");
}

getSdkClient(): SuiPythClient {
return new SuiPythClient(
this.getProvider(),
this.stateId,
this.wormholeStateId
);
}

async executeUpdatePriceFeedWithFeeds(
senderPrivateKey: string,
vaas: Buffer[],
feedIds: string[]
) {
const tx = new TransactionBlock();
const client = this.getSdkClient();
await client.updatePriceFeeds(tx, vaas, feedIds);
const keypair = Ed25519Keypair.fromSecretKey(
Buffer.from(senderPrivateKey, "hex")
);
let result = await this.executeTransaction(tx, keypair);
return result.digest;
}
async executeCreatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
const tx = new TransactionBlock();
const client = this.getSdkClient();
await client.createPriceFeed(tx, vaas);
const keypair = Ed25519Keypair.fromSecretKey(
Buffer.from(senderPrivateKey, "hex")
);

let result = await this.executeTransaction(tx, keypair);
return result.digest;
}

async executeGovernanceInstruction(senderPrivateKey: string, vaa: Buffer) {
Expand All @@ -205,11 +235,15 @@ export class SuiContract extends Contract {
);
const tx = new TransactionBlock();
const packageId = await this.getPythPackageId();
let decreeReceipt = await this.getVaaDecreeReceipt(tx, packageId, vaa);
let verificationReceipt = await this.getVaaVerificationReceipt(
tx,
packageId,
vaa
);

tx.moveCall({
target: `${packageId}::governance::execute_governance_instruction`,
arguments: [tx.object(this.stateId), decreeReceipt],
arguments: [tx.object(this.stateId), verificationReceipt],
});

return this.executeTransaction(tx, keypair);
Expand All @@ -223,11 +257,15 @@ export class SuiContract extends Contract {
) {
const tx = new TransactionBlock();
const packageId = await this.getPythPackageId();
let decreeReceipt = await this.getVaaDecreeReceipt(tx, packageId, vaa);
let verificationReceipt = await this.getVaaVerificationReceipt(
tx,
packageId,
vaa
);

const [upgradeTicket] = tx.moveCall({
target: `${packageId}::contract_upgrade::authorize_upgrade`,
arguments: [tx.object(this.stateId), decreeReceipt],
arguments: [tx.object(this.stateId), verificationReceipt],
});

const [upgradeReceipt] = tx.upgrade({
Expand All @@ -245,23 +283,19 @@ export class SuiContract extends Contract {
}

/**
* Utility function to get the decree receipt object for a VAA that can be
* Utility function to get the verification receipt object for a VAA that can be
* used to authorize a governance instruction.
* @param tx
* @param packageId pyth package id
* @param vaa
* @private
*/
private async getVaaDecreeReceipt(
async getVaaVerificationReceipt(
tx: TransactionBlock,
packageId: string,
vaa: Buffer
) {
const wormholePackageId = await this.getWormholePackageId();
let [decreeTicket] = tx.moveCall({
target: `${packageId}::set_update_fee::authorize_governance`,
arguments: [tx.object(this.stateId), tx.pure(false)],
});

let [verifiedVAA] = tx.moveCall({
target: `${wormholePackageId}::vaa::parse_and_verify`,
Expand All @@ -272,12 +306,11 @@ export class SuiContract extends Contract {
],
});

let [decreeReceipt] = tx.moveCall({
target: `${wormholePackageId}::governance_message::verify_vaa`,
arguments: [tx.object(this.wormholeStateId), verifiedVAA, decreeTicket],
typeArguments: [`${packageId}::governance_witness::GovernanceWitness`],
let [verificationReceipt] = tx.moveCall({
target: `${packageId}::governance::verify_vaa`,
arguments: [tx.object(this.stateId), verifiedVAA],
});
return decreeReceipt;
return verificationReceipt;
}

/**
Expand Down Expand Up @@ -361,7 +394,7 @@ export class SuiContract extends Contract {
return Number(fields.last_executed_governance_sequence);
}

private getProvider() {
getProvider() {
return new JsonRpcProvider(new Connection({ fullnode: this.chain.rpcUrl }));
}

Expand Down
Loading

0 comments on commit b189937

Please sign in to comment.