Open
Description
query.compute.queryContract
throws errors in some cases and returns error strings in other cases (like when a query does not exist), which is confusing and problematic, especially because strings are valid responses from queries. thus the caller cannot verify if a string is an error or a successful response from a contract.
i suspect the error strings should actually be thrown as errors instead, unless i'm misunderstanding the purpose here.
in src/query/compute.ts
:
/**
* Query a Secret Contract.
* May return a string on error.
*/
async queryContract<T extends object, R extends any>(
{
contract_address: contractAddress,
code_hash: codeHash,
query,
}: QueryContractRequest<T>,
headers?: HeadersInit,
): Promise<R> {
if (!codeHash) {
console.warn(getMissingCodeHashWarning("queryContract()"));
({ code_hash: codeHash } = await this.codeHashByContractAddress({
contract_address: contractAddress,
}));
}
codeHash = codeHash!.replace("0x", "").toLowerCase();
const encryptedQuery = await this.encryption!.encrypt(codeHash, query);
const nonce = encryptedQuery.slice(0, 32);
try {
const { data: encryptedResult } = await Query.QuerySecretContract(
{
contract_address: contractAddress,
query: encryptedQuery,
},
{
headers,
pathPrefix: this.url,
},
);
const decryptedBase64Result = await this.encryption!.decrypt(
fromBase64(encryptedResult as unknown as string)!,
nonce,
);
// Don't try to parse JSON in case the result is empty.
// This seems kinda stupid but if the contract for some reason returns `Binary::default()`
// the JSON parsing will fail (empty bytes)
if (!decryptedBase64Result?.length) {
return {} as R;
}
return JSON.parse(fromUtf8(fromBase64(fromUtf8(decryptedBase64Result))));
} catch (err) {
try {
const errorMessageRgx =
/encrypted: (.+?): (?:instantiate|execute|query|reply to|migrate) contract failed/g;
const rgxMatches = errorMessageRgx.exec(err.message);
if (rgxMatches == null || rgxMatches?.length != 2) {
throw err;
}
const encryptedError = fromBase64(rgxMatches[1]);
const decryptedBase64Error = await this.encryption!.decrypt(
encryptedError,
nonce,
);
try {
//@ts-ignore
// return the error string
return fromUtf8(fromBase64(fromUtf8(decryptedBase64Error)));
} catch (parseError) {
if (parseError.message === "Invalid base64 string format") {
//@ts-ignore
// return the error string
return fromUtf8(decryptedBase64Error);
} else {
throw err;
}
}
} catch (decryptionError) {
throw err;
}
}
}
i feel like the return
statements in the main catch statement should probably be throw new Error(...)
instead.
Metadata
Metadata
Assignees
Labels
No labels