@n1xyz/wallet-widget 0.0.22 → 0.0.24

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.
Files changed (39) hide show
  1. package/dist/Modal/NordFlow/context/DepositContext.js +1 -1
  2. package/dist/Modal/NordFlow/context/DepositContext.js.map +1 -1
  3. package/dist/Modal/NordFlow/context/WalletConnectContext.js +4 -3
  4. package/dist/Modal/NordFlow/context/WalletConnectContext.js.map +1 -1
  5. package/dist/Modal/NordFlow/screens/04-AmountInputScreen.js +19 -14
  6. package/dist/Modal/NordFlow/screens/04-AmountInputScreen.js.map +1 -1
  7. package/dist/Modal/Sidebar/N1Sidebar.js +6 -2
  8. package/dist/Modal/Sidebar/N1Sidebar.js.map +1 -1
  9. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketOverview.d.ts +7 -2
  10. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketOverview.js +11 -8
  11. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketOverview.js.map +1 -1
  12. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketSelector.d.ts +2 -2
  13. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketSelector.js +3 -3
  14. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketSelector.js.map +1 -1
  15. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketStats.d.ts +4 -0
  16. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketStats.js +4 -0
  17. package/dist/Modal/Sidebar/NordTradingView/MarketOverview/MarketStats.js.map +1 -1
  18. package/dist/Modal/Sidebar/NordTradingView/NordTradingView.d.ts +1 -1
  19. package/dist/Modal/Sidebar/NordTradingView/NordTradingView.js +129 -41
  20. package/dist/Modal/Sidebar/NordTradingView/NordTradingView.js.map +1 -1
  21. package/dist/Modal/Sidebar/NordTradingView/OrderBook/OrderBook.d.ts +0 -5
  22. package/dist/Modal/Sidebar/NordTradingView/OrderBook/OrderBook.js +234 -195
  23. package/dist/Modal/Sidebar/NordTradingView/OrderBook/OrderBook.js.map +1 -1
  24. package/dist/Modal/Sidebar/NordTradingView/TradeForm/TradeForm.d.ts +6 -1
  25. package/dist/Modal/Sidebar/NordTradingView/TradeForm/TradeForm.js +11 -7
  26. package/dist/Modal/Sidebar/NordTradingView/TradeForm/TradeForm.js.map +1 -1
  27. package/dist/Modal/Sidebar/NordTradingView/UserBalances/UserBalances.d.ts +4 -0
  28. package/dist/Modal/Sidebar/NordTradingView/UserBalances/UserBalances.js +4 -0
  29. package/dist/Modal/Sidebar/NordTradingView/UserBalances/UserBalances.js.map +1 -1
  30. package/dist/Modal/Sidebar/NordTradingView/UserPositions/UserPositions.d.ts +0 -1
  31. package/dist/Modal/Sidebar/NordTradingView/UserPositions/UserPositions.js +271 -189
  32. package/dist/Modal/Sidebar/NordTradingView/UserPositions/UserPositions.js.map +1 -1
  33. package/dist/Provider/hooks/useNordUserInitialization.js +7 -4
  34. package/dist/Provider/hooks/useNordUserInitialization.js.map +1 -1
  35. package/dist/embedded-main-css.d.ts +1 -1
  36. package/dist/embedded-main-css.js +1 -1
  37. package/dist/embedded-main-css.js.map +1 -1
  38. package/dist/main.css +1 -1
  39. package/package.json +12 -13
@@ -1,196 +1,278 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
- function verb(n) { return function (v) { return step([n, v]); }; }
14
- function step(op) {
15
- if (f) throw new TypeError("Generator is already executing.");
16
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
- if (y = 0, t) op = [op[0] & 2, t.value];
19
- switch (op[0]) {
20
- case 0: case 1: t = op; break;
21
- case 4: _.label++; return { value: op[1], done: false };
22
- case 5: _.label++; y = op[1]; op = [0]; continue;
23
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
- default:
25
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
- if (t[2]) _.ops.pop();
30
- _.trys.pop(); continue;
31
- }
32
- op = body.call(thisArg, _);
33
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
- }
36
- };
37
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ "use strict";
2
+ // DEPRECATED: This entire component has been deprecated due to errors
3
+ // All code below has been commented out to prevent issues
4
+ /*
5
+
38
6
  import { useState, useEffect } from 'react';
39
7
  import { useN1WalletContext } from '../../../../Provider/hooks';
40
- import { RefreshCw } from 'lucide-react';
8
+ import { RefreshCw, X } from 'lucide-react';
9
+
10
+ interface Position {
11
+ marketId: number;
12
+ symbol: string;
13
+ size: number;
14
+ entryPrice: number;
15
+ markPrice: number;
16
+ pnl: number;
17
+ pnlPercentage: number;
18
+ liquidationPrice?: number;
19
+ accountId: number;
20
+ }
21
+
22
+ // Interface for market stats based on the Nord API
23
+ interface MarketStats {
24
+ market_id: number;
25
+ index_price: [number, number];
26
+ volume_24h: number;
27
+ high_24h: number;
28
+ low_24h: number;
29
+ perp_stats?: {
30
+ mark_price?: number;
31
+ funding_rate?: number;
32
+ next_funding_time?: Date;
33
+ open_interest?: number;
34
+ };
35
+ }
36
+
41
37
  export default function UserPositions() {
42
- var _this = this;
43
- var _a = useN1WalletContext(), nord = _a.nord, nordUser = _a.nordUser;
44
- var _b = useState([]), positions = _b[0], setPositions = _b[1];
45
- var _c = useState(false), loading = _c[0], setLoading = _c[1];
46
- var _d = useState(null), error = _d[0], setError = _d[1];
47
- var _e = useState([]), marketStats = _e[0], setMarketStats = _e[1];
48
- // Fetch user positions
49
- useEffect(function () {
50
- if (!nordUser || !nord)
51
- return;
52
- var fetchPositions = function () { return __awaiter(_this, void 0, void 0, function () {
53
- var stats, statsErr_1, realPositions, _i, _a, accountId, accountPositions, _loop_1, _b, accountPositions_1, position, err_1;
54
- var _c;
55
- return __generator(this, function (_d) {
56
- switch (_d.label) {
57
- case 0:
58
- setLoading(true);
59
- setError(null);
60
- _d.label = 1;
61
- case 1:
62
- _d.trys.push([1, 7, , 8]);
63
- // Refresh user info to get latest positions
64
- return [4 /*yield*/, nordUser.fetchInfo()];
65
- case 2:
66
- // Refresh user info to get latest positions
67
- _d.sent();
68
- _d.label = 3;
69
- case 3:
70
- _d.trys.push([3, 5, , 6]);
71
- return [4 /*yield*/, nord.marketsStats()];
72
- case 4:
73
- stats = _d.sent();
74
- setMarketStats(stats.markets);
75
- return [3 /*break*/, 6];
76
- case 5:
77
- statsErr_1 = _d.sent();
78
- console.error('Error fetching market stats:', statsErr_1);
79
- return [3 /*break*/, 6];
80
- case 6:
81
- realPositions = [];
82
- // Loop through all accounts
83
- if (nordUser.accountIds) {
84
- for (_i = 0, _a = nordUser.accountIds; _i < _a.length; _i++) {
85
- accountId = _a[_i];
86
- accountPositions = nordUser.positions[accountId];
87
- if (accountPositions && accountPositions.length > 0) {
88
- _loop_1 = function (position) {
89
- // Only include positions with perp data and non-zero size
90
- if (position.perp && Math.abs(position.perp.baseSize) > 0) {
91
- // Find market info to get symbol
92
- var market = nord.markets.find(function (m) { return m.marketId === position.marketId; });
93
- var symbol = market
94
- ? market.symbol
95
- : "Market-".concat(position.marketId);
96
- // Calculate PnL
97
- var totalPnl = position.perp.sizePricePnl +
98
- position.perp.fundingPaymentPnl;
99
- var entryValue = Math.abs(position.perp.baseSize) * position.perp.price;
100
- var pnlPercentage = entryValue > 0 ? (totalPnl / entryValue) * 100 : 0;
101
- // Get mark price from market stats or use entry price as fallback
102
- var stats = marketStats.find(function (m) { return m.market_id === position.marketId; });
103
- var markPrice = ((_c = stats === null || stats === void 0 ? void 0 : stats.perp_stats) === null || _c === void 0 ? void 0 : _c.mark_price) || position.perp.price;
104
- realPositions.push({
105
- marketId: position.marketId,
106
- symbol: symbol,
107
- size: position.perp.isLong
108
- ? position.perp.baseSize
109
- : -position.perp.baseSize,
110
- entryPrice: position.perp.price,
111
- markPrice: markPrice,
112
- pnl: totalPnl,
113
- pnlPercentage: pnlPercentage,
114
- accountId: accountId,
115
- });
116
- }
117
- };
118
- // Process each position
119
- for (_b = 0, accountPositions_1 = accountPositions; _b < accountPositions_1.length; _b++) {
120
- position = accountPositions_1[_b];
121
- _loop_1(position);
122
- }
123
- }
124
- }
125
- }
126
- setPositions(realPositions);
127
- setLoading(false); // Explicitly set loading to false on success
128
- return [3 /*break*/, 8];
129
- case 7:
130
- err_1 = _d.sent();
131
- console.error('Error fetching positions:', err_1);
132
- setError('Failed to load positions');
133
- setLoading(false); // Ensure loading is set to false on error
134
- return [3 /*break*/, 8];
135
- case 8: return [2 /*return*/];
38
+ const { nord, nordUser } = useN1WalletContext();
39
+ const [positions, setPositions] = useState<Position[]>([]);
40
+ const [loading, setLoading] = useState(false);
41
+ const [error, setError] = useState<string | null>(null);
42
+ const [marketStats, setMarketStats] = useState<MarketStats[]>([]);
43
+
44
+ // Fetch user positions
45
+ useEffect(() => {
46
+ if (!nordUser || !nord) return;
47
+
48
+ const fetchPositions = async () => {
49
+ setLoading(true);
50
+ setError(null);
51
+
52
+ try {
53
+ // Refresh user info to get latest positions
54
+ await nordUser.fetchInfo();
55
+
56
+ // Get market stats for mark prices
57
+ try {
58
+ const stats = await nord.marketsStats();
59
+ setMarketStats(stats.markets);
60
+ } catch (statsErr) {
61
+ console.error('Error fetching market stats:', statsErr);
62
+ // Don't set loading to false here, as we still want to try to get positions
63
+ }
64
+
65
+ // Extract real positions from nordUser
66
+ const realPositions: Position[] = [];
67
+
68
+ // Loop through all accounts
69
+ if (nordUser.accountIds) {
70
+ for (const accountId of nordUser.accountIds) {
71
+ // Check if this account has positions
72
+ const accountPositions = nordUser.positions[accountId];
73
+
74
+ if (accountPositions && accountPositions.length > 0) {
75
+ // Process each position
76
+ for (const position of accountPositions) {
77
+ // Only include positions with perp data and non-zero size
78
+ if (position.perp && Math.abs(position.perp.baseSize) > 0) {
79
+ // Find market info to get symbol
80
+ const market = nord.markets.find(
81
+ (m) => m.marketId === position.marketId
82
+ );
83
+ const symbol = market
84
+ ? market.symbol
85
+ : `Market-${position.marketId}`;
86
+
87
+ // Calculate PnL
88
+ const totalPnl =
89
+ position.perp.sizePricePnl +
90
+ position.perp.fundingPaymentPnl;
91
+ const entryValue =
92
+ Math.abs(position.perp.baseSize) * position.perp.price;
93
+ const pnlPercentage =
94
+ entryValue > 0 ? (totalPnl / entryValue) * 100 : 0;
95
+
96
+ // Get mark price from market stats or use entry price as fallback
97
+ const stats = marketStats.find(
98
+ (m) => m.market_id === position.marketId
99
+ );
100
+ const markPrice =
101
+ stats?.perp_stats?.mark_price || position.perp.price;
102
+
103
+ realPositions.push({
104
+ marketId: position.marketId,
105
+ symbol: symbol,
106
+ size: position.perp.isLong
107
+ ? position.perp.baseSize
108
+ : -position.perp.baseSize,
109
+ entryPrice: position.perp.price,
110
+ markPrice: markPrice,
111
+ pnl: totalPnl,
112
+ pnlPercentage: pnlPercentage,
113
+ accountId: accountId,
114
+ });
136
115
  }
137
- });
138
- }); };
139
- fetchPositions();
140
- // Set up polling for position updates
141
- var intervalId = setInterval(fetchPositions, 10000); // Update every 10 seconds
142
- return function () { return clearInterval(intervalId); };
143
- }, [nordUser, nord]); // Remove marketStats from dependency array to prevent infinite loops
144
- // Handle position close
145
- var handleClosePosition = function (marketId, accountId) { return __awaiter(_this, void 0, void 0, function () {
146
- var position, err_2;
147
- return __generator(this, function (_a) {
148
- switch (_a.label) {
149
- case 0:
150
- if (!nordUser)
151
- return [2 /*return*/];
152
- _a.label = 1;
153
- case 1:
154
- _a.trys.push([1, 4, , 5]);
155
- position = positions.find(function (pos) { return pos.marketId === marketId && pos.accountId === accountId; });
156
- if (!position) {
157
- throw new Error('Position not found');
158
- }
159
- // Place an order to close the position (opposite side, same size)
160
- return [4 /*yield*/, nordUser.placeOrder({
161
- marketId: marketId,
162
- side: position.size > 0 ? 'ask' : 'bid', // Opposite side to close
163
- fillMode: 'market', // Market order to ensure it gets filled
164
- isReduceOnly: true, // Reduce-only to ensure it only closes the position
165
- size: Math.abs(position.size), // Absolute size value
166
- accountId: accountId,
167
- })];
168
- case 2:
169
- // Place an order to close the position (opposite side, same size)
170
- _a.sent();
171
- // Refresh positions after closing
172
- return [4 /*yield*/, nordUser.fetchInfo()];
173
- case 3:
174
- // Refresh positions after closing
175
- _a.sent();
176
- // Remove the position from the local state
177
- setPositions(positions.filter(function (pos) { return !(pos.marketId === marketId && pos.accountId === accountId); }));
178
- return [3 /*break*/, 5];
179
- case 4:
180
- err_2 = _a.sent();
181
- console.error('Error closing position:', err_2);
182
- setError('Failed to close position');
183
- return [3 /*break*/, 5];
184
- case 5: return [2 /*return*/];
116
+ }
185
117
  }
186
- });
187
- }); };
188
- return (_jsx("div", { className: "bg-white dark:bg-n1-ww-gray-950 overflow-hidden", children: _jsxs("div", { className: "p-4", children: [_jsx("h2", { className: "text-lg font-semibold text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mb-4", children: "Positions" }), loading && positions.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsx(RefreshCw, { size: 20, className: "text-n1-ww-gray-400 n1-ww-animate-spin" }) })) : error ? (_jsx("div", { className: "p-3 bg-red-50 dark:bg-red-900/20 rounded-lg text-red-600 dark:text-red-400 text-sm", children: error })) : positions.length === 0 ? (_jsx("div", { className: "p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg text-n1-ww-gray-500 dark:text-n1-ww-gray-400 text-sm text-center", children: "No open positions" })) : (_jsxs("div", { className: "space-y-3", children: [positions.map(function (position, index) { return (_jsxs("div", { className: "p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg", children: [_jsx("div", { className: "flex items-center justify-between mb-2", children: _jsxs("div", { className: "flex items-center", children: [_jsx("span", { className: "font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mr-2", children: position.symbol }), _jsxs("span", { className: "text-xs px-2 py-0.5 rounded ".concat(position.size > 0
189
- ? 'bg-green-100 dark:bg-green-900/20 text-green-600 dark:text-green-400'
190
- : 'bg-red-100 dark:bg-red-900/20 text-red-600 dark:text-red-400'), children: [position.size > 0 ? 'Long' : 'Short', ' ', Math.abs(position.size)] })] }) }), _jsxs("div", { className: "grid grid-cols-2 gap-2 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "text-n1-ww-gray-500 dark:text-n1-ww-gray-400", children: "Entry Price" }), _jsx("div", { className: "font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono", children: position.entryPrice.toFixed(2) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-n1-ww-gray-500 dark:text-n1-ww-gray-400", children: "Mark Price" }), _jsx("div", { className: "font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono", children: position.markPrice.toFixed(2) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-n1-ww-gray-500 dark:text-n1-ww-gray-400", children: "PnL" }), _jsxs("div", { className: "font-medium font-mono ".concat(position.pnl >= 0
191
- ? 'text-green-600 dark:text-green-400'
192
- : 'text-red-600 dark:text-red-400'), children: [position.pnl >= 0 ? '+' : '', position.pnl.toFixed(2), " (", position.pnlPercentage.toFixed(2), "%)"] })] }), _jsxs("div", { children: [_jsx("div", { className: "text-n1-ww-gray-500 dark:text-n1-ww-gray-400", children: "Liquidation" }), _jsx("div", { className: "font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono", children: position.liquidationPrice
193
- ? position.liquidationPrice.toFixed(2)
194
- : 'N/A' })] })] })] }, index)); }), loading && positions.length > 0 && (_jsx("div", { className: "flex justify-center mt-2", children: _jsx(RefreshCw, { size: 16, className: "text-n1-ww-gray-400 n1-ww-animate-spin" }) }))] }))] }) }));
118
+ }
119
+ }
120
+
121
+ setPositions(realPositions);
122
+ setLoading(false); // Explicitly set loading to false on success
123
+ } catch (err) {
124
+ console.error('Error fetching positions:', err);
125
+ setError('Failed to load positions');
126
+ setLoading(false); // Ensure loading is set to false on error
127
+ }
128
+ };
129
+
130
+ fetchPositions();
131
+
132
+ // Set up polling for position updates
133
+ const intervalId = setInterval(fetchPositions, 10000); // Update every 10 seconds
134
+
135
+ return () => clearInterval(intervalId);
136
+ }, [nordUser, nord]); // Remove marketStats from dependency array to prevent infinite loops
137
+
138
+ // Handle position close
139
+ const handleClosePosition = async (marketId: number, accountId: number) => {
140
+ if (!nordUser) return;
141
+
142
+ try {
143
+ // Find the position to close
144
+ const position = positions.find(
145
+ (pos) => pos.marketId === marketId && pos.accountId === accountId
146
+ );
147
+
148
+ if (!position) {
149
+ throw new Error('Position not found');
150
+ }
151
+
152
+ // Place an order to close the position (opposite side, same size)
153
+ await nordUser.placeOrder({
154
+ marketId: marketId,
155
+ side: position.size > 0 ? 'ask' : 'bid', // Opposite side to close
156
+ fillMode: 'market', // Market order to ensure it gets filled
157
+ isReduceOnly: true, // Reduce-only to ensure it only closes the position
158
+ size: Math.abs(position.size), // Absolute size value
159
+ accountId: accountId,
160
+ });
161
+
162
+ // Refresh positions after closing
163
+ await nordUser.fetchInfo();
164
+
165
+ // Remove the position from the local state
166
+ setPositions(
167
+ positions.filter(
168
+ (pos) => !(pos.marketId === marketId && pos.accountId === accountId)
169
+ )
170
+ );
171
+ } catch (err) {
172
+ console.error('Error closing position:', err);
173
+ setError('Failed to close position');
174
+ }
175
+ };
176
+
177
+ return (
178
+ <div className="bg-white dark:bg-n1-ww-gray-950 overflow-hidden">
179
+ <div className="p-4">
180
+ <h2 className="text-lg font-semibold text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mb-4">
181
+ Positions
182
+ </h2>
183
+
184
+ {loading && positions.length === 0 ? (
185
+ <div className="flex items-center justify-center h-32">
186
+ <RefreshCw size={20} className="text-n1-ww-gray-400 n1-ww-animate-spin" />
187
+ </div>
188
+ ) : error ? (
189
+ <div className="p-3 bg-red-50 dark:bg-red-900/20 rounded-lg text-red-600 dark:text-red-400 text-sm">
190
+ {error}
191
+ </div>
192
+ ) : positions.length === 0 ? (
193
+ <div className="p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg text-n1-ww-gray-500 dark:text-n1-ww-gray-400 text-sm text-center">
194
+ No open positions
195
+ </div>
196
+ ) : (
197
+ <div className="space-y-3">
198
+ {positions.map((position, index) => (
199
+ <div
200
+ key={index}
201
+ className="p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg"
202
+ >
203
+ <div className="flex items-center justify-between mb-2">
204
+ <div className="flex items-center">
205
+ <span className="font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mr-2">
206
+ {position.symbol}
207
+ </span>
208
+ <span
209
+ className={`text-xs px-2 py-0.5 rounded ${
210
+ position.size > 0
211
+ ? 'bg-green-100 dark:bg-green-900/20 text-green-600 dark:text-green-400'
212
+ : 'bg-red-100 dark:bg-red-900/20 text-red-600 dark:text-red-400'
213
+ }`}
214
+ >
215
+ {position.size > 0 ? 'Long' : 'Short'}{' '}
216
+ {Math.abs(position.size)}
217
+ </span>
218
+ </div>
219
+ </div>
220
+
221
+ <div className="grid grid-cols-2 gap-2 text-sm">
222
+ <div>
223
+ <div className="text-n1-ww-gray-500 dark:text-n1-ww-gray-400">
224
+ Entry Price
225
+ </div>
226
+ <div className="font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono">
227
+ {position.entryPrice.toFixed(2)}
228
+ </div>
229
+ </div>
230
+ <div>
231
+ <div className="text-n1-ww-gray-500 dark:text-n1-ww-gray-400">
232
+ Mark Price
233
+ </div>
234
+ <div className="font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono">
235
+ {position.markPrice.toFixed(2)}
236
+ </div>
237
+ </div>
238
+ <div>
239
+ <div className="text-n1-ww-gray-500 dark:text-n1-ww-gray-400">PnL</div>
240
+ <div
241
+ className={`font-medium font-mono ${
242
+ position.pnl >= 0
243
+ ? 'text-green-600 dark:text-green-400'
244
+ : 'text-red-600 dark:text-red-400'
245
+ }`}
246
+ >
247
+ {position.pnl >= 0 ? '+' : ''}
248
+ {position.pnl.toFixed(2)} (
249
+ {position.pnlPercentage.toFixed(2)}%)
250
+ </div>
251
+ </div>
252
+ <div>
253
+ <div className="text-n1-ww-gray-500 dark:text-n1-ww-gray-400">
254
+ Liquidation
255
+ </div>
256
+ <div className="font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono">
257
+ {position.liquidationPrice
258
+ ? position.liquidationPrice.toFixed(2)
259
+ : 'N/A'}
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ ))}
265
+
266
+ {loading && positions.length > 0 && (
267
+ <div className="flex justify-center mt-2">
268
+ <RefreshCw size={16} className="text-n1-ww-gray-400 n1-ww-animate-spin" />
269
+ </div>
270
+ )}
271
+ </div>
272
+ )}
273
+ </div>
274
+ </div>
275
+ );
195
276
  }
277
+ */
196
278
  //# sourceMappingURL=UserPositions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserPositions.js","sourceRoot":"","sources":["../../../../../src/Modal/Sidebar/NordTradingView/UserPositions/UserPositions.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, useEffect } from 'react';\nimport { useN1WalletContext } from '../../../../Provider/hooks';\nimport { RefreshCw, X } from 'lucide-react';\n\ninterface Position {\n marketId: number;\n symbol: string;\n size: number;\n entryPrice: number;\n markPrice: number;\n pnl: number;\n pnlPercentage: number;\n liquidationPrice?: number;\n accountId: number;\n}\n\n// Interface for market stats based on the Nord API\ninterface MarketStats {\n market_id: number;\n index_price: [number, number];\n volume_24h: number;\n high_24h: number;\n low_24h: number;\n perp_stats?: {\n mark_price?: number;\n funding_rate?: number;\n next_funding_time?: Date;\n open_interest?: number;\n };\n}\n\nexport default function UserPositions() {\n const { nord, nordUser } = useN1WalletContext();\n const [positions, setPositions] = useState<Position[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [marketStats, setMarketStats] = useState<MarketStats[]>([]);\n\n // Fetch user positions\n useEffect(() => {\n if (!nordUser || !nord) return;\n\n const fetchPositions = async () => {\n setLoading(true);\n setError(null);\n\n try {\n // Refresh user info to get latest positions\n await nordUser.fetchInfo();\n\n // Get market stats for mark prices\n try {\n const stats = await nord.marketsStats();\n setMarketStats(stats.markets);\n } catch (statsErr) {\n console.error('Error fetching market stats:', statsErr);\n // Don't set loading to false here, as we still want to try to get positions\n }\n\n // Extract real positions from nordUser\n const realPositions: Position[] = [];\n\n // Loop through all accounts\n if (nordUser.accountIds) {\n for (const accountId of nordUser.accountIds) {\n // Check if this account has positions\n const accountPositions = nordUser.positions[accountId];\n\n if (accountPositions && accountPositions.length > 0) {\n // Process each position\n for (const position of accountPositions) {\n // Only include positions with perp data and non-zero size\n if (position.perp && Math.abs(position.perp.baseSize) > 0) {\n // Find market info to get symbol\n const market = nord.markets.find(\n (m) => m.marketId === position.marketId\n );\n const symbol = market\n ? market.symbol\n : `Market-${position.marketId}`;\n\n // Calculate PnL\n const totalPnl =\n position.perp.sizePricePnl +\n position.perp.fundingPaymentPnl;\n const entryValue =\n Math.abs(position.perp.baseSize) * position.perp.price;\n const pnlPercentage =\n entryValue > 0 ? (totalPnl / entryValue) * 100 : 0;\n\n // Get mark price from market stats or use entry price as fallback\n const stats = marketStats.find(\n (m) => m.market_id === position.marketId\n );\n const markPrice =\n stats?.perp_stats?.mark_price || position.perp.price;\n\n realPositions.push({\n marketId: position.marketId,\n symbol: symbol,\n size: position.perp.isLong\n ? position.perp.baseSize\n : -position.perp.baseSize,\n entryPrice: position.perp.price,\n markPrice: markPrice,\n pnl: totalPnl,\n pnlPercentage: pnlPercentage,\n accountId: accountId,\n });\n }\n }\n }\n }\n }\n\n setPositions(realPositions);\n setLoading(false); // Explicitly set loading to false on success\n } catch (err) {\n console.error('Error fetching positions:', err);\n setError('Failed to load positions');\n setLoading(false); // Ensure loading is set to false on error\n }\n };\n\n fetchPositions();\n\n // Set up polling for position updates\n const intervalId = setInterval(fetchPositions, 10000); // Update every 10 seconds\n\n return () => clearInterval(intervalId);\n }, [nordUser, nord]); // Remove marketStats from dependency array to prevent infinite loops\n\n // Handle position close\n const handleClosePosition = async (marketId: number, accountId: number) => {\n if (!nordUser) return;\n\n try {\n // Find the position to close\n const position = positions.find(\n (pos) => pos.marketId === marketId && pos.accountId === accountId\n );\n\n if (!position) {\n throw new Error('Position not found');\n }\n\n // Place an order to close the position (opposite side, same size)\n await nordUser.placeOrder({\n marketId: marketId,\n side: position.size > 0 ? 'ask' : 'bid', // Opposite side to close\n fillMode: 'market', // Market order to ensure it gets filled\n isReduceOnly: true, // Reduce-only to ensure it only closes the position\n size: Math.abs(position.size), // Absolute size value\n accountId: accountId,\n });\n\n // Refresh positions after closing\n await nordUser.fetchInfo();\n\n // Remove the position from the local state\n setPositions(\n positions.filter(\n (pos) => !(pos.marketId === marketId && pos.accountId === accountId)\n )\n );\n } catch (err) {\n console.error('Error closing position:', err);\n setError('Failed to close position');\n }\n };\n\n return (\n <div className=\"bg-white dark:bg-n1-ww-gray-950 overflow-hidden\">\n <div className=\"p-4\">\n <h2 className=\"text-lg font-semibold text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mb-4\">\n Positions\n </h2>\n\n {loading && positions.length === 0 ? (\n <div className=\"flex items-center justify-center h-32\">\n <RefreshCw size={20} className=\"text-n1-ww-gray-400 n1-ww-animate-spin\" />\n </div>\n ) : error ? (\n <div className=\"p-3 bg-red-50 dark:bg-red-900/20 rounded-lg text-red-600 dark:text-red-400 text-sm\">\n {error}\n </div>\n ) : positions.length === 0 ? (\n <div className=\"p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg text-n1-ww-gray-500 dark:text-n1-ww-gray-400 text-sm text-center\">\n No open positions\n </div>\n ) : (\n <div className=\"space-y-3\">\n {positions.map((position, index) => (\n <div\n key={index}\n className=\"p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg\"\n >\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center\">\n <span className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mr-2\">\n {position.symbol}\n </span>\n <span\n className={`text-xs px-2 py-0.5 rounded ${\n position.size > 0\n ? 'bg-green-100 dark:bg-green-900/20 text-green-600 dark:text-green-400'\n : 'bg-red-100 dark:bg-red-900/20 text-red-600 dark:text-red-400'\n }`}\n >\n {position.size > 0 ? 'Long' : 'Short'}{' '}\n {Math.abs(position.size)}\n </span>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">\n Entry Price\n </div>\n <div className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono\">\n {position.entryPrice.toFixed(2)}\n </div>\n </div>\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">\n Mark Price\n </div>\n <div className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono\">\n {position.markPrice.toFixed(2)}\n </div>\n </div>\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">PnL</div>\n <div\n className={`font-medium font-mono ${\n position.pnl >= 0\n ? 'text-green-600 dark:text-green-400'\n : 'text-red-600 dark:text-red-400'\n }`}\n >\n {position.pnl >= 0 ? '+' : ''}\n {position.pnl.toFixed(2)} (\n {position.pnlPercentage.toFixed(2)}%)\n </div>\n </div>\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">\n Liquidation\n </div>\n <div className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono\">\n {position.liquidationPrice\n ? position.liquidationPrice.toFixed(2)\n : 'N/A'}\n </div>\n </div>\n </div>\n </div>\n ))}\n\n {/* Loading indicator for refreshing */}\n {loading && positions.length > 0 && (\n <div className=\"flex justify-center mt-2\">\n <RefreshCw size={16} className=\"text-n1-ww-gray-400 n1-ww-animate-spin\" />\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"UserPositions.js","sourceRoot":"","sources":["../../../../../src/Modal/Sidebar/NordTradingView/UserPositions/UserPositions.tsx"],"names":[],"mappings":";AAAA,sEAAsE;AACtE,0DAA0D;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiRE","sourcesContent":["// DEPRECATED: This entire component has been deprecated due to errors\n// All code below has been commented out to prevent issues\n\n/*\n\nimport { useState, useEffect } from 'react';\nimport { useN1WalletContext } from '../../../../Provider/hooks';\nimport { RefreshCw, X } from 'lucide-react';\n\ninterface Position {\n marketId: number;\n symbol: string;\n size: number;\n entryPrice: number;\n markPrice: number;\n pnl: number;\n pnlPercentage: number;\n liquidationPrice?: number;\n accountId: number;\n}\n\n// Interface for market stats based on the Nord API\ninterface MarketStats {\n market_id: number;\n index_price: [number, number];\n volume_24h: number;\n high_24h: number;\n low_24h: number;\n perp_stats?: {\n mark_price?: number;\n funding_rate?: number;\n next_funding_time?: Date;\n open_interest?: number;\n };\n}\n\nexport default function UserPositions() {\n const { nord, nordUser } = useN1WalletContext();\n const [positions, setPositions] = useState<Position[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [marketStats, setMarketStats] = useState<MarketStats[]>([]);\n\n // Fetch user positions\n useEffect(() => {\n if (!nordUser || !nord) return;\n\n const fetchPositions = async () => {\n setLoading(true);\n setError(null);\n\n try {\n // Refresh user info to get latest positions\n await nordUser.fetchInfo();\n\n // Get market stats for mark prices\n try {\n const stats = await nord.marketsStats();\n setMarketStats(stats.markets);\n } catch (statsErr) {\n console.error('Error fetching market stats:', statsErr);\n // Don't set loading to false here, as we still want to try to get positions\n }\n\n // Extract real positions from nordUser\n const realPositions: Position[] = [];\n\n // Loop through all accounts\n if (nordUser.accountIds) {\n for (const accountId of nordUser.accountIds) {\n // Check if this account has positions\n const accountPositions = nordUser.positions[accountId];\n\n if (accountPositions && accountPositions.length > 0) {\n // Process each position\n for (const position of accountPositions) {\n // Only include positions with perp data and non-zero size\n if (position.perp && Math.abs(position.perp.baseSize) > 0) {\n // Find market info to get symbol\n const market = nord.markets.find(\n (m) => m.marketId === position.marketId\n );\n const symbol = market\n ? market.symbol\n : `Market-${position.marketId}`;\n\n // Calculate PnL\n const totalPnl =\n position.perp.sizePricePnl +\n position.perp.fundingPaymentPnl;\n const entryValue =\n Math.abs(position.perp.baseSize) * position.perp.price;\n const pnlPercentage =\n entryValue > 0 ? (totalPnl / entryValue) * 100 : 0;\n\n // Get mark price from market stats or use entry price as fallback\n const stats = marketStats.find(\n (m) => m.market_id === position.marketId\n );\n const markPrice =\n stats?.perp_stats?.mark_price || position.perp.price;\n\n realPositions.push({\n marketId: position.marketId,\n symbol: symbol,\n size: position.perp.isLong\n ? position.perp.baseSize\n : -position.perp.baseSize,\n entryPrice: position.perp.price,\n markPrice: markPrice,\n pnl: totalPnl,\n pnlPercentage: pnlPercentage,\n accountId: accountId,\n });\n }\n }\n }\n }\n }\n\n setPositions(realPositions);\n setLoading(false); // Explicitly set loading to false on success\n } catch (err) {\n console.error('Error fetching positions:', err);\n setError('Failed to load positions');\n setLoading(false); // Ensure loading is set to false on error\n }\n };\n\n fetchPositions();\n\n // Set up polling for position updates\n const intervalId = setInterval(fetchPositions, 10000); // Update every 10 seconds\n\n return () => clearInterval(intervalId);\n }, [nordUser, nord]); // Remove marketStats from dependency array to prevent infinite loops\n\n // Handle position close\n const handleClosePosition = async (marketId: number, accountId: number) => {\n if (!nordUser) return;\n\n try {\n // Find the position to close\n const position = positions.find(\n (pos) => pos.marketId === marketId && pos.accountId === accountId\n );\n\n if (!position) {\n throw new Error('Position not found');\n }\n\n // Place an order to close the position (opposite side, same size)\n await nordUser.placeOrder({\n marketId: marketId,\n side: position.size > 0 ? 'ask' : 'bid', // Opposite side to close\n fillMode: 'market', // Market order to ensure it gets filled\n isReduceOnly: true, // Reduce-only to ensure it only closes the position\n size: Math.abs(position.size), // Absolute size value\n accountId: accountId,\n });\n\n // Refresh positions after closing\n await nordUser.fetchInfo();\n\n // Remove the position from the local state\n setPositions(\n positions.filter(\n (pos) => !(pos.marketId === marketId && pos.accountId === accountId)\n )\n );\n } catch (err) {\n console.error('Error closing position:', err);\n setError('Failed to close position');\n }\n };\n\n return (\n <div className=\"bg-white dark:bg-n1-ww-gray-950 overflow-hidden\">\n <div className=\"p-4\">\n <h2 className=\"text-lg font-semibold text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mb-4\">\n Positions\n </h2>\n\n {loading && positions.length === 0 ? (\n <div className=\"flex items-center justify-center h-32\">\n <RefreshCw size={20} className=\"text-n1-ww-gray-400 n1-ww-animate-spin\" />\n </div>\n ) : error ? (\n <div className=\"p-3 bg-red-50 dark:bg-red-900/20 rounded-lg text-red-600 dark:text-red-400 text-sm\">\n {error}\n </div>\n ) : positions.length === 0 ? (\n <div className=\"p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg text-n1-ww-gray-500 dark:text-n1-ww-gray-400 text-sm text-center\">\n No open positions\n </div>\n ) : (\n <div className=\"space-y-3\">\n {positions.map((position, index) => (\n <div\n key={index}\n className=\"p-3 bg-n1-ww-gray-50 dark:bg-n1-ww-gray-950 rounded-lg\"\n >\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center\">\n <span className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 mr-2\">\n {position.symbol}\n </span>\n <span\n className={`text-xs px-2 py-0.5 rounded ${\n position.size > 0\n ? 'bg-green-100 dark:bg-green-900/20 text-green-600 dark:text-green-400'\n : 'bg-red-100 dark:bg-red-900/20 text-red-600 dark:text-red-400'\n }`}\n >\n {position.size > 0 ? 'Long' : 'Short'}{' '}\n {Math.abs(position.size)}\n </span>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">\n Entry Price\n </div>\n <div className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono\">\n {position.entryPrice.toFixed(2)}\n </div>\n </div>\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">\n Mark Price\n </div>\n <div className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono\">\n {position.markPrice.toFixed(2)}\n </div>\n </div>\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">PnL</div>\n <div\n className={`font-medium font-mono ${\n position.pnl >= 0\n ? 'text-green-600 dark:text-green-400'\n : 'text-red-600 dark:text-red-400'\n }`}\n >\n {position.pnl >= 0 ? '+' : ''}\n {position.pnl.toFixed(2)} (\n {position.pnlPercentage.toFixed(2)}%)\n </div>\n </div>\n <div>\n <div className=\"text-n1-ww-gray-500 dark:text-n1-ww-gray-400\">\n Liquidation\n </div>\n <div className=\"font-medium text-n1-ww-gray-900 dark:text-n1-ww-gray-100 font-mono\">\n {position.liquidationPrice\n ? position.liquidationPrice.toFixed(2)\n : 'N/A'}\n </div>\n </div>\n </div>\n </div>\n ))}\n\n {loading && positions.length > 0 && (\n <div className=\"flex justify-center mt-2\">\n <RefreshCw size={16} className=\"text-n1-ww-gray-400 n1-ww-animate-spin\" />\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n*/"]}
@@ -37,7 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  import { useEffect } from 'react';
38
38
  import { NordUser } from '@n1xyz/nord-ts';
39
39
  import { generateSessionKeyPair, signEd25519 } from '@n1xyz/nts-sdk';
40
- import { PublicKey, Transaction } from '@solana/web3.js';
40
+ import { PublicKey } from '@solana/web3.js';
41
41
  import { getSessionKeysFromLocalStorage, storeSessionKeysInLocalStorage } from '../../Logic/utils';
42
42
  import { WalletError, WalletErrorCode } from '../../errors/types';
43
43
  import { logger } from '../../utils/logger';
@@ -88,7 +88,7 @@ export function useNordUserInitialization() {
88
88
  return null;
89
89
  }
90
90
  var signTransactionWithWallet = function (transaction) { return __awaiter(_this, void 0, void 0, function () {
91
- var signedTransaction, serializedTx, error_2;
91
+ var signedTransaction, error_2;
92
92
  return __generator(this, function (_a) {
93
93
  switch (_a.label) {
94
94
  case 0:
@@ -99,8 +99,11 @@ export function useNordUserInitialization() {
99
99
  case 2:
100
100
  signedTransaction = _a.sent();
101
101
  logger.debug('Solana transaction signature received');
102
- serializedTx = signedTransaction.serialize();
103
- return [2 /*return*/, Transaction.from(serializedTx)];
102
+ // const serializedTx = signedTransaction.serialize();
103
+ // return Transaction.from(serializedTx);
104
+ console.log('signedTransaction', signedTransaction.signatures);
105
+ console.log('signedTransaction - 2', signedTransaction);
106
+ return [2 /*return*/, signedTransaction];
104
107
  case 3: throw new WalletError(WalletErrorCode.USER_REJECTED, 'Unsupported chain', { originalError: new Error('Unsupported chain') });
105
108
  case 4:
106
109
  error_2 = _a.sent();