@wormhole-foundation/sdk-sui
Version:
SDK for Sui chains, used in conjunction with @wormhole-foundation/sdk
211 lines • 8.63 kB
JavaScript
;
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