UNPKG

@wormhole-foundation/sdk-sui

Version:

SDK for Sui chains, used in conjunction with @wormhole-foundation/sdk

211 lines 8.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.newEmitterCap = exports.publishPackage = exports.getUpgradeCapObjectId = exports.getOwnedObjectIdPaginated = exports.getOwnedObjectId = exports.getOldestEmitterCapObjectId = exports.getPackageId = exports.getObjectFields = exports.getOriginalPackageId = exports.UPGRADE_CAP_TYPE = void 0; const transactions_1 = require("@mysten/sui/transactions"); const utils_1 = require("@mysten/sui/utils"); const sdk_connect_1 = require("@wormhole-foundation/sdk-connect"); const types_js_1 = require("./types.js"); const address_js_1 = require("./address.js"); exports.UPGRADE_CAP_TYPE = "0x2::package::UpgradeCap"; // // Utils to fetch data from Sui // const getOriginalPackageId = async (provider, stateObjectId) => { const { data, error } = await provider.getObject({ id: stateObjectId, options: { showContent: true }, }); if (error) throw new Error("Error getting object: " + error); if (!data || !(0, types_js_1.isMoveStructStruct)(data.content)) throw new Error(`Cannot get oject for state id ${stateObjectId}: ` + data); return (0, address_js_1.getPackageIdFromType)(data.content.type); }; exports.getOriginalPackageId = getOriginalPackageId; const getObjectFields = async (provider, objectId) => { if (!(0, utils_1.isValidSuiAddress)(objectId)) { throw new Error(`Invalid object ID: ${objectId}`); } const res = await provider.getObject({ id: objectId, options: { showContent: true, }, }); return (0, types_js_1.getFieldsFromObjectResponse)(res); }; exports.getObjectFields = getObjectFields; const getPackageId = async (provider, objectId) => { let currentPackage; let nextCursor; do { const dynamicFields = await provider.getDynamicFields({ parentId: objectId, cursor: nextCursor, }); currentPackage = dynamicFields.data.find((field) => field.name.type.endsWith("CurrentPackage")); nextCursor = dynamicFields.hasNextPage ? dynamicFields.nextCursor : null; } while (nextCursor && !currentPackage); if (!currentPackage) throw new Error("CurrentPackage not found"); const obj = await provider.getObject({ id: currentPackage.objectId, options: { showContent: true, }, }); const fields = (0, types_js_1.getFieldsFromObjectResponse)(obj); if (!fields || !(0, types_js_1.isMoveStructObject)(fields)) throw new Error("Unable to get fields from object response"); if (!("value" in fields) || !(0, types_js_1.isMoveStructStruct)(fields["value"])) throw new Error("Unable to get package id"); return fields["value"].fields["package"]; }; exports.getPackageId = getPackageId; const getOldestEmitterCapObjectId = async (provider, coreBridgePackageId, owner) => { let oldestVersion = null; let oldestObjectId = null; let response = null; let nextCursor; do { response = await provider.getOwnedObjects({ owner, filter: { StructType: `${coreBridgePackageId}::emitter::EmitterCap`, }, options: { showContent: true, }, cursor: nextCursor, }); if (!response || !response.data) { throw Error("Failed to get owned objects"); } for (const objectResponse of response.data) { if (!objectResponse.data) continue; const { version, objectId } = objectResponse.data; if (oldestVersion === null || version < oldestVersion) { oldestVersion = version; oldestObjectId = objectId; } } nextCursor = response.hasNextPage ? response.nextCursor : undefined; } while (nextCursor); return oldestObjectId; }; exports.getOldestEmitterCapObjectId = getOldestEmitterCapObjectId; const getOwnedObjectId = async (provider, owner, type) => { // Upgrade caps are a special case if ((0, types_js_1.isSameType)(type, exports.UPGRADE_CAP_TYPE)) { throw new Error("`getOwnedObjectId` should not be used to get the object ID of an `UpgradeCap`. Use `getUpgradeCapObjectId` instead."); } try { const res = await provider.getOwnedObjects({ owner, filter: { StructType: type }, options: { showContent: true, }, }); if (!res || !res.data) { throw new Error("Failed to get owned objects"); } const objects = res.data.filter((o) => o.data?.objectId); if (!objects || objects.length === 0) return null; if (objects.length === 1) { return objects[0].data?.objectId ?? null; } else { const objectsStr = JSON.stringify(objects, null, 2); throw new Error(`Found multiple objects owned by ${owner} of type ${type}. This may mean that we've received an unexpected response from the Sui RPC and \`worm\` logic needs to be updated to handle this. Objects: ${objectsStr}`); } } catch (error) { // Handle 504 error by using findOwnedObjectByType method const is504HttpError = `${error}`.includes("504 Gateway Time-out"); if (error && is504HttpError) { return (0, exports.getOwnedObjectIdPaginated)(provider, owner, type); } else { throw error; } } }; exports.getOwnedObjectId = getOwnedObjectId; const getOwnedObjectIdPaginated = async (provider, owner, type, cursor) => { const res = await provider.getOwnedObjects({ owner, filter: undefined, // Filter must be undefined to avoid 504 responses cursor: cursor || undefined, options: { showType: true, }, }); if (!res || !res.data) { throw new Error("Could not fetch owned object id"); } const object = res.data.find((d) => (0, types_js_1.isSameType)(d.data?.type || "", type)); if (!object && res.hasNextPage) { return (0, exports.getOwnedObjectIdPaginated)(provider, owner, type, res.nextCursor); } else if (!object && !res.hasNextPage) { return null; } else { return object?.data?.objectId ?? null; } }; exports.getOwnedObjectIdPaginated = getOwnedObjectIdPaginated; const getUpgradeCapObjectId = async (provider, owner, packageId) => { const res = await provider.getOwnedObjects({ owner, filter: { StructType: (0, address_js_1.normalizeSuiType)(exports.UPGRADE_CAP_TYPE) }, options: { showContent: true, }, }); if (!res || !res.data) { throw new Error("Failed to get upgrade caps"); } const objects = res.data.filter((o) => { const fields = (0, types_js_1.getFieldsFromObjectResponse)(o); return ((0, types_js_1.isMoveStructStruct)(fields) && (0, utils_1.normalizeSuiAddress)(fields.fields["package"]) === (0, utils_1.normalizeSuiAddress)(packageId)); }); if (!objects || objects.length === 0) return null; if (objects.length === 1) { // We've found the object we're looking for return objects[0].data?.objectId ?? null; } else { const objectsStr = JSON.stringify(objects, null, 2); throw new Error(`Found multiple upgrade capabilities owned by ${owner} from package ${packageId}. Objects: ${objectsStr}`); } }; exports.getUpgradeCapObjectId = getUpgradeCapObjectId; // Create a TransactionBlock to publish a package const publishPackage = async (buildOutput, signerAddress) => { const tx = new transactions_1.Transaction(); const [upgradeCap] = tx.publish({ modules: buildOutput.modules.map((m) => Array.from(sdk_connect_1.encoding.b64.decode(m))), dependencies: buildOutput.dependencies.map((d) => (0, utils_1.normalizeSuiObjectId)(d)), }); // Transfer upgrade capability to recipient tx.transferObjects([upgradeCap], tx.pure.address(signerAddress)); return tx; }; exports.publishPackage = publishPackage; const newEmitterCap = (coreBridgePackageId, coreBridgeStateObjectId, owner) => { const tx = new transactions_1.Transaction(); const [emitterCap] = tx.moveCall({ target: `${coreBridgePackageId}::emitter::new`, arguments: [tx.object(coreBridgeStateObjectId)], }); tx.transferObjects([emitterCap], tx.pure.address(owner)); return tx; }; exports.newEmitterCap = newEmitterCap; //# sourceMappingURL=utils.js.map