New:Socket for Asana Is Now Available.Learn more
Get Started

zerohash

Package Overview
Versions
2
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zeroauth@zerohash.com - firefox Package Compare versions

Comparing version
0.2.4
to
0.2.5
+2
-2
BUILD_INFO.json
{
"commit": "412b6877be9f62d1c8da613ddef500974c956e59",
"commit": "ab717ef245b299191fdc5c2b1f51497f127f0786",
"dirty": true,
"target": "firefox",
"dev": false,
"version": "0.2.4",
"version": "0.2.5",
"senders": [

@@ -8,0 +8,0 @@ "https://sdk-cdn.dev.0hash.com/*",

@@ -629,2 +629,19 @@ (function(exports) {

}
async function callMain(operation, payload, timeoutMs) {
const resp = await relayToMain({
id: generateId(),
role: ROLE_BACKGROUND,
platform: "",
operation,
payload,
selfDrivenUi: true,
telemetry: eventsEnabled()
}, timeoutMs);
adoptCaptureDrafts(resp);
if (!resp.success) {
const message = resp.error ?? `MAIN op failed: ${operation}`;
throw resp.retryable ? new RetryableError(message) : new Error(message);
}
return resp.data;
}
async function runSideEffecting(message, handler) {

@@ -689,2 +706,3 @@ const collector = new TraceCollector(message.operation);

//#endregion
exports.callMain = callMain;
exports.captureForget = captureForget;

@@ -691,0 +709,0 @@ exports.captureRead = captureRead;

@@ -447,3 +447,6 @@ (function() {

TagRequired: "WITHDRAWAL_TAG_REQUIRED",
Indeterminate: "KRAKEN_BALANCES_INDETERMINATE"
Indeterminate: "KRAKEN_BALANCES_INDETERMINATE",
AddressNotWhitelisted: "WITHDRAWAL_ADDRESS_NOT_WHITELISTED",
ChallengeUnmapped: "KRAKEN_WITHDRAW_CHALLENGE_UNMAPPED",
MaxUnavailable: "KRAKEN_WITHDRAW_MAX_UNAVAILABLE"
};

@@ -1227,2 +1230,18 @@ function isTransientStatus(status) {

//#endregion
//#region src/platforms/kraken/method-select.ts
function selectByNetwork(options, asset, network, noun) {
if (options.length === 0) throw new RetryableError(`No ${noun} methods available for ${asset}`);
if (options.length === 1) return options[0];
const listOptions = () => options.map((o) => o.network).join(", ");
if (network) {
const n = network.trim().toLowerCase();
const exact = options.find((o) => o.network.toLowerCase() === n || o.method.toLowerCase() === n);
if (exact) return exact;
const partial = options.filter((o) => o.network.toLowerCase().includes(n) || o.method.toLowerCase().includes(n));
if (partial.length === 1) return partial[0];
throw new Error(`${partial.length === 0 ? "No" : "Ambiguous"} Kraken ${noun} network matching "${network}" for ${asset}. Options: ${listOptions()}`);
}
throw new Error(`${asset} has multiple ${noun} networks; specify one. Options: ${listOptions()}`);
}
//#endregion
//#region src/platforms/kraken/operations/get-deposit-address.ts

@@ -1264,3 +1283,3 @@ init_dist();

function resolveMethod(rows, asset, network) {
const options = (Array.isArray(rows) ? rows : []).map((e) => e.name ? {
return selectByNetwork((Array.isArray(rows) ? rows : []).map((e) => e.name ? {
method: e.name,

@@ -1271,15 +1290,3 @@ network: e.deposit_network_info?.network ?? e.name,

limits: toLimits(e.limits, asset)
} : null).filter((o) => o !== null);
if (options.length === 0) throw new RetryableError(`No deposit methods available for ${asset}`);
if (options.length === 1) return options[0];
const listOptions = () => options.map((o) => o.network).join(", ");
if (network) {
const n = network.trim().toLowerCase();
const exact = options.find((o) => o.network.toLowerCase() === n || o.method.toLowerCase() === n);
if (exact) return exact;
const partial = options.filter((o) => o.network.toLowerCase().includes(n) || o.method.toLowerCase().includes(n));
if (partial.length === 1) return partial[0];
throw new Error(`${partial.length === 0 ? "No" : "Ambiguous"} Kraken deposit network matching "${network}" for ${asset}. Options: ${listOptions()}`);
}
throw new Error(`${asset} has multiple deposit networks; specify one. Options: ${listOptions()}`);
} : null).filter((o) => o !== null), asset, network, "deposit");
}

@@ -1403,3 +1410,8 @@ function resolveDestinationTag(row, asset) {

getBalance,
getDepositAddress
getDepositAddress,
"kraken.csrf.mint": async (payload) => {
const intent = payload?.intent;
if (!intent || typeof intent !== "string") throw new Error("kraken.csrf.mint requires an { intent } string");
return { token: await mintCsrfToken(intent) };
}
});

@@ -1406,0 +1418,0 @@ window.__zeroauth = {

@@ -5,2 +5,3 @@ (function() {

var ROLE_CONTENT = "zeroauth-content";
var ROLE_BACKGROUND = "zeroauth-background";
var MSG_CHALLENGE_COVER = "zeroauth-challenge-cover";

@@ -174,2 +175,5 @@ var CAPABILITY_PORT_HANDSHAKE = "zeroauth-capability-port";

}
function activeEventCollector() {
return activeCollector$1;
}
function eventsEnabled() {

@@ -264,2 +268,5 @@ return activeCollector$1 !== void 0;

}
function pushBreadcrumb(phase, note) {
activeCollector?.enter(phase, note);
}
function redactContext(c) {

@@ -597,2 +604,23 @@ const out = {};

}
function adoptCaptureDrafts(resp) {
const drafts = pullDrafts(resp);
if (drafts) activeEventCollector()?.adopt(drafts);
}
async function callMain(operation, payload, timeoutMs) {
const resp = await relayToMain({
id: generateId(),
role: ROLE_BACKGROUND,
platform: "",
operation,
payload,
selfDrivenUi: true,
telemetry: eventsEnabled()
}, timeoutMs);
adoptCaptureDrafts(resp);
if (!resp.success) {
const message = resp.error ?? `MAIN op failed: ${operation}`;
throw resp.retryable ? new RetryableError(message) : new Error(message);
}
return resp.data;
}
async function runSideEffecting(message, handler) {

@@ -657,2 +685,264 @@ const collector = new TraceCollector(message.operation);

//#endregion
//#region src/platforms/kraken/operations/withdraw/transport.ts
var current = {
mintToken: () => {
throw new Error("kraken withdraw transport not wired (see isolated.ts)");
},
request: () => {
throw new Error("kraken withdraw transport not wired (see isolated.ts)");
}
};
function setWriteTransport(transport) {
current = transport;
}
function writeTransport() {
return current;
}
//#endregion
//#region src/platforms/kraken/errors.ts
var KrakenErrorCode = {
RateLimited: "ErrRateLimited",
PlatformUnreachable: "ErrPlatformUnreachable",
NotLoggedIn: "ErrNotLoggedIn",
PlatformChanged: "ErrPlatformChanged",
TagRequired: "WITHDRAWAL_TAG_REQUIRED",
Indeterminate: "KRAKEN_BALANCES_INDETERMINATE",
AddressNotWhitelisted: "WITHDRAWAL_ADDRESS_NOT_WHITELISTED",
ChallengeUnmapped: "KRAKEN_WITHDRAW_CHALLENGE_UNMAPPED",
MaxUnavailable: "KRAKEN_WITHDRAW_MAX_UNAVAILABLE"
};
function isTransientStatus(status) {
return status === 429 || status >= 500;
}
function krakenErrorStrings(body) {
if (typeof body !== "object" || body === null) return [];
const b = body;
const raw = b.error ?? b.errors ?? b.message;
if (typeof raw === "string") return [raw];
if (Array.isArray(raw)) return raw.filter((e) => typeof e === "string");
return [];
}
function refineFromBody(body) {
const strings = krakenErrorStrings(body).map((s) => s.toLowerCase());
const has = (needle) => strings.some((s) => s.includes(needle));
if (has("permission") || has("not authenticated") || has("unauthorized") || has("login")) return KrakenErrorCode.NotLoggedIn;
return KrakenErrorCode.PlatformChanged;
}
function classifyKrakenError(status, body) {
if (isTransientStatus(status)) return {
code: status === 429 ? KrakenErrorCode.RateLimited : KrakenErrorCode.PlatformUnreachable,
retryable: true
};
if (status === 401 || status === 403) return {
code: KrakenErrorCode.NotLoggedIn,
retryable: false
};
return {
code: refineFromBody(body),
retryable: false
};
}
function krakenError(status, body, detail) {
const { code, retryable } = classifyKrakenError(status, body);
const message = detail ? `${code}: ${detail}` : code;
return retryable ? new RetryableError(message) : new Error(message);
}
function krakenCodedError(code, detail) {
return new Error(detail ? `${code}: ${detail}` : code);
}
//#endregion
//#region src/platforms/kraken/constants.ts
var TAG_REQUIRED_ASSETS = new Set([
"XRP",
"XLM",
"EOS",
"STX",
"ATOM"
]);
var KRAKEN_KORIGIN = "2081";
var KRAKEN_HANDLER_ENV = "stable";
//#endregion
//#region src/platforms/kraken/method-select.ts
function selectByNetwork(options, asset, network, noun) {
if (options.length === 0) throw new RetryableError(`No ${noun} methods available for ${asset}`);
if (options.length === 1) return options[0];
const listOptions = () => options.map((o) => o.network).join(", ");
if (network) {
const n = network.trim().toLowerCase();
const exact = options.find((o) => o.network.toLowerCase() === n || o.method.toLowerCase() === n);
if (exact) return exact;
const partial = options.filter((o) => o.network.toLowerCase().includes(n) || o.method.toLowerCase().includes(n));
if (partial.length === 1) return partial[0];
throw new Error(`${partial.length === 0 ? "No" : "Ambiguous"} Kraken ${noun} network matching "${network}" for ${asset}. Options: ${listOptions()}`);
}
throw new Error(`${asset} has multiple ${noun} networks; specify one. Options: ${listOptions()}`);
}
//#endregion
//#region src/platforms/kraken/operations/withdraw/iapi.ts
var IAPI_WITHDRAWALS = "https://iapi.kraken.com/api/internal/withdrawals";
var COMMON_QS = "asset_class=currency&preferred_asset_name=new";
var WITHDRAW_CSRF_INTENT = "WITHDRAW";
var CLIENT_CAPABILITIES = "dynamic_challenges_v1";
async function iapi(endpoint, url, init, raw = false) {
let res;
try {
res = await writeTransport().request(url, {
method: "GET",
headers: { accept: "application/json" },
...init
});
} catch (e) {
const detail = e instanceof Error ? e.message : String(e);
throw new RetryableError(`${KrakenErrorCode.PlatformUnreachable}: /withdrawals/${endpoint} unreachable — no HTTP response (${detail}). If this is a POST, suspect a rejected CORS preflight, which is also how a non-existent iapi path presents.`);
}
const body = res.body ?? {};
if (!res.ok) throw krakenError(res.status, body, `/withdrawals/${endpoint} ${res.status}`);
if (!raw && Array.isArray(body.errors) && body.errors.length > 0) throw new RetryableError(`Kraken /withdrawals/${endpoint} returned errors`);
return {
body,
status: res.status
};
}
function resolveWithdrawMethod(rows, asset, network) {
const chosen = selectByNetwork((Array.isArray(rows) ? rows : []).filter((r) => r.temp_disabled_public !== true).map((r) => {
if (!r.name) return null;
return {
method: r.name,
network: r.withdrawal_network_info?.network ?? r.name,
feeToken: typeof r.fee_token === "string" ? r.fee_token.trim() : "",
fee: r.fee ?? null,
minAmount: r.min_amount ?? null
};
}).filter((o) => o !== null), asset, network, "withdrawal");
if (!chosen.feeToken) throw new RetryableError(`Kraken returned no fee_token for ${asset} (${chosen.method}); cannot submit a withdrawal`);
return chosen;
}
async function fetchMethod(asset, network) {
pushBreadcrumb("methods", asset);
const { body } = await iapi("methods", `${IAPI_WITHDRAWALS}/methods?asset=${encodeURIComponent(asset)}&${COMMON_QS}`);
return resolveWithdrawMethod(body.result, asset, network);
}
function addressesMatch(a, b) {
const x = a.trim();
const y = b.trim();
const isEvm = (v) => /^0x[0-9a-fA-F]{40}$/.test(v);
return isEvm(x) && isEvm(y) ? x.toLowerCase() === y.toLowerCase() : x === y;
}
function rowAddress(row) {
return (row.info?.address ?? row.address ?? "").trim();
}
function rowLabel(row) {
return (row.id ?? row.name ?? "").trim();
}
function isPending(row) {
if ([
row.verified,
row.confirmed,
row.is_verified
].some((f) => f === false)) return true;
const text = `${row.status ?? ""} ${row.state ?? ""}`.toLowerCase();
return /pending|unverified|unconfirmed|awaiting/.test(text);
}
function resolveWhitelistEntry(rows, address, asset, method) {
const matches = (Array.isArray(rows) ? rows : []).filter((r) => (r.asset === void 0 || r.asset.toUpperCase() === asset) && (r.method === void 0 || r.method === method)).filter((r) => {
const a = rowAddress(r);
return a.length > 0 && addressesMatch(a, address) && rowLabel(r).length > 0;
});
if (matches.length === 0) throw krakenCodedError(KrakenErrorCode.AddressNotWhitelisted, `${asset} destination is not on this account's withdrawal whitelist (${method})`);
if (matches.some(isPending)) throw krakenCodedError(KrakenErrorCode.AddressNotWhitelisted, `${asset} destination is whitelisted but still awaiting email confirmation`);
const labels = new Set(matches.map(rowLabel));
if (labels.size > 1) throw krakenCodedError(KrakenErrorCode.AddressNotWhitelisted, `${asset} destination matches ${labels.size} whitelist entries; cannot choose one`);
const row = matches[0];
return {
label: rowLabel(row),
fee: row.fee ?? null,
minAmount: row.min_amount ?? null
};
}
async function fetchWhitelistEntry(address, asset, method) {
pushBreadcrumb("addresses", `${asset}/${method}`);
const { body } = await iapi("addresses", `${IAPI_WITHDRAWALS}/addresses?asset=${encodeURIComponent(asset)}&${COMMON_QS}`);
return resolveWhitelistEntry(body.result, address, asset, method);
}
async function submit(asset, method, name, amount, feeToken, destinationTag) {
const token = await writeTransport().mintToken(WITHDRAW_CSRF_INTENT);
pushBreadcrumb("submit", `${asset}/${method}`);
const { body, status } = await iapi("submit", IAPI_WITHDRAWALS, {
method: "POST",
headers: {
accept: "application/json",
"content-type": "application/json",
"x-csrf-token": token,
"x-korigin": KRAKEN_KORIGIN,
"x-handler-environment": KRAKEN_HANDLER_ENV,
"x-kraken-client-capabilities": CLIENT_CAPABILITIES
},
body: JSON.stringify({
amount,
asset,
asset_class: "currency",
name,
fee_included: false,
method,
fee_token: feeToken,
...destinationTag ? { info: { address_tag: destinationTag } } : {}
})
}, true);
const result = body.result;
const txId = result && typeof result === "object" && typeof result.transaction_id === "string" ? result.transaction_id : null;
const rawStatus = result && typeof result === "object" ? result.status : void 0;
return {
transactionId: txId,
status: typeof rawStatus === "string" ? rawStatus : null,
result: body.result ?? null,
status_code: status
};
}
function resolveTag(payload, asset) {
const tag = payload.destinationTag?.trim();
if (!tag && TAG_REQUIRED_ASSETS.has(asset)) throw krakenCodedError(KrakenErrorCode.TagRequired, `${asset} requires a destination tag/memo; sending without it would permanently lose the funds`);
return tag || void 0;
}
function resolveAmount(amount, asset) {
if (amount === "max") throw krakenCodedError(KrakenErrorCode.MaxUnavailable, `Kraken exposes no authoritative maximum for ${asset}; send an explicit amount`);
const spec = amount;
if (spec.currency !== "asset") throw new Error(`Kraken ${asset} withdrawal amount must be asset-denominated (in ${asset}); got currency "${spec.currency}". Pass { currency: "asset" }.`);
const raw = spec.value.trim();
if (!/^\d+(\.\d+)?$/.test(raw) || !(Number(raw) > 0)) throw new Error(`Kraken ${asset} withdrawal requires a positive amount; got "${spec.value}".`);
return raw;
}
async function resolveDestination(payload) {
const asset = payload.asset.trim().toUpperCase();
const tag = resolveTag(payload, asset);
const method = await fetchMethod(asset, payload.network);
const entry = await fetchWhitelistEntry(payload.address, asset, method.method);
return {
asset,
method: method.method,
network: method.network,
name: entry.label,
tag,
feeToken: method.feeToken,
fee: entry.fee ?? method.fee,
minAmount: entry.minAmount ?? method.minAmount
};
}
async function submitResolved(dest, amountSpec) {
const amount = resolveAmount(amountSpec, dest.asset);
return {
outcome: await submit(dest.asset, dest.method, dest.name, amount, dest.feeToken, dest.tag),
details: {
fiatAmount: null,
cryptoAmount: amount,
recipient: dest.name,
network: dest.network,
timeEstimate: null,
fee: dest.fee
}
};
}
async function runWithdraw(payload) {
return submitResolved(await resolveDestination(payload), payload.amount);
}
//#endregion
//#region src/platforms/kraken/operations/withdraw/index.ts

@@ -674,6 +964,34 @@ var STATE_KEY = "__zeroauthKrakenWithdraw";

var WITHDRAW_NOT_IMPLEMENTED = "withdraw/not-implemented: driving lands in AUTH-3714";
function validateStartPayload(payload) {
var DEFAULT_SUBMIT_STATUS = "PENDING";
var CHALLENGE_HINTS = [
"challenge",
"challenges",
"challenge_type",
"required_action",
"action"
];
function challengeHint(result) {
if (!result || typeof result !== "object") return "no transaction_id in response";
const keys = Object.keys(result);
const hit = keys.filter((k) => CHALLENGE_HINTS.includes(k.toLowerCase()));
return hit.length > 0 ? `challenge-shaped response (keys: ${hit.join(", ")})` : `no transaction_id in response (keys: ${keys.join(", ")})`;
}
function mapWithdrawOutcome(outcome, details) {
if (outcome.transactionId) return {
state: "submitted",
result: {
status: outcome.status ?? DEFAULT_SUBMIT_STATUS,
completeBefore: null,
referenceId: outcome.transactionId,
sendUuid: null,
details
}
};
throw krakenCodedError(KrakenErrorCode.ChallengeUnmapped, `${challengeHint(outcome.result)}; HTTP ${outcome.status_code}`);
}
function validateDestinationPayload(payload) {
for (const field of ["asset", "address"]) if (!payload[field] || typeof payload[field] !== "string") throw new Error(`withdraw/invalid-payload: ${field}`);
if (payload.network !== void 0 && typeof payload.network !== "string") throw new Error(`withdraw/invalid-payload: network must be a string when provided`);
const amount = payload.amount;
}
function validateAmount(amount) {
if (amount === "max") return;

@@ -684,7 +1002,20 @@ if (!amount || typeof amount !== "object" || typeof amount.value !== "string" || amount.currency !== "asset" && amount.currency !== "fiat") throw new Error(`withdraw/invalid-payload: amount must be "max" or { value: string, currency: "asset" | "fiat" }`);

}
var AWAITING_AMOUNT = {
state: "awaiting-input",
kind: "amount"
};
async function startWithdraw(payloadRaw) {
validateStartPayload(payloadRaw ?? {});
const payload = payloadRaw ?? {};
const checkFirst = payload.amount === void 0;
validateDestinationPayload(payload);
if (!checkFirst) validateAmount(payload.amount);
const state = moduleState();
state.details = null;
throw new Error(WITHDRAW_NOT_IMPLEMENTED);
if (checkFirst) {
await resolveDestination(payload);
return AWAITING_AMOUNT;
}
const { outcome, details } = await runWithdraw(payload);
state.details = details;
return mapWithdrawOutcome(outcome, details);
}

@@ -694,2 +1025,16 @@ async function continueWithdraw(payloadRaw) {

if (!payload || typeof payload !== "object" || !("kind" in payload)) throw new Error(`withdraw/invalid-payload: kind`);
if (payload.kind === "amount") {
const request = payload.request ?? {};
validateDestinationPayload(request);
validateAmount(request.amount);
const { outcome, details } = await runWithdraw(request);
moduleState().details = details;
return mapWithdrawOutcome(outcome, details);
}
if (payload.kind === "check-address") {
const request = payload.request ?? {};
validateDestinationPayload(request);
await resolveDestination(request);
return AWAITING_AMOUNT;
}
if (payload.kind === "otp") {

@@ -708,2 +1053,26 @@ if (!payload.code || !/^\d{6}$/.test(payload.code)) throw new Error(`withdraw/invalid-payload: code (expected 6 digits)`);

//#region src/platforms/kraken/isolated.ts
var CSRF_MINT_TIMEOUT_MS = 2e4;
setWriteTransport({
async mintToken(intent) {
const token = (await callMain("kraken.csrf.mint", { intent }, CSRF_MINT_TIMEOUT_MS))?.token;
if (typeof token !== "string" || !token) throw new Error("kraken.csrf.mint returned no token");
return token;
},
async request(url, init) {
const res = await fetch(url, {
credentials: "include",
...init
});
const text = await res.text();
let body = null;
try {
body = JSON.parse(text);
} catch {}
return {
status: res.status,
ok: res.ok,
body
};
}
});
registerSideEffectHandler("withdraw.start", startWithdraw);

@@ -710,0 +1079,0 @@ registerSideEffectHandler("withdraw.continue", continueWithdraw);

{
"manifest_version": 3,
"name": "zerohash",
"version": "0.2.4",
"version": "0.2.5",
"minimum_chrome_version": "102",

@@ -6,0 +6,0 @@ "description": "Programmatic access to platform data via window API",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet