Initial commit
This commit is contained in:
28
scripts/check-map-ohlcv.js
Normal file
28
scripts/check-map-ohlcv.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/** ponytail: assert TV resolutions map 1:1 to Dena periods (no 180→240 / 480→720). */
|
||||
const assert = require("assert");
|
||||
const { tradingViewResolutionToDena } = require("../src/lib/mapOhlcv");
|
||||
|
||||
const cases = [
|
||||
["60", 60],
|
||||
["120", 120],
|
||||
["240", 240],
|
||||
["360", 360],
|
||||
["720", 720],
|
||||
["1D", 1440],
|
||||
["D", 1440],
|
||||
["d", 1440],
|
||||
];
|
||||
|
||||
for (const [res, period] of cases) {
|
||||
assert.strictEqual(
|
||||
tradingViewResolutionToDena(res),
|
||||
period,
|
||||
`${res} → ${period}`
|
||||
);
|
||||
}
|
||||
|
||||
// Fake intervals must NOT silently alias to a different bucket.
|
||||
assert.strictEqual(tradingViewResolutionToDena("180"), 180);
|
||||
assert.strictEqual(tradingViewResolutionToDena("480"), 480);
|
||||
|
||||
console.log("ok: mapOhlcv TV resolutions");
|
||||
30
scripts/check-ranger-credentials.js
Normal file
30
scripts/check-ranger-credentials.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/** ponytail: assert ranger credentials + upstream URL/stream defaults. */
|
||||
const assert = require("assert");
|
||||
const {
|
||||
defaultPrivateStreams,
|
||||
buildUpstreamUrl,
|
||||
cookieUpstreamHeaders,
|
||||
} = require("../src/routes/ranger");
|
||||
|
||||
const streams = defaultPrivateStreams();
|
||||
assert.ok(streams.includes("order"));
|
||||
assert.ok(streams.includes("trade"));
|
||||
assert.ok(!streams.includes("balances"), "balances off by default (Finex)");
|
||||
|
||||
const url = buildUpstreamUrl(
|
||||
["trade", "order"],
|
||||
"ws://rango:8080/api/v2/ranger/private"
|
||||
);
|
||||
assert.ok(url.includes("/api/v2/ranger/private"));
|
||||
assert.ok(url.includes("stream=order"));
|
||||
assert.ok(url.includes("stream=trade"));
|
||||
assert.ok(!url.includes("balances"));
|
||||
|
||||
const headers = cookieUpstreamHeaders({
|
||||
cookies: "a=1",
|
||||
csrfToken: "csrf",
|
||||
});
|
||||
assert.strictEqual(headers.Cookie, "a=1");
|
||||
assert.strictEqual(headers["X-CSRF-Token"], "csrf");
|
||||
|
||||
console.log("check-ranger-credentials: ok");
|
||||
79
scripts/patch-tv-tehran-tz.js
Normal file
79
scripts/patch-tv-tehran-tz.js
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Patch TradingView charting_library Asia/Tehran zone:
|
||||
* Iran abolished DST in 2022 — permanently UTC+03:30 (12600s).
|
||||
*
|
||||
* IMPORTANT: TV binary-search returns -1 (→ offset 0 / UTC) when "now"
|
||||
* is past the LAST transition. A single-entry zone breaks modern charts.
|
||||
* Mirror Asia/Dubai: keep a far-future sentinel as the last time entry.
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// Both offsets 12600: permanent UTC+03:30 (no DST).
|
||||
// Sentinel ~2030 so current timestamps resolve to index 0/1 with +3:30, not UTC.
|
||||
const FIXED =
|
||||
'"Asia/Tehran":{time:[-1704153600,1925006400],offset:[12600,12600]}';
|
||||
|
||||
const FILES = [
|
||||
path.resolve(
|
||||
__dirname,
|
||||
"../../Gereh/src/charting_library/static/bundles/library.e964cdc99937c68d0389.js"
|
||||
),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
"../../Gereh/public/charting_library/static/bundles/library.e964cdc99937c68d0389.js"
|
||||
),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
"../../Shahoo/public/charting_library/static/bundles/library.e964cdc99937c68d0389.js"
|
||||
),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
"../../Shahoo/src/features/Market/MainComponents/TVChartContainer/charting_library/static/bundles/library.e964cdc99937c68d0389.js"
|
||||
),
|
||||
];
|
||||
|
||||
function extractTehran(s) {
|
||||
const key = '"Asia/Tehran":{';
|
||||
const i = s.indexOf(key);
|
||||
if (i < 0) return null;
|
||||
let depth = 0;
|
||||
let end = -1;
|
||||
for (let j = i + key.length - 1; j < s.length; j++) {
|
||||
if (s[j] === "{") depth++;
|
||||
else if (s[j] === "}") {
|
||||
depth--;
|
||||
if (depth === 0) {
|
||||
end = j + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end < 0) return null;
|
||||
return { start: i, end, text: s.slice(i, end) };
|
||||
}
|
||||
|
||||
let patched = 0;
|
||||
for (const file of FILES) {
|
||||
if (!fs.existsSync(file)) {
|
||||
console.log("skip missing:", file);
|
||||
continue;
|
||||
}
|
||||
const src = fs.readFileSync(file, "utf8");
|
||||
const hit = extractTehran(src);
|
||||
if (!hit) {
|
||||
console.log("skip no Tehran:", file);
|
||||
continue;
|
||||
}
|
||||
if (hit.text === FIXED) {
|
||||
console.log("already patched:", file);
|
||||
continue;
|
||||
}
|
||||
fs.writeFileSync(file, src.slice(0, hit.start) + FIXED + src.slice(hit.end));
|
||||
console.log("patched:", path.relative(process.cwd(), file));
|
||||
console.log(" was:", hit.text);
|
||||
console.log(" now:", FIXED);
|
||||
patched++;
|
||||
}
|
||||
|
||||
console.log("done, patched", patched, "file(s)");
|
||||
Reference in New Issue
Block a user