@flaunch/sdk
Version:
Flaunch SDK to easily interact with the Flaunch protocol
290 lines (282 loc) • 10.5 kB
JavaScript
import { s as slice, t as toFunctionSelector, f as formatAbiItem, A as AbiFunctionSignatureNotFoundError, d as decodeAbiParameters, g as getAbiItem, a as AbiErrorNotFoundError, b as AbiErrorInputsNotFoundError, e as encodeAbiParameters, c as concatHex, h as AbiFunctionNotFoundError, i as AbiFunctionOutputsNotFoundError, I as InvalidArrayError, B as BaseError, j as getUrl, k as stringify, l as batchGatewayAbi, m as solidityError, n as decodeErrorResult, o as isAddressEqual, p as call, q as concat, r as getAbortError, u as isAbortError, H as HttpRequestError, v as isHex } from './index-a87fa473.js';
import 'viem';
import 'axios';
function decodeFunctionData(parameters) {
const { abi, data } = parameters;
const signature = slice(data, 0, 4);
const description = abi.find((x) => x.type === 'function' &&
signature === toFunctionSelector(formatAbiItem(x)));
if (!description)
throw new AbiFunctionSignatureNotFoundError(signature, {
docsPath: '/docs/contract/decodeFunctionData',
});
return {
functionName: description.name,
args: ('inputs' in description &&
description.inputs &&
description.inputs.length > 0
? decodeAbiParameters(description.inputs, slice(data, 4))
: undefined),
};
}
const docsPath$1 = '/docs/contract/encodeErrorResult';
function encodeErrorResult(parameters) {
const { abi, errorName, args } = parameters;
let abiItem = abi[0];
if (errorName) {
const item = getAbiItem({ abi, args, name: errorName });
if (!item)
throw new AbiErrorNotFoundError(errorName, { docsPath: docsPath$1 });
abiItem = item;
}
if (abiItem.type !== 'error')
throw new AbiErrorNotFoundError(undefined, { docsPath: docsPath$1 });
const definition = formatAbiItem(abiItem);
const signature = toFunctionSelector(definition);
let data = '0x';
if (args && args.length > 0) {
if (!abiItem.inputs)
throw new AbiErrorInputsNotFoundError(abiItem.name, { docsPath: docsPath$1 });
data = encodeAbiParameters(abiItem.inputs, args);
}
return concatHex([signature, data]);
}
const docsPath = '/docs/contract/encodeFunctionResult';
function encodeFunctionResult(parameters) {
const { abi, functionName, result } = parameters;
let abiItem = abi[0];
if (functionName) {
const item = getAbiItem({ abi, name: functionName });
if (!item)
throw new AbiFunctionNotFoundError(functionName, { docsPath });
abiItem = item;
}
if (abiItem.type !== 'function')
throw new AbiFunctionNotFoundError(undefined, { docsPath });
if (!abiItem.outputs)
throw new AbiFunctionOutputsNotFoundError(abiItem.name, { docsPath });
const values = (() => {
if (abiItem.outputs.length === 0)
return [];
if (abiItem.outputs.length === 1)
return [result];
if (Array.isArray(result))
return result;
throw new InvalidArrayError(result);
})();
return encodeAbiParameters(abiItem.outputs, values);
}
class OffchainLookupError extends BaseError {
constructor({ callbackSelector, cause, data, extraData, sender, urls, }) {
super(cause.shortMessage ||
'An error occurred while fetching for an offchain result.', {
cause,
metaMessages: [
...(cause.metaMessages || []),
cause.metaMessages?.length ? '' : [],
'Offchain Gateway Call:',
urls && [
' Gateway URL(s):',
...urls.map((url) => ` ${getUrl(url)}`),
],
` Sender: ${sender}`,
` Data: ${data}`,
` Callback selector: ${callbackSelector}`,
` Extra data: ${extraData}`,
].flat(),
name: 'OffchainLookupError',
});
}
}
class OffchainLookupResponseMalformedError extends BaseError {
constructor({ result, url }) {
super('Offchain gateway response is malformed. Response data must be a hex value.', {
metaMessages: [
`Gateway URL: ${getUrl(url)}`,
`Response: ${stringify(result)}`,
],
name: 'OffchainLookupResponseMalformedError',
});
}
}
class OffchainLookupSenderMismatchError extends BaseError {
constructor({ sender, to }) {
super('Reverted sender address does not match target contract address (`to`).', {
metaMessages: [
`Contract address: ${to}`,
`OffchainLookup sender address: ${sender}`,
],
name: 'OffchainLookupSenderMismatchError',
});
}
}
const localBatchGatewayUrl = 'x-batch-gateway:true';
async function localBatchGatewayRequest(parameters) {
const { data, ccipRequest } = parameters;
const { args: [queries], } = decodeFunctionData({ abi: batchGatewayAbi, data });
const failures = [];
const responses = [];
await Promise.all(queries.map(async (query, i) => {
try {
responses[i] = query.urls.includes(localBatchGatewayUrl)
? await localBatchGatewayRequest({ data: query.data, ccipRequest })
: await ccipRequest(query);
failures[i] = false;
}
catch (err) {
failures[i] = true;
responses[i] = encodeError(err);
}
}));
return encodeFunctionResult({
abi: batchGatewayAbi,
functionName: 'query',
result: [failures, responses],
});
}
function encodeError(error) {
if (error.name === 'HttpRequestError' && error.status)
return encodeErrorResult({
abi: batchGatewayAbi,
errorName: 'HttpError',
args: [error.status, error.shortMessage],
});
return encodeErrorResult({
abi: [solidityError],
errorName: 'Error',
args: ['shortMessage' in error ? error.shortMessage : error.message],
});
}
const offchainLookupSignature = '0x556f1830';
const offchainLookupAbiItem = {
name: 'OffchainLookup',
type: 'error',
inputs: [
{
name: 'sender',
type: 'address',
},
{
name: 'urls',
type: 'string[]',
},
{
name: 'callData',
type: 'bytes',
},
{
name: 'callbackFunction',
type: 'bytes4',
},
{
name: 'extraData',
type: 'bytes',
},
],
};
async function offchainLookup(client, { blockNumber, blockTag, data, requestOptions, to, }) {
const { args } = decodeErrorResult({
data,
abi: [offchainLookupAbiItem],
});
const [sender, urls, callData, callbackSelector, extraData] = args;
const { ccipRead } = client;
const ccipRequest_ = ccipRead && typeof ccipRead?.request === 'function'
? ccipRead.request
: ccipRequest;
try {
if (!isAddressEqual(to, sender))
throw new OffchainLookupSenderMismatchError({ sender, to });
const result = urls.includes(localBatchGatewayUrl)
? await localBatchGatewayRequest({
data: callData,
ccipRequest: (parameters) => ccipRequest_({ ...parameters, requestOptions }),
})
: await ccipRequest_({ data: callData, requestOptions, sender, urls });
const { data: data_ } = await call(client, {
blockNumber,
blockTag,
data: concat([
callbackSelector,
encodeAbiParameters([{ type: 'bytes' }, { type: 'bytes' }], [result, extraData]),
]),
requestOptions,
to,
});
return data_;
}
catch (err) {
if (requestOptions?.signal?.aborted)
throw getAbortError(requestOptions.signal);
if (isAbortError(err))
throw err;
throw new OffchainLookupError({
callbackSelector,
cause: err,
data,
extraData,
sender,
urls,
});
}
}
async function ccipRequest({ data, requestOptions, sender, urls, }) {
let error = new Error('An unknown error occurred.');
for (let i = 0; i < urls.length; i++) {
if (requestOptions?.signal?.aborted)
throw getAbortError(requestOptions.signal);
const url = urls[i];
const method = url.includes('{data}') ? 'GET' : 'POST';
const body = method === 'POST' ? { data, sender } : undefined;
const headers = method === 'POST' ? { 'Content-Type': 'application/json' } : {};
try {
const response = await fetch(url.replace('{sender}', sender.toLowerCase()).replace('{data}', data), {
body: JSON.stringify(body),
headers,
method,
...(requestOptions?.signal ? { signal: requestOptions.signal } : {}),
});
let result;
if (response.headers.get('Content-Type')?.startsWith('application/json')) {
result = (await response.json()).data;
}
else {
result = (await response.text());
}
if (!response.ok) {
error = new HttpRequestError({
body,
details: result?.error
? stringify(result.error)
: response.statusText,
headers: response.headers,
status: response.status,
url,
});
continue;
}
if (!isHex(result)) {
error = new OffchainLookupResponseMalformedError({
result,
url,
});
continue;
}
return result;
}
catch (err) {
if (requestOptions?.signal?.aborted)
throw getAbortError(requestOptions.signal);
if (isAbortError(err))
throw err;
error = new HttpRequestError({
body,
details: err.message,
url,
});
}
}
throw error;
}
export { ccipRequest, offchainLookup, offchainLookupAbiItem, offchainLookupSignature };
//# sourceMappingURL=ccip-93b2db26.js.map