@signals-protocol/v1-sdk 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/share/index.d.ts +2 -1
- package/dist/share/index.js +3 -1
- package/dist/share/profile-image.d.ts +2 -0
- package/dist/share/profile-image.js +552 -0
- package/dist/share/types.d.ts +33 -0
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -10,4 +10,4 @@ export * as MathUtils from "./utils/math";
|
|
|
10
10
|
export { toWAD, toMicroUSDC } from "./clmsr-sdk";
|
|
11
11
|
export { createCLMSRSDK, createSignalsSDK } from "./clmsr-sdk";
|
|
12
12
|
export * from "./share";
|
|
13
|
-
export declare const VERSION = "1.
|
|
13
|
+
export declare const VERSION = "1.4.0";
|
package/dist/index.js
CHANGED
package/dist/share/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export type { SatoriNode, PositionImageInput, DistributionImageInput, PriceTick, BarCategory, } from "./types";
|
|
1
|
+
export type { SatoriNode, PositionImageInput, ProfileImageInput, ProfileChartPosition, DistributionImageInput, PriceTick, BarCategory, } from "./types";
|
|
2
2
|
export { buildPositionVNode } from "./position-image";
|
|
3
|
+
export { buildProfileVNode } from "./profile-image";
|
|
3
4
|
export { buildDistributionVNode } from "./distribution-image";
|
|
4
5
|
export { buildBrandVNode } from "./brand-image";
|
|
5
6
|
export { h } from "./h";
|
package/dist/share/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatDistributionPriceRange = exports.getPeakRange = exports.formatXTick = exports.generateXAxisTicks = exports.getSqrtHeight = exports.getBarCategory = exports.getPnlColor = exports.formatUsdPnl = exports.percForm = exports.formatPriceRange = exports.formatPrice = exports.formatUSDC = exports.buildLogoStrokeSVG = exports.SIGNALS_LOGO_URI = exports.h = exports.buildBrandVNode = exports.buildDistributionVNode = exports.buildPositionVNode = void 0;
|
|
3
|
+
exports.formatDistributionPriceRange = exports.getPeakRange = exports.formatXTick = exports.generateXAxisTicks = exports.getSqrtHeight = exports.getBarCategory = exports.getPnlColor = exports.formatUsdPnl = exports.percForm = exports.formatPriceRange = exports.formatPrice = exports.formatUSDC = exports.buildLogoStrokeSVG = exports.SIGNALS_LOGO_URI = exports.h = exports.buildBrandVNode = exports.buildDistributionVNode = exports.buildProfileVNode = exports.buildPositionVNode = void 0;
|
|
4
4
|
// VNode builders
|
|
5
5
|
var position_image_1 = require("./position-image");
|
|
6
6
|
Object.defineProperty(exports, "buildPositionVNode", { enumerable: true, get: function () { return position_image_1.buildPositionVNode; } });
|
|
7
|
+
var profile_image_1 = require("./profile-image");
|
|
8
|
+
Object.defineProperty(exports, "buildProfileVNode", { enumerable: true, get: function () { return profile_image_1.buildProfileVNode; } });
|
|
7
9
|
var distribution_image_1 = require("./distribution-image");
|
|
8
10
|
Object.defineProperty(exports, "buildDistributionVNode", { enumerable: true, get: function () { return distribution_image_1.buildDistributionVNode; } });
|
|
9
11
|
var brand_image_1 = require("./brand-image");
|
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildProfileVNode = buildProfileVNode;
|
|
4
|
+
const h_1 = require("./h");
|
|
5
|
+
const assets_1 = require("./assets");
|
|
6
|
+
const CARD_WIDTH = 1200;
|
|
7
|
+
const CARD_HEIGHT = 630;
|
|
8
|
+
const OUTER_PADDING = 24;
|
|
9
|
+
const CARD_PADDING_X = 32;
|
|
10
|
+
const CARD_PADDING_Y = 28;
|
|
11
|
+
const CHART_WIDTH = CARD_WIDTH - OUTER_PADDING * 2 - CARD_PADDING_X * 2;
|
|
12
|
+
const CHART_HEIGHT = 228;
|
|
13
|
+
const PLOT_LEFT = 56;
|
|
14
|
+
const PLOT_RIGHT = 18;
|
|
15
|
+
const PLOT_TOP = 14;
|
|
16
|
+
const PLOT_BOTTOM = 24;
|
|
17
|
+
const BAND_WIDTH = 18;
|
|
18
|
+
const OG_THEMES = {
|
|
19
|
+
light: {
|
|
20
|
+
pageBg: "#eef7ff", // bg-surface-soft
|
|
21
|
+
card: "#FFFFFF", // bg-card
|
|
22
|
+
ink: "#242424", // text-primary
|
|
23
|
+
inkMuted: "#737373", // text-secondary
|
|
24
|
+
border: "#EDEDED", // border-default
|
|
25
|
+
primary: "#1444c2", // brand-primary
|
|
26
|
+
positive: "#00BF40", // status-positive
|
|
27
|
+
negative: "#FF4343", // status-negative
|
|
28
|
+
bitcoin: "#F7931A", // bitcoin-accent
|
|
29
|
+
neutralBg: "#F4F4F4", // surface-muted
|
|
30
|
+
},
|
|
31
|
+
dark: {
|
|
32
|
+
pageBg: "#0F0F11", // bg-surface-soft
|
|
33
|
+
card: "#18181B", // bg-card
|
|
34
|
+
ink: "#E4E4E7", // text-primary
|
|
35
|
+
inkMuted: "#A1A1AA", // text-secondary
|
|
36
|
+
border: "#27272A", // border-default
|
|
37
|
+
primary: "#5B8DEF", // brand-primary
|
|
38
|
+
positive: "#4ADE80", // status-positive
|
|
39
|
+
negative: "#F87171", // status-negative
|
|
40
|
+
bitcoin: "#F7931A", // bitcoin-accent
|
|
41
|
+
neutralBg: "#27272A", // surface-muted
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const TIER_ACCENT_COLORS = {
|
|
45
|
+
BRONZE: "#C7742A",
|
|
46
|
+
SILVER: "#BFC6CE",
|
|
47
|
+
GOLD: "#F3BC3C",
|
|
48
|
+
PLATINUM: "#63CBB2",
|
|
49
|
+
DIAMOND: "#5EC0F2",
|
|
50
|
+
};
|
|
51
|
+
function shortenAddress(address) {
|
|
52
|
+
return `${address.slice(0, 6)}…${address.slice(-4)}`;
|
|
53
|
+
}
|
|
54
|
+
function resolveDisplayName(displayName) {
|
|
55
|
+
const resolved = displayName?.trim();
|
|
56
|
+
return resolved ? resolved : null;
|
|
57
|
+
}
|
|
58
|
+
function formatProfilePnl(value) {
|
|
59
|
+
const sign = value >= 0 ? "+" : "-";
|
|
60
|
+
return `${sign}$${Math.abs(value).toFixed(2)}`;
|
|
61
|
+
}
|
|
62
|
+
function formatProfileRoi(value) {
|
|
63
|
+
return `${value >= 0 ? "+" : ""}${value.toFixed(1)}%`;
|
|
64
|
+
}
|
|
65
|
+
function formatBestMult(value) {
|
|
66
|
+
if (value == null || value <= 1)
|
|
67
|
+
return "—";
|
|
68
|
+
return `${value.toFixed(2)}×`;
|
|
69
|
+
}
|
|
70
|
+
function getSignedValueColor(value, theme) {
|
|
71
|
+
if (value > 0)
|
|
72
|
+
return theme.positive;
|
|
73
|
+
if (value < 0)
|
|
74
|
+
return theme.negative;
|
|
75
|
+
return theme.inkMuted;
|
|
76
|
+
}
|
|
77
|
+
function normalizeStatus(status) {
|
|
78
|
+
if (status === "OPEN" ||
|
|
79
|
+
status === "WIN" ||
|
|
80
|
+
status === "LOSS" ||
|
|
81
|
+
status === "CLOSED") {
|
|
82
|
+
return status;
|
|
83
|
+
}
|
|
84
|
+
if (status === "PENDING") {
|
|
85
|
+
return "OPEN";
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function normalizePositions(positions) {
|
|
90
|
+
const normalized = [];
|
|
91
|
+
positions.forEach((position) => {
|
|
92
|
+
const status = normalizeStatus(position.status);
|
|
93
|
+
if (status == null)
|
|
94
|
+
return;
|
|
95
|
+
normalized.push({
|
|
96
|
+
...position,
|
|
97
|
+
status,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
return normalized;
|
|
101
|
+
}
|
|
102
|
+
function buildMainText(input) {
|
|
103
|
+
if (input.hideWallet)
|
|
104
|
+
return "A Signals trader";
|
|
105
|
+
return resolveDisplayName(input.displayName) ?? shortenAddress(input.address);
|
|
106
|
+
}
|
|
107
|
+
function buildSubline(input) {
|
|
108
|
+
const callCopy = `${input.totalCalls} BTC range calls`;
|
|
109
|
+
if (input.hideWallet)
|
|
110
|
+
return callCopy;
|
|
111
|
+
const parts = [];
|
|
112
|
+
if (resolveDisplayName(input.displayName) !== null) {
|
|
113
|
+
parts.push(shortenAddress(input.address));
|
|
114
|
+
}
|
|
115
|
+
if (input.twitter) {
|
|
116
|
+
parts.push(`@${input.twitter}`);
|
|
117
|
+
}
|
|
118
|
+
parts.push(callCopy);
|
|
119
|
+
return parts.join(" · ");
|
|
120
|
+
}
|
|
121
|
+
function getPriceTickStep(span) {
|
|
122
|
+
const target = span / 4;
|
|
123
|
+
const candidates = [
|
|
124
|
+
500,
|
|
125
|
+
1000,
|
|
126
|
+
2500,
|
|
127
|
+
5000,
|
|
128
|
+
10000,
|
|
129
|
+
25000,
|
|
130
|
+
50000,
|
|
131
|
+
100000,
|
|
132
|
+
250000,
|
|
133
|
+
500000,
|
|
134
|
+
1000000,
|
|
135
|
+
];
|
|
136
|
+
return candidates.find((step) => step >= target) ?? 1000000;
|
|
137
|
+
}
|
|
138
|
+
function getExpandedPriceBounds(min, max) {
|
|
139
|
+
const span = max - min;
|
|
140
|
+
const step = getPriceTickStep(span);
|
|
141
|
+
return {
|
|
142
|
+
min: Math.floor(min / step) * step,
|
|
143
|
+
max: Math.ceil(max / step) * step,
|
|
144
|
+
step,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function getPriceTicks(min, max, step) {
|
|
148
|
+
const ticks = [];
|
|
149
|
+
for (let tick = min; tick <= max + step / 2; tick += step) {
|
|
150
|
+
ticks.push(tick);
|
|
151
|
+
if (ticks.length >= 6)
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
return ticks.length > 0 ? ticks : [min, max];
|
|
155
|
+
}
|
|
156
|
+
function formatAxisLabel(value) {
|
|
157
|
+
if (Math.abs(value) >= 1000) {
|
|
158
|
+
return `$${Math.round(value / 1000)}k`;
|
|
159
|
+
}
|
|
160
|
+
return `$${Math.round(value)}`;
|
|
161
|
+
}
|
|
162
|
+
function computePriceBounds(btcHistory, positions) {
|
|
163
|
+
let rawMin = Infinity;
|
|
164
|
+
let rawMax = -Infinity;
|
|
165
|
+
let hasPrices = false;
|
|
166
|
+
btcHistory.forEach((point) => {
|
|
167
|
+
if (point.close < rawMin)
|
|
168
|
+
rawMin = point.close;
|
|
169
|
+
if (point.close > rawMax)
|
|
170
|
+
rawMax = point.close;
|
|
171
|
+
hasPrices = true;
|
|
172
|
+
});
|
|
173
|
+
positions.forEach((position) => {
|
|
174
|
+
if (position.lowerPrice < rawMin)
|
|
175
|
+
rawMin = position.lowerPrice;
|
|
176
|
+
if (position.lowerPrice > rawMax)
|
|
177
|
+
rawMax = position.lowerPrice;
|
|
178
|
+
if (position.upperPrice < rawMin)
|
|
179
|
+
rawMin = position.upperPrice;
|
|
180
|
+
if (position.upperPrice > rawMax)
|
|
181
|
+
rawMax = position.upperPrice;
|
|
182
|
+
hasPrices = true;
|
|
183
|
+
if (position.settlementPrice != null) {
|
|
184
|
+
if (position.settlementPrice < rawMin)
|
|
185
|
+
rawMin = position.settlementPrice;
|
|
186
|
+
if (position.settlementPrice > rawMax)
|
|
187
|
+
rawMax = position.settlementPrice;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
if (!hasPrices)
|
|
191
|
+
return null;
|
|
192
|
+
const span = rawMax - rawMin;
|
|
193
|
+
const padding = span === 0 ? 500 : span * 0.1;
|
|
194
|
+
return {
|
|
195
|
+
min: rawMin - padding,
|
|
196
|
+
max: rawMax + padding,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function computeTimeBounds(btcHistory, positions) {
|
|
200
|
+
let min = Infinity;
|
|
201
|
+
let max = -Infinity;
|
|
202
|
+
let hasTimes = false;
|
|
203
|
+
if (btcHistory.length > 0) {
|
|
204
|
+
const first = btcHistory[0].t;
|
|
205
|
+
const last = btcHistory[btcHistory.length - 1].t;
|
|
206
|
+
min = Math.min(first, last);
|
|
207
|
+
max = Math.max(first, last);
|
|
208
|
+
hasTimes = true;
|
|
209
|
+
}
|
|
210
|
+
positions.forEach((position) => {
|
|
211
|
+
if (position.marketEndTimestampMs < min)
|
|
212
|
+
min = position.marketEndTimestampMs;
|
|
213
|
+
if (position.marketEndTimestampMs > max)
|
|
214
|
+
max = position.marketEndTimestampMs;
|
|
215
|
+
hasTimes = true;
|
|
216
|
+
});
|
|
217
|
+
if (!hasTimes)
|
|
218
|
+
return null;
|
|
219
|
+
return {
|
|
220
|
+
min,
|
|
221
|
+
max,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function buildHistoryPath(btcHistory, scaleX, scaleY) {
|
|
225
|
+
return btcHistory
|
|
226
|
+
.map((point, index) => {
|
|
227
|
+
const command = index === 0 ? "M" : "L";
|
|
228
|
+
return `${command} ${scaleX(point.t).toFixed(2)} ${scaleY(point.close).toFixed(2)}`;
|
|
229
|
+
})
|
|
230
|
+
.join(" ");
|
|
231
|
+
}
|
|
232
|
+
function buildChartArea(theme, btcHistory, positions) {
|
|
233
|
+
const normalizedPositions = normalizePositions(positions);
|
|
234
|
+
const renderablePositions = normalizedPositions.filter((position) => position.status !== "CLOSED");
|
|
235
|
+
const sortedHistory = [...btcHistory].sort((a, b) => a.t - b.t);
|
|
236
|
+
if (btcHistory.length === 0 && renderablePositions.length === 0) {
|
|
237
|
+
return (0, h_1.h)("div", {
|
|
238
|
+
style: {
|
|
239
|
+
width: CHART_WIDTH,
|
|
240
|
+
height: CHART_HEIGHT,
|
|
241
|
+
display: "flex",
|
|
242
|
+
alignItems: "center",
|
|
243
|
+
justifyContent: "center",
|
|
244
|
+
background: theme.neutralBg,
|
|
245
|
+
border: `1px solid ${theme.border}`,
|
|
246
|
+
borderRadius: 20,
|
|
247
|
+
color: theme.inkMuted,
|
|
248
|
+
fontSize: 16,
|
|
249
|
+
fontWeight: 500,
|
|
250
|
+
overflow: "hidden",
|
|
251
|
+
},
|
|
252
|
+
}, "BTC history unavailable");
|
|
253
|
+
}
|
|
254
|
+
const bounds = computePriceBounds(sortedHistory, renderablePositions);
|
|
255
|
+
const timeBounds = computeTimeBounds(sortedHistory, renderablePositions);
|
|
256
|
+
if (!bounds || !timeBounds) {
|
|
257
|
+
return (0, h_1.h)("div", {
|
|
258
|
+
style: {
|
|
259
|
+
width: CHART_WIDTH,
|
|
260
|
+
height: CHART_HEIGHT,
|
|
261
|
+
display: "flex",
|
|
262
|
+
background: theme.neutralBg,
|
|
263
|
+
border: `1px solid ${theme.border}`,
|
|
264
|
+
borderRadius: 20,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
const plotWidth = CHART_WIDTH - PLOT_LEFT - PLOT_RIGHT;
|
|
269
|
+
const plotHeight = CHART_HEIGHT - PLOT_TOP - PLOT_BOTTOM;
|
|
270
|
+
const timeMin = timeBounds.min;
|
|
271
|
+
const timeMax = timeBounds.max;
|
|
272
|
+
const priceBounds = getExpandedPriceBounds(bounds.min, bounds.max);
|
|
273
|
+
const scaleX = (value) => {
|
|
274
|
+
if (timeMin === timeMax) {
|
|
275
|
+
return PLOT_LEFT + plotWidth / 2;
|
|
276
|
+
}
|
|
277
|
+
return PLOT_LEFT + ((value - timeMin) / (timeMax - timeMin)) * plotWidth;
|
|
278
|
+
};
|
|
279
|
+
const scaleY = (value) => {
|
|
280
|
+
if (priceBounds.max === priceBounds.min) {
|
|
281
|
+
return PLOT_TOP + plotHeight / 2;
|
|
282
|
+
}
|
|
283
|
+
return (PLOT_TOP +
|
|
284
|
+
(1 -
|
|
285
|
+
(value - priceBounds.min) / (priceBounds.max - priceBounds.min)) *
|
|
286
|
+
plotHeight);
|
|
287
|
+
};
|
|
288
|
+
const priceTicks = getPriceTicks(priceBounds.min, priceBounds.max, priceBounds.step);
|
|
289
|
+
const hasOpenPositions = renderablePositions.some((position) => position.status === "OPEN");
|
|
290
|
+
const svgChildren = [];
|
|
291
|
+
if (hasOpenPositions) {
|
|
292
|
+
svgChildren.push((0, h_1.h)("defs", null, (0, h_1.h)("pattern", {
|
|
293
|
+
id: "profile-open-band",
|
|
294
|
+
width: 8,
|
|
295
|
+
height: 8,
|
|
296
|
+
patternUnits: "userSpaceOnUse",
|
|
297
|
+
}, (0, h_1.h)("path", {
|
|
298
|
+
d: "M-2 8 L8 -2 M0 10 L10 0 M2 12 L12 2",
|
|
299
|
+
stroke: theme.bitcoin,
|
|
300
|
+
strokeWidth: 2,
|
|
301
|
+
}))));
|
|
302
|
+
}
|
|
303
|
+
priceTicks.forEach((tick) => {
|
|
304
|
+
const y = scaleY(tick);
|
|
305
|
+
svgChildren.push((0, h_1.h)("line", {
|
|
306
|
+
x1: PLOT_LEFT,
|
|
307
|
+
x2: PLOT_LEFT + plotWidth,
|
|
308
|
+
y1: y,
|
|
309
|
+
y2: y,
|
|
310
|
+
stroke: theme.border,
|
|
311
|
+
strokeDasharray: "2 3",
|
|
312
|
+
strokeWidth: 1,
|
|
313
|
+
}));
|
|
314
|
+
});
|
|
315
|
+
renderablePositions.forEach((position) => {
|
|
316
|
+
const topPrice = Math.max(position.lowerPrice, position.upperPrice);
|
|
317
|
+
const bottomPrice = Math.min(position.lowerPrice, position.upperPrice);
|
|
318
|
+
const x = scaleX(position.marketEndTimestampMs) - BAND_WIDTH / 2;
|
|
319
|
+
const top = scaleY(topPrice);
|
|
320
|
+
const bottom = scaleY(bottomPrice);
|
|
321
|
+
const height = Math.max(bottom - top, 6);
|
|
322
|
+
if (position.status === "OPEN") {
|
|
323
|
+
svgChildren.push((0, h_1.h)("rect", {
|
|
324
|
+
x,
|
|
325
|
+
y: top,
|
|
326
|
+
width: BAND_WIDTH,
|
|
327
|
+
height,
|
|
328
|
+
rx: 6,
|
|
329
|
+
fill: "url(#profile-open-band)",
|
|
330
|
+
stroke: theme.bitcoin,
|
|
331
|
+
strokeWidth: 2,
|
|
332
|
+
}));
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const fill = position.status === "WIN" ? theme.primary : theme.negative;
|
|
336
|
+
const fillOpacity = position.status === "WIN" ? 0.55 : 0.28;
|
|
337
|
+
svgChildren.push((0, h_1.h)("rect", {
|
|
338
|
+
x,
|
|
339
|
+
y: top,
|
|
340
|
+
width: BAND_WIDTH,
|
|
341
|
+
height,
|
|
342
|
+
rx: 6,
|
|
343
|
+
fill,
|
|
344
|
+
fillOpacity,
|
|
345
|
+
stroke: fill,
|
|
346
|
+
strokeOpacity: 0.9,
|
|
347
|
+
}));
|
|
348
|
+
});
|
|
349
|
+
if (sortedHistory.length === 1) {
|
|
350
|
+
svgChildren.push((0, h_1.h)("circle", {
|
|
351
|
+
cx: scaleX(sortedHistory[0].t),
|
|
352
|
+
cy: scaleY(sortedHistory[0].close),
|
|
353
|
+
r: 5,
|
|
354
|
+
fill: theme.ink,
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
else if (sortedHistory.length > 1) {
|
|
358
|
+
svgChildren.push((0, h_1.h)("path", {
|
|
359
|
+
d: buildHistoryPath(sortedHistory, scaleX, scaleY),
|
|
360
|
+
fill: "none",
|
|
361
|
+
stroke: theme.ink,
|
|
362
|
+
strokeWidth: 2,
|
|
363
|
+
strokeLinecap: "round",
|
|
364
|
+
strokeLinejoin: "round",
|
|
365
|
+
}));
|
|
366
|
+
}
|
|
367
|
+
renderablePositions.forEach((position) => {
|
|
368
|
+
if ((position.status === "WIN" || position.status === "LOSS") &&
|
|
369
|
+
position.settlementPrice != null) {
|
|
370
|
+
svgChildren.push((0, h_1.h)("circle", {
|
|
371
|
+
cx: scaleX(position.marketEndTimestampMs),
|
|
372
|
+
cy: scaleY(position.settlementPrice),
|
|
373
|
+
r: 4.5,
|
|
374
|
+
fill: position.status === "WIN" ? theme.primary : theme.negative,
|
|
375
|
+
}));
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
const labelNodes = priceTicks.map((tick) => (0, h_1.h)("div", {
|
|
379
|
+
style: {
|
|
380
|
+
position: "absolute",
|
|
381
|
+
left: 12,
|
|
382
|
+
top: scaleY(tick) - 9,
|
|
383
|
+
display: "flex",
|
|
384
|
+
fontSize: 13,
|
|
385
|
+
fontWeight: 500,
|
|
386
|
+
color: theme.inkMuted,
|
|
387
|
+
background: theme.card,
|
|
388
|
+
padding: "0 4px",
|
|
389
|
+
},
|
|
390
|
+
}, formatAxisLabel(tick)));
|
|
391
|
+
return (0, h_1.h)("div", {
|
|
392
|
+
style: {
|
|
393
|
+
width: CHART_WIDTH,
|
|
394
|
+
height: CHART_HEIGHT,
|
|
395
|
+
display: "flex",
|
|
396
|
+
position: "relative",
|
|
397
|
+
overflow: "hidden",
|
|
398
|
+
background: theme.neutralBg,
|
|
399
|
+
border: `1px solid ${theme.border}`,
|
|
400
|
+
borderRadius: 20,
|
|
401
|
+
},
|
|
402
|
+
}, (0, h_1.h)("svg", {
|
|
403
|
+
width: CHART_WIDTH,
|
|
404
|
+
height: CHART_HEIGHT,
|
|
405
|
+
viewBox: `0 0 ${CHART_WIDTH} ${CHART_HEIGHT}`,
|
|
406
|
+
style: {
|
|
407
|
+
position: "absolute",
|
|
408
|
+
inset: 0,
|
|
409
|
+
display: "flex",
|
|
410
|
+
pointerEvents: "none",
|
|
411
|
+
},
|
|
412
|
+
}, ...svgChildren), ...labelNodes);
|
|
413
|
+
}
|
|
414
|
+
function buildStatCard(label, value, valueColor, theme) {
|
|
415
|
+
return (0, h_1.h)("div", {
|
|
416
|
+
style: {
|
|
417
|
+
flex: 1,
|
|
418
|
+
display: "flex",
|
|
419
|
+
flexDirection: "column",
|
|
420
|
+
padding: "16px 18px",
|
|
421
|
+
borderRadius: 18,
|
|
422
|
+
border: `1px solid ${theme.border}`,
|
|
423
|
+
background: theme.neutralBg,
|
|
424
|
+
},
|
|
425
|
+
}, (0, h_1.h)("div", {
|
|
426
|
+
style: {
|
|
427
|
+
display: "flex",
|
|
428
|
+
fontSize: 14,
|
|
429
|
+
fontWeight: 500,
|
|
430
|
+
color: theme.inkMuted,
|
|
431
|
+
marginBottom: 10,
|
|
432
|
+
},
|
|
433
|
+
}, label), (0, h_1.h)("div", {
|
|
434
|
+
style: {
|
|
435
|
+
display: "flex",
|
|
436
|
+
fontSize: 28,
|
|
437
|
+
lineHeight: 1.1,
|
|
438
|
+
fontWeight: 700,
|
|
439
|
+
color: valueColor,
|
|
440
|
+
},
|
|
441
|
+
}, value));
|
|
442
|
+
}
|
|
443
|
+
function buildProfileVNode(input) {
|
|
444
|
+
const theme = OG_THEMES[input.theme];
|
|
445
|
+
const accent = TIER_ACCENT_COLORS[input.tier];
|
|
446
|
+
const mainText = buildMainText(input);
|
|
447
|
+
const subline = buildSubline(input);
|
|
448
|
+
const pnlValue = input.hideAmounts ? "••••" : formatProfilePnl(input.totalPnl);
|
|
449
|
+
const roiValue = formatProfileRoi(input.roi);
|
|
450
|
+
const bestMultValue = formatBestMult(input.bestMult);
|
|
451
|
+
return (0, h_1.h)("div", {
|
|
452
|
+
style: {
|
|
453
|
+
width: CARD_WIDTH,
|
|
454
|
+
height: CARD_HEIGHT,
|
|
455
|
+
display: "flex",
|
|
456
|
+
padding: OUTER_PADDING,
|
|
457
|
+
fontFamily: "Inter",
|
|
458
|
+
background: `linear-gradient(135deg, ${theme.pageBg}, ${theme.card})`,
|
|
459
|
+
},
|
|
460
|
+
}, (0, h_1.h)("div", {
|
|
461
|
+
style: {
|
|
462
|
+
flex: 1,
|
|
463
|
+
display: "flex",
|
|
464
|
+
flexDirection: "column",
|
|
465
|
+
padding: `${CARD_PADDING_Y}px ${CARD_PADDING_X}px`,
|
|
466
|
+
background: theme.card,
|
|
467
|
+
border: `1px solid ${theme.border}`,
|
|
468
|
+
borderRadius: 24,
|
|
469
|
+
},
|
|
470
|
+
}, (0, h_1.h)("div", {
|
|
471
|
+
style: {
|
|
472
|
+
display: "flex",
|
|
473
|
+
alignItems: "center",
|
|
474
|
+
justifyContent: "space-between",
|
|
475
|
+
},
|
|
476
|
+
}, (0, h_1.h)("div", {
|
|
477
|
+
style: {
|
|
478
|
+
display: "flex",
|
|
479
|
+
alignItems: "center",
|
|
480
|
+
gap: 10,
|
|
481
|
+
},
|
|
482
|
+
}, (0, h_1.h)("img", {
|
|
483
|
+
src: assets_1.SIGNALS_LOGO_URI,
|
|
484
|
+
width: 34,
|
|
485
|
+
height: 32,
|
|
486
|
+
style: { display: "flex" },
|
|
487
|
+
}), (0, h_1.h)("div", {
|
|
488
|
+
style: {
|
|
489
|
+
display: "flex",
|
|
490
|
+
fontSize: 28,
|
|
491
|
+
fontWeight: 700,
|
|
492
|
+
color: theme.primary,
|
|
493
|
+
},
|
|
494
|
+
}, "Signals")), (0, h_1.h)("div", {
|
|
495
|
+
style: {
|
|
496
|
+
display: "flex",
|
|
497
|
+
fontSize: 18,
|
|
498
|
+
fontWeight: 700,
|
|
499
|
+
letterSpacing: "0.04em",
|
|
500
|
+
textTransform: "uppercase",
|
|
501
|
+
color: accent,
|
|
502
|
+
},
|
|
503
|
+
}, input.tier)), (0, h_1.h)("div", {
|
|
504
|
+
style: {
|
|
505
|
+
flex: 1,
|
|
506
|
+
display: "flex",
|
|
507
|
+
flexDirection: "column",
|
|
508
|
+
marginTop: 20,
|
|
509
|
+
},
|
|
510
|
+
}, (0, h_1.h)("div", {
|
|
511
|
+
style: {
|
|
512
|
+
display: "flex",
|
|
513
|
+
flexDirection: "column",
|
|
514
|
+
},
|
|
515
|
+
}, (0, h_1.h)("div", {
|
|
516
|
+
style: {
|
|
517
|
+
display: "flex",
|
|
518
|
+
fontSize: 52,
|
|
519
|
+
lineHeight: 1.05,
|
|
520
|
+
fontWeight: 700,
|
|
521
|
+
color: theme.ink,
|
|
522
|
+
marginBottom: 10,
|
|
523
|
+
},
|
|
524
|
+
}, mainText), (0, h_1.h)("div", {
|
|
525
|
+
style: {
|
|
526
|
+
display: "flex",
|
|
527
|
+
fontSize: 20,
|
|
528
|
+
fontWeight: 500,
|
|
529
|
+
color: theme.inkMuted,
|
|
530
|
+
},
|
|
531
|
+
}, subline)), (0, h_1.h)("div", {
|
|
532
|
+
style: {
|
|
533
|
+
display: "flex",
|
|
534
|
+
marginTop: 24,
|
|
535
|
+
},
|
|
536
|
+
}, buildChartArea(theme, input.btcHistory, input.positions)), (0, h_1.h)("div", {
|
|
537
|
+
style: {
|
|
538
|
+
display: "flex",
|
|
539
|
+
gap: 16,
|
|
540
|
+
marginTop: 20,
|
|
541
|
+
},
|
|
542
|
+
}, buildStatCard("P&L", pnlValue, getSignedValueColor(input.totalPnl, theme), theme), buildStatCard("ROI", roiValue, getSignedValueColor(input.roi, theme), theme), buildStatCard("Best call", bestMultValue, theme.primary, theme)), (0, h_1.h)("div", {
|
|
543
|
+
style: {
|
|
544
|
+
display: "flex",
|
|
545
|
+
justifyContent: "flex-end",
|
|
546
|
+
marginTop: 16,
|
|
547
|
+
fontSize: 13,
|
|
548
|
+
fontWeight: 500,
|
|
549
|
+
color: theme.inkMuted,
|
|
550
|
+
},
|
|
551
|
+
}, "signals.wtf · Pick your range"))));
|
|
552
|
+
}
|
package/dist/share/types.d.ts
CHANGED
|
@@ -22,6 +22,39 @@ export interface PositionImageInput {
|
|
|
22
22
|
/** Current position value in USDC (NOT raw). null = use max payout fallback. */
|
|
23
23
|
currentValue: number | null;
|
|
24
24
|
}
|
|
25
|
+
export interface ProfileChartPosition {
|
|
26
|
+
lowerPrice: number;
|
|
27
|
+
upperPrice: number;
|
|
28
|
+
settlementPrice: number | null;
|
|
29
|
+
status: "OPEN" | "WIN" | "LOSS" | "CLOSED";
|
|
30
|
+
marketEndTimestampMs: number;
|
|
31
|
+
}
|
|
32
|
+
export interface ProfileImageInput {
|
|
33
|
+
displayName: string | null;
|
|
34
|
+
address: string;
|
|
35
|
+
twitter: string | null;
|
|
36
|
+
tier: "BRONZE" | "SILVER" | "GOLD" | "PLATINUM" | "DIAMOND";
|
|
37
|
+
totalCalls: number;
|
|
38
|
+
totalPnl: number;
|
|
39
|
+
roi: number;
|
|
40
|
+
bestMult: number | null;
|
|
41
|
+
/**
|
|
42
|
+
* BTC daily close timeline.
|
|
43
|
+
*
|
|
44
|
+
* Must be sorted ascending by `t` (UNIX ms). Adapters should pass
|
|
45
|
+
* ordered data, and the builder defensively re-sorts a shallow copy
|
|
46
|
+
* before rendering so chart bounds and SVG path order stay correct
|
|
47
|
+
* even if input arrives out of order.
|
|
48
|
+
*/
|
|
49
|
+
btcHistory: Array<{
|
|
50
|
+
t: number;
|
|
51
|
+
close: number;
|
|
52
|
+
}>;
|
|
53
|
+
positions: ProfileChartPosition[];
|
|
54
|
+
theme: "light" | "dark";
|
|
55
|
+
hideWallet: boolean;
|
|
56
|
+
hideAmounts: boolean;
|
|
57
|
+
}
|
|
25
58
|
export type BarCategory = "peak" | "high" | "mid" | "low";
|
|
26
59
|
export interface PriceTick {
|
|
27
60
|
tick: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signals-protocol/v1-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Signals v1 SDK for CLMSR market calculations and utilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"test:watch": "jest --watch",
|
|
14
14
|
"npm:auth": "node scripts/write-npmrc.js",
|
|
15
15
|
"publish:package": "NPM_CONFIG_USERCONFIG=.npmrc.auth npm publish",
|
|
16
|
+
"prepack": "yarn rebuild",
|
|
16
17
|
"lint": "eslint src/**/*.ts",
|
|
17
18
|
"format": "prettier --write src/**/*.ts",
|
|
18
19
|
"clean": "rm -rf dist",
|