Skip to content

Commit b189937

Browse files
authored
[sui] Sui dx improvement (#1011)
* 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
1 parent 55129e5 commit b189937

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+763
-18568
lines changed

contract_manager/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
"url": "git+https://github.com/pyth-network/pyth-crosschain.git"
2020
},
2121
"dependencies": {
22-
"@mysten/sui.js": "^0.37.1",
22+
"@mysten/sui.js": "^0.32.2",
2323
"@certusone/wormhole-sdk": "^0.9.8",
2424
"@pythnetwork/cosmwasm-deploy-tools": "*",
2525
"@pythnetwork/price-service-client": "*",
26+
"@pythnetwork/pyth-sui-js": "*",
2627
"@injectivelabs/networks": "1.0.68",
2728
"bs58": "^5.0.0",
2829
"ts-node": "^10.9.1",

contract_manager/src/contracts/sui.ts

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { Chain, SuiChain } from "../chains";
1111
import { DataSource } from "xc_admin_common";
1212
import { Contract } from "../base";
13+
import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
1314

1415
export class SuiContract extends Contract {
1516
static type = "SuiContract";
@@ -59,27 +60,8 @@ export class SuiContract extends Contract {
5960
* @param objectId
6061
*/
6162
async getPackageId(objectId: ObjectId): Promise<ObjectId> {
62-
const provider = this.getProvider();
63-
const state = await provider
64-
.getObject({
65-
id: objectId,
66-
options: {
67-
showContent: true,
68-
},
69-
})
70-
.then((result) => {
71-
if (result.data?.content?.dataType == "moveObject") {
72-
return result.data.content.fields;
73-
}
74-
75-
throw new Error("not move object");
76-
});
77-
78-
if ("upgrade_cap" in state) {
79-
return state.upgrade_cap.fields.package;
80-
}
81-
82-
throw new Error("upgrade_cap not found");
63+
const client = this.getSdkClient();
64+
return client.getPackageId(objectId);
8365
}
8466

8567
async getPythPackageId(): Promise<ObjectId> {
@@ -132,7 +114,7 @@ export class SuiContract extends Contract {
132114
};
133115
}
134116

135-
async getPriceFeed(feedId: string) {
117+
async getPriceFeedObjectId(feedId: string): Promise<ObjectId | undefined> {
136118
const tableId = await this.getPriceTableId();
137119
const provider = this.getProvider();
138120
let result = await provider.getDynamicFieldObject({
@@ -150,7 +132,13 @@ export class SuiContract extends Contract {
150132
if (result.data.content.dataType !== "moveObject") {
151133
throw new Error("Price feed type mismatch");
152134
}
153-
let priceInfoObjectId = result.data.content.fields.value;
135+
return result.data.content.fields.value;
136+
}
137+
138+
async getPriceFeed(feedId: string) {
139+
const provider = this.getProvider();
140+
let priceInfoObjectId = await this.getPriceFeedObjectId(feedId);
141+
if (!priceInfoObjectId) return undefined;
154142
let priceInfo = await provider.getObject({
155143
id: priceInfoObjectId,
156144
options: { showContent: true },
@@ -185,18 +173,60 @@ export class SuiContract extends Contract {
185173
async executeMigrateInstruction(vaa: Buffer, keypair: Ed25519Keypair) {
186174
const tx = new TransactionBlock();
187175
const packageId = await this.getPythPackageId();
188-
let decreeReceipt = await this.getVaaDecreeReceipt(tx, packageId, vaa);
176+
let verificationReceipt = await this.getVaaVerificationReceipt(
177+
tx,
178+
packageId,
179+
vaa
180+
);
189181

190182
tx.moveCall({
191183
target: `${packageId}::migrate::migrate`,
192-
arguments: [tx.object(this.stateId), decreeReceipt],
184+
arguments: [tx.object(this.stateId), verificationReceipt],
193185
});
194186

195187
return this.executeTransaction(tx, keypair);
196188
}
197189

198190
async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
199-
throw new Error("Not implemented");
191+
// We need the feed ids to be able to execute the transaction
192+
// it may be possible to get them from the VAA but in batch transactions,
193+
// it is also possible to hava fewer feeds that user wants to update compared to
194+
// what exists in the VAA.
195+
throw new Error("Use executeUpdatePriceFeedWithFeeds instead");
196+
}
197+
198+
getSdkClient(): SuiPythClient {
199+
return new SuiPythClient(
200+
this.getProvider(),
201+
this.stateId,
202+
this.wormholeStateId
203+
);
204+
}
205+
206+
async executeUpdatePriceFeedWithFeeds(
207+
senderPrivateKey: string,
208+
vaas: Buffer[],
209+
feedIds: string[]
210+
) {
211+
const tx = new TransactionBlock();
212+
const client = this.getSdkClient();
213+
await client.updatePriceFeeds(tx, vaas, feedIds);
214+
const keypair = Ed25519Keypair.fromSecretKey(
215+
Buffer.from(senderPrivateKey, "hex")
216+
);
217+
let result = await this.executeTransaction(tx, keypair);
218+
return result.digest;
219+
}
220+
async executeCreatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
221+
const tx = new TransactionBlock();
222+
const client = this.getSdkClient();
223+
await client.createPriceFeed(tx, vaas);
224+
const keypair = Ed25519Keypair.fromSecretKey(
225+
Buffer.from(senderPrivateKey, "hex")
226+
);
227+
228+
let result = await this.executeTransaction(tx, keypair);
229+
return result.digest;
200230
}
201231

202232
async executeGovernanceInstruction(senderPrivateKey: string, vaa: Buffer) {
@@ -205,11 +235,15 @@ export class SuiContract extends Contract {
205235
);
206236
const tx = new TransactionBlock();
207237
const packageId = await this.getPythPackageId();
208-
let decreeReceipt = await this.getVaaDecreeReceipt(tx, packageId, vaa);
238+
let verificationReceipt = await this.getVaaVerificationReceipt(
239+
tx,
240+
packageId,
241+
vaa
242+
);
209243

210244
tx.moveCall({
211245
target: `${packageId}::governance::execute_governance_instruction`,
212-
arguments: [tx.object(this.stateId), decreeReceipt],
246+
arguments: [tx.object(this.stateId), verificationReceipt],
213247
});
214248

215249
return this.executeTransaction(tx, keypair);
@@ -223,11 +257,15 @@ export class SuiContract extends Contract {
223257
) {
224258
const tx = new TransactionBlock();
225259
const packageId = await this.getPythPackageId();
226-
let decreeReceipt = await this.getVaaDecreeReceipt(tx, packageId, vaa);
260+
let verificationReceipt = await this.getVaaVerificationReceipt(
261+
tx,
262+
packageId,
263+
vaa
264+
);
227265

228266
const [upgradeTicket] = tx.moveCall({
229267
target: `${packageId}::contract_upgrade::authorize_upgrade`,
230-
arguments: [tx.object(this.stateId), decreeReceipt],
268+
arguments: [tx.object(this.stateId), verificationReceipt],
231269
});
232270

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

247285
/**
248-
* Utility function to get the decree receipt object for a VAA that can be
286+
* Utility function to get the verification receipt object for a VAA that can be
249287
* used to authorize a governance instruction.
250288
* @param tx
251289
* @param packageId pyth package id
252290
* @param vaa
253291
* @private
254292
*/
255-
private async getVaaDecreeReceipt(
293+
async getVaaVerificationReceipt(
256294
tx: TransactionBlock,
257295
packageId: string,
258296
vaa: Buffer
259297
) {
260298
const wormholePackageId = await this.getWormholePackageId();
261-
let [decreeTicket] = tx.moveCall({
262-
target: `${packageId}::set_update_fee::authorize_governance`,
263-
arguments: [tx.object(this.stateId), tx.pure(false)],
264-
});
265299

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

275-
let [decreeReceipt] = tx.moveCall({
276-
target: `${wormholePackageId}::governance_message::verify_vaa`,
277-
arguments: [tx.object(this.wormholeStateId), verifiedVAA, decreeTicket],
278-
typeArguments: [`${packageId}::governance_witness::GovernanceWitness`],
309+
let [verificationReceipt] = tx.moveCall({
310+
target: `${packageId}::governance::verify_vaa`,
311+
arguments: [tx.object(this.stateId), verifiedVAA],
279312
});
280-
return decreeReceipt;
313+
return verificationReceipt;
281314
}
282315

283316
/**
@@ -361,7 +394,7 @@ export class SuiContract extends Contract {
361394
return Number(fields.last_executed_governance_sequence);
362395
}
363396

364-
private getProvider() {
397+
getProvider() {
365398
return new JsonRpcProvider(new Connection({ fullnode: this.chain.rpcUrl }));
366399
}
367400

0 commit comments

Comments
 (0)