Source previews
bundle.js
1740449 bytes · SHA-256 1d4c2ad4c304621d219f2c23818cd56f4f0dc94469131c4ccecf5bb10dc0a591
// This file is compiled to devtools-snippet.js and injected at the beginning
// of user scripts when enableDevtools is true. It overrides console methods to
// forward logs to the Acurast DevTools API.
//
// Placeholder https://api.devtools.acurast.com is replaced at injection time.
;
(() => {
const DEVTOOLS_API_URL = 'https://api.devtools.acurast.com';
const originalConsole = {
log: console.log,
warn: console.warn,
error: console.error,
info: console.info,
debug: console.debug,
};
// --- Auth: obtain a Bearer token from the devtools API ---
let apiKey = null;
const pendingLogs = []; // buffered payloads while awaiting auth
const toHex = (str) => {
let hex = '';
for (let i = 0; i < str.length; i++) {
hex += str.charCodeAt(i).toString(16).padStart(2, '0');
}
return hex;
};
const sendBuffered = () => {
for (const body of pendingLogs.splice(0)) {
httpPOST(`${DEVTOOLS_API_URL}/v1/logs`, body, { 'Content-Type': 'application/json', Authorization: 'Bearer ' + apiKey }, () => { }, (error) => {
originalConsole.error('[devtools] buffered log post failed:', error);
});
}
};
try {
// The full "origin:owner:number" deployment id. The API needs the owner to
// find the job on chain: job storage is keyed by (origin, number) under a
// one-way hasher, so a bare number cannot be resolved there.
const rawId = _STD_.job.getId();
const jobNumber = String(rawId.id);
const origin = rawId.origin;
const jobId = origin && origin.kind && origin.source
? origin.kind + ':' + origin.source + ':' + jobNumber
: jobNumber;
const processorAddress = _STD_.device.getAddress();
const pubKeyHex = _STD_.job.getPublicKeys().ed25519;
const timestamp = String(Math.floor(Date.now() / 1000));
// Bound to the deployment so a captured signature cannot be reused against
// another job.
const message = pubKeyHex + ':' + jobId + ':' + timestamp;
const messageHex = toHex(message);
const signatureHex = _STD_.signers.ed25519.sign(messageHex);
httpPOST(`${DEVTOOLS_API_URL}/v1/auth/api-key`, JSON.stringify({ jobId, processorAddress }), {
'Content-Type': 'application/json',
'X-Signature': signatureHex,
'X-PublicKey': pubKeyHex,
'X-Timestamp': timestamp,
}, (response, _certificate) => {
try {
const parsed = JSON.parse(response);
apiKey = parsed.apiKey;
sendBuffered();
}
catch (_e) {
originalConsole.error('[devtools] failed to parse auth response:', response);
}
}, (error) => {
originalConsole.error('[devtools] auth failed:', error);
});
}
catch (e) {
originalConsole.error('[devtools] auth setup failed:', e?.message ?? String(e));
}
// --- Rate limiting ---
const RATE_LIMIT_MAX = 20;
const RATE_LIMIT_WINDOW_MS = 10000;
let rateBucketStart = Date.now();
let rateBucketCount = 0;
let dropped = 0;
const sendLog = (level, args) => {
const now = Date.now();
if (now - rateBucketStart >= RATE_LIMIT_WINDOW_MS) {
if (dropped > 0) {
enqueue([
{
type: 'warn',
data: `[devtools] rate limit ended: ${dropped} log(s) were dropped`,
timestamp: now,
},
]);
}
rateBucketStart = now;
rateBucketCount = 0;
dropped = 0;
}
if (rateBucketCount >= RATE_LIMIT_MAX) {
dropped++;
return;
}
rateBucketCount++;
try {
const data = args.length === 1 ? args[0] : args;
let serializable;
try {
JSON.stringify(data);
serializable = data;
}
catch {
serializable = String(data);
}
enqueue([{ type: level, data: serializable, timestamp: now }]);
}
catch (_e) {
// Silently ignore serialization errors to avoid breaking user scripts
}
};
const enqueue = (entries) => {
const body = JSON.stringify(entries);
if (apiKey) {
httpPOST(`${DEVTOOLS_API_URL}/v1/logs`, body, { 'Content-Type': 'application/json', Authorization: 'Bearer ' + apiKey }, () => { }, (error) => {
originalConsole.error('[devtools] log post failed:', error);
});
}
else {
pendingLogs.push(body);
}
};
// --- File upload via /v1/files ---
const uploadFile = (filename, content, mimeType, onSuccess, onError) => {
if (!apiKey) {
onError('[devtools] file upload failed: not authenticated yet');
return;
}
// The processor's httpPOST JSON-parses the body regardless of Content-Type,
// so we cannot send multipart/form-data through it. Use fetch + FormData
// instead — fetch sets the Content-Type header (with boundary) automatically.
const formData = new FormData();
formData.append('file', new Blob([content], { type: mimeType }), filename);
fetch(`${DEVTOOLS_API_URL}/v1/files`, {
method: 'POST',
headers: { Authorization: 'Bearer ' + apiKey },
body: formData,
})
.then((res) => res.text().then((text) => ({ ok: res.ok, status: res.status, text })))
.then(({ ok, status, text }) => {
if (!ok) {
onError('[devtools] file upload failed: HTTP ' + status + ' ' + text);
return;
}
try {
onSuccess(JSON.parse(text));
}
catch (_e) {
onError('[devtools] failed to parse upload response: ' + text);
}
})
.catch((err) => {
onError('[devtools] file upload failed: ' + (err?.message ?? String(err)));
});
};
globalThis._DEVTOOLS_ = { uploadFile };
for (const level of Object.keys(originalConsole)) {
;
console[level] = (...args) => {
originalConsole[level](...args);
sendLog(level, args);
};
}
})();
const __import_meta_url=require('url').pathToFileURL(__filename).href;
"use strict";var Nj=Object.create;var pE=Object.defineProperty;var Bj=Object.getOwnPropertyDescriptor;var Dj=Object.getOwnPropertyNames;var Lj=Object.getPrototypeOf,Uj=Object.prototype.hasOwnProperty;var ae=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(r){throw n=[r],r}};var Pe=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(n){throw t=0,n}},Zb=(e,t)=>{for(var n in t)pE(e,n,{get:t[n],enumerable:!0})},Fj=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Dj(t))!Uj.call(e,i)&&i!==n&&pE(e,i,{get:()=>t[i],enumerable:!(r=Bj(t,i))||r.enumerable});return e};var Mh=(e,t,n)=>(n=e!=null?Nj(Lj(e)):{},Fj(t||!e||!e.__esModule?pE(n,"default",{value:e,enumerable:!0}):n,e));var d3,l3=ae(()=>{d3="1.2.3"});var Hn,cp=ae(()=>{l3();Hn=class e extends Error{constructor(t,n={}){let r=n.cause instanceof e?n.cause.details:n.cause?.message?n.cause.message:n.details,i=n.cause instanceof e&&n.cause.docsPath||n.docsPath,o=[t||"An error occurred.","",...n.metaMessages?[...n.metaMessages,""]:[],...i?[`Docs: https://abitype.dev${i}`]:[],...r?[`Details: ${r}`]:[],`Version: abitype@${d3}`].join(`
`);super(o),Object.defineProperty(this,"details",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"docsPath",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"metaMessages",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"shortMessage",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProper
Preview truncated.
manifest.json
77 bytes · SHA-256 981478369204b4991fc02966ebf88fc709c7bb9fade101070af735c952ad283c
Preview truncated.