"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WasmFetchError = void 0;
exports.fetchFromContractId = fetchFromContractId;
exports.fetchFromWasmHash = fetchFromWasmHash;
var _stellarBase = require("@stellar/stellar-base");
/**
* Types of contract data that can be fetched
*/
/**
* Errors that can occur during WASM fetching
*/
class WasmFetchError extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "WasmFetchError";
}
}
/**
* Get WASM bytes from a WASM hash on the network
*/
exports.WasmFetchError = WasmFetchError;
async function getRemoteWasmFromHash(server, hashBuffer) {
try {
// Create the ledger key for the contract code
const contractCodeKey = _stellarBase.xdr.LedgerKey.contractCode(new _stellarBase.xdr.LedgerKeyContractCode({
hash: _stellarBase.xdr.Hash.fromXDR(hashBuffer, "raw")
}));
// Get the ledger entries
const response = await server.getLedgerEntries(contractCodeKey);
if (!response.entries || response.entries.length === 0) {
throw new WasmFetchError("WASM not found for the given hash");
}
const entry = response.entries[0];
if (entry.key.switch() !== _stellarBase.xdr.LedgerEntryType.contractCode()) {
throw new WasmFetchError("Invalid ledger entry type returned");
}
const contractCode = entry.val.contractCode();
return Buffer.from(contractCode.code());
} catch (error) {
if (error instanceof WasmFetchError) {
throw error;
}
throw new WasmFetchError("Failed to fetch WASM from hash", error);
}
}
/**
* Check if a contract is a Stellar Asset Contract
*/
function isStellarAssetContract(instance) {
// Check if it's a Stellar Asset Contract (has no WASM hash)
return instance.executable().switch() === _stellarBase.xdr.ContractExecutableType.contractExecutableStellarAsset();
}
/**
* Fetch WASM bytes from a deployed contract
*/
async function fetchWasmFromContract(server, contractAddress) {
try {
const contract = new _stellarBase.Contract(contractAddress.toString());
const response = await server.getLedgerEntries(contract.getFootprint());
if (!response.entries || response.entries.length === 0) {
throw new WasmFetchError("Contract instance not found");
}
const entry = response.entries[0];
if (entry.key.switch() !== _stellarBase.xdr.LedgerEntryType.contractData()) {
throw new WasmFetchError("Invalid ledger entry type returned");
}
const contractData = entry.val.contractData();
const instance = contractData.val().instance();
if (isStellarAssetContract(instance)) {
return {
type: "stellar-asset-contract"
};
}
const wasmHash = instance.executable().wasmHash();
let wasmBytes = await getRemoteWasmFromHash(server, wasmHash);
return {
type: "wasm",
wasmBytes
};
} catch (error) {
if (error instanceof WasmFetchError) {
throw error;
}
throw new WasmFetchError("Failed to fetch WASM from contract", error);
}
}
/**
* Fetch WASM from network using WASM hash
*/
async function fetchFromWasmHash(wasmHash, rpcServer) {
try {
// Validate and decode the hash
const hashBuffer = Buffer.from(wasmHash, "hex");
if (hashBuffer.length !== 32) {
throw new WasmFetchError(`Invalid WASM hash length: expected 32 bytes, got ${hashBuffer.length}`);
}
// Get WASM from hash
const wasmBytes = await getRemoteWasmFromHash(rpcServer, hashBuffer);
return {
type: "wasm",
wasmBytes
};
} catch (error) {
throw new WasmFetchError(`Failed to fetch WASM from hash ${wasmHash}`, error);
}
}
/**
* Fetch WASM from network using contract ID
*/
async function fetchFromContractId(contractId, rpcServer) {
try {
if (!_stellarBase.StrKey.isValidContract(contractId)) {
throw new WasmFetchError(`Invalid contract ID: ${contractId}`);
}
// Parse contract address
const contractAddress = _stellarBase.Address.fromString(contractId);
// Try to get WASM from contract
return await fetchWasmFromContract(rpcServer, contractAddress);
} catch (error) {
throw new WasmFetchError(`Failed to fetch WASM from contract ${contractId}`, error);
}
}
Source