@n1xyz/nord-ts 0.0.1 → 0.0.5
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/README.md +148 -65
- package/dist/bridge/client.d.ts +150 -0
- package/dist/bridge/client.js +394 -0
- package/dist/bridge/const.d.ts +23 -0
- package/dist/bridge/const.js +47 -0
- package/dist/bridge/index.d.ts +5 -0
- package/dist/bridge/index.js +23 -0
- package/dist/bridge/types.d.ts +118 -0
- package/dist/bridge/types.js +16 -0
- package/dist/bridge/utils.d.ts +64 -0
- package/dist/bridge/utils.js +131 -0
- package/dist/const.d.ts +2 -5
- package/dist/const.js +2 -6
- package/dist/gen/common.d.ts +6 -1
- package/dist/gen/common.js +19 -9
- package/dist/gen/nord.d.ts +76 -21
- package/dist/gen/nord.js +987 -423
- package/dist/idl/bridge.d.ts +2 -0
- package/dist/idl/bridge.js +703 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +18 -2
- package/dist/nord/{actions.d.ts → api/actions.d.ts} +6 -6
- package/dist/nord/{actions.js → api/actions.js} +6 -10
- package/dist/nord/api/core.d.ts +49 -0
- package/dist/nord/api/core.js +121 -0
- package/dist/nord/api/market.d.ts +36 -0
- package/dist/nord/api/market.js +98 -0
- package/dist/nord/api/metrics.d.ts +67 -0
- package/dist/nord/api/metrics.js +132 -0
- package/dist/nord/api/queries.d.ts +81 -0
- package/dist/nord/api/queries.js +187 -0
- package/dist/nord/client/Nord.d.ts +335 -0
- package/dist/nord/client/Nord.js +532 -0
- package/dist/nord/client/NordUser.d.ts +320 -0
- package/dist/nord/client/NordUser.js +697 -0
- package/dist/nord/index.d.ts +9 -2
- package/dist/nord/index.js +30 -6
- package/dist/nord/models/Subscriber.d.ts +37 -0
- package/dist/nord/models/Subscriber.js +25 -0
- package/dist/nord/utils/NordError.d.ts +35 -0
- package/dist/nord/utils/NordError.js +46 -0
- package/dist/types.d.ts +143 -86
- package/dist/types.js +12 -1
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +20 -1
- package/dist/websocket/NordWebSocketClient.d.ts +71 -0
- package/dist/websocket/NordWebSocketClient.js +343 -0
- package/dist/websocket/events.d.ts +19 -0
- package/dist/websocket/events.js +2 -0
- package/dist/websocket/index.d.ts +2 -0
- package/dist/websocket/index.js +5 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/assets/highlight.css +16 -16
- package/docs/assets/icons.js +17 -14
- package/docs/assets/icons.svg +1 -1
- package/docs/assets/main.js +5 -4
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +1423 -1227
- package/docs/classes/Nord.html +189 -43
- package/docs/classes/NordError.html +24 -0
- package/docs/classes/NordUser.html +120 -35
- package/docs/classes/NordWebSocketClient.html +335 -0
- package/docs/classes/SolanaBridgeClient.html +86 -0
- package/docs/classes/Subscriber.html +10 -6
- package/docs/enums/FillMode.html +5 -5
- package/docs/enums/KeyType.html +4 -4
- package/docs/enums/MetricPeriod.html +9 -0
- package/docs/enums/PdaSeedType.html +9 -0
- package/docs/enums/PeakTpsPeriodUnit.html +7 -7
- package/docs/enums/Side.html +3 -3
- package/docs/enums/WebSocketMessageType.html +7 -0
- package/docs/functions/actionQueryRollman.html +6 -0
- package/docs/functions/actionsQueryRollman.html +6 -0
- package/docs/functions/aggregateMetrics-1.html +7 -0
- package/docs/functions/assert.html +1 -1
- package/docs/functions/bigIntToProtoU128.html +3 -3
- package/docs/functions/blockQueryRollman.html +6 -0
- package/docs/functions/blockSummaryQueryRollman.html +6 -0
- package/docs/functions/bridgeToBN.html +5 -0
- package/docs/functions/bufferToHex.html +4 -0
- package/docs/functions/cancelOrder.html +1 -0
- package/docs/functions/checkPubKeyLength.html +1 -1
- package/docs/functions/checkedFetch.html +4 -4
- package/docs/functions/createSession.html +1 -0
- package/docs/functions/decodeLengthDelimited.html +7 -6
- package/docs/functions/encodeLengthDelimited.html +4 -4
- package/docs/functions/fillModeToProtoFillMode.html +4 -4
- package/docs/functions/findMarket.html +1 -1
- package/docs/functions/findPda.html +6 -0
- package/docs/functions/findToken.html +1 -1
- package/docs/functions/fromBN.html +5 -0
- package/docs/functions/getAccount.html +6 -0
- package/docs/functions/getActionNonce.html +5 -0
- package/docs/functions/getCurrentTps.html +6 -0
- package/docs/functions/getInfo.html +5 -0
- package/docs/functions/getMedianLatency.html +6 -0
- package/docs/functions/getOrderbook.html +6 -0
- package/docs/functions/getPeakTps.html +6 -0
- package/docs/functions/getTimestamp.html +5 -0
- package/docs/functions/getTotalTransactions.html +5 -0
- package/docs/functions/getTrades.html +6 -0
- package/docs/functions/getUserAccountIds.html +6 -0
- package/docs/functions/hexToBuffer.html +4 -0
- package/docs/functions/initWebSocketClient.html +12 -0
- package/docs/functions/keypairFromPrivateKey.html +4 -0
- package/docs/functions/makeSigningFunction.html +4 -0
- package/docs/functions/makeWalletSignFn.html +5 -5
- package/docs/functions/marketsStats.html +5 -0
- package/docs/functions/optExpect.html +4 -4
- package/docs/functions/optMap.html +5 -5
- package/docs/functions/optUnwrap.html +2 -2
- package/docs/functions/panic.html +1 -1
- package/docs/functions/placeOrder.html +1 -0
- package/docs/functions/queryAction.html +6 -0
- package/docs/functions/queryBlock.html +6 -0
- package/docs/functions/queryLastNBlocks.html +5 -0
- package/docs/functions/queryPrometheus.html +6 -0
- package/docs/functions/queryRecentActions.html +6 -0
- package/docs/functions/queryRecentBlocks.html +6 -0
- package/docs/functions/revokeSession.html +1 -0
- package/docs/functions/shortenPublicKey.html +5 -0
- package/docs/functions/signAction.html +2 -2
- package/docs/functions/toBN.html +5 -0
- package/docs/functions/toScaledU128.html +5 -5
- package/docs/functions/toScaledU64.html +5 -5
- package/docs/functions/transfer.html +1 -0
- package/docs/functions/withdraw.html +1 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +39 -20
- package/docs/interfaces/Account.html +8 -8
- package/docs/interfaces/ActionInfo.html +8 -8
- package/docs/interfaces/ActionNonceResponse.html +3 -0
- package/docs/interfaces/ActionQuery.html +4 -4
- package/docs/interfaces/ActionResponse.html +8 -8
- package/docs/interfaces/ActionsExtendedInfo.html +10 -10
- package/docs/interfaces/ActionsQuery.html +5 -5
- package/docs/interfaces/ActionsResponse.html +6 -6
- package/docs/interfaces/AggregateMetrics.html +12 -12
- package/docs/interfaces/BlockFacts.html +10 -0
- package/docs/interfaces/BlockQuery.html +6 -6
- package/docs/interfaces/BlockResponse.html +6 -6
- package/docs/interfaces/BlockSummary.html +8 -8
- package/docs/interfaces/BlockSummaryResponse.html +6 -6
- package/docs/interfaces/DeltaEvent.html +6 -6
- package/docs/interfaces/DepositSplParams.html +10 -0
- package/docs/interfaces/Info.html +3 -3
- package/docs/interfaces/Market.html +8 -6
- package/docs/interfaces/MarketStats.html +7 -7
- package/docs/interfaces/MarketsStatsResponse.html +2 -2
- package/docs/interfaces/NordConfig.html +14 -5
- package/docs/interfaces/NordWebSocketClientEvents.html +4 -0
- package/docs/interfaces/NordWebSocketEvents.html +8 -0
- package/docs/interfaces/Order.html +6 -6
- package/docs/interfaces/OrderInfo.html +6 -6
- package/docs/interfaces/OrderbookEntry.html +4 -0
- package/docs/interfaces/OrderbookQuery.html +6 -0
- package/docs/interfaces/OrderbookResponse.html +6 -10
- package/docs/interfaces/OrderbookSubscription.html +159 -0
- package/docs/interfaces/PerpMarketStats.html +5 -5
- package/docs/interfaces/RollmanActionExtendedInfo.html +4 -4
- package/docs/interfaces/RollmanActionInfo.html +4 -4
- package/docs/interfaces/RollmanActionResponse.html +4 -4
- package/docs/interfaces/RollmanActionsResponse.html +2 -2
- package/docs/interfaces/RollmanBlockResponse.html +3 -3
- package/docs/interfaces/SPLTokenInfo.html +10 -0
- package/docs/interfaces/SolanaBridgeConfig.html +10 -0
- package/docs/interfaces/StateFacts.html +10 -0
- package/docs/interfaces/SubscriberConfig.html +3 -3
- package/docs/interfaces/TimestampResponse.html +3 -0
- package/docs/interfaces/Token.html +5 -5
- package/docs/interfaces/TokenInfo.html +5 -0
- package/docs/interfaces/Trade.html +5 -5
- package/docs/interfaces/TradeSubscription.html +159 -0
- package/docs/interfaces/Trades.html +5 -5
- package/docs/interfaces/TradesQuery.html +6 -0
- package/docs/interfaces/TradesResponse.html +7 -12
- package/docs/interfaces/TransferParams.html +8 -0
- package/docs/interfaces/UserAccountIdsQuery.html +3 -0
- package/docs/interfaces/UserAccountIdsResponse.html +3 -0
- package/docs/interfaces/WebSocketDeltaUpdate.html +9 -0
- package/docs/interfaces/WebSocketSubscription.html +4 -0
- package/docs/interfaces/WebSocketTradeUpdate.html +6 -0
- package/docs/interfaces/WebSocketUserUpdate.html +6 -0
- package/docs/interfaces/WithdrawalClaim.html +14 -0
- package/docs/interfaces/WithdrawalParams.html +8 -0
- package/docs/modules.html +1 -77
- package/docs/types/BigIntValue.html +2 -2
- package/docs/types/WebSocketMessage.html +1 -0
- package/docs/variables/DEBUG_KEYS.html +1 -1
- package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +1 -1
- package/docs/variables/DEV_TOKEN_INFOS.html +1 -1
- package/docs/variables/DEV_URL.html +1 -1
- package/docs/variables/MAX_BUFFER_LEN.html +1 -1
- package/docs/variables/SESSION_TTL.html +1 -1
- package/docs/variables/WEBSERVER_DEV_URL.html +1 -1
- package/docs/variables/ZERO_DECIMAL.html +1 -1
- package/docs/variables/_private.html +2 -0
- package/eslint.config.mjs +66 -0
- package/package.json +20 -23
- package/src/bridge/client.ts +487 -0
- package/src/bridge/const.ts +53 -0
- package/src/bridge/index.ts +7 -0
- package/src/bridge/types.ts +127 -0
- package/src/bridge/utils.ts +140 -0
- package/src/const.ts +4 -9
- package/src/gen/common.ts +27 -10
- package/src/gen/nord.ts +1045 -487
- package/src/idl/bridge.ts +702 -0
- package/src/index.ts +21 -2
- package/src/nord/{actions.ts → api/actions.ts} +12 -16
- package/src/nord/api/core.ts +130 -0
- package/src/nord/api/market.ts +125 -0
- package/src/nord/api/metrics.ts +154 -0
- package/src/nord/api/queries.ts +236 -0
- package/src/nord/client/Nord.ts +652 -0
- package/src/nord/client/NordUser.ts +1101 -0
- package/src/nord/index.ts +16 -2
- package/src/nord/models/Subscriber.ts +56 -0
- package/src/nord/utils/NordError.ts +72 -0
- package/src/types.ts +163 -92
- package/src/utils.ts +22 -1
- package/src/websocket/NordWebSocketClient.ts +432 -0
- package/src/websocket/events.ts +31 -0
- package/src/websocket/index.ts +2 -0
- package/tsconfig.eslint.json +12 -0
- package/.eslintignore +0 -1
- package/.eslintrc.js +0 -20
- package/dist/abis/ERC20_ABI.d.ts +0 -39
- package/dist/abis/ERC20_ABI.js +0 -313
- package/dist/abis/NORD_GETTERS_FACET_ABI.d.ts +0 -34
- package/dist/abis/NORD_GETTERS_FACET_ABI.js +0 -195
- package/dist/abis/NORD_RAMP_FACET_ABI.d.ts +0 -35
- package/dist/abis/NORD_RAMP_FACET_ABI.js +0 -144
- package/dist/abis/index.d.ts +0 -3
- package/dist/abis/index.js +0 -9
- package/dist/nord/Nord.d.ts +0 -76
- package/dist/nord/Nord.js +0 -376
- package/dist/nord/NordImpl.d.ts +0 -7
- package/dist/nord/NordImpl.js +0 -6
- package/dist/nord/NordUser.d.ts +0 -77
- package/dist/nord/NordUser.js +0 -249
- package/docs/functions/createWebSocketSubscription.html +0 -12
- package/docs/interfaces/ERC20TokenInfo.html +0 -5
- package/docs/interfaces/OrderbookOrder.html +0 -6
- package/docs/interfaces/TradeInfo.html +0 -20
- package/docs/interfaces/TradesQueryParams.html +0 -10
- package/docs/variables/DEV_CONTRACT_ADDRESS.html +0 -1
- package/docs/variables/ERC20_ABI.html +0 -1
- package/docs/variables/EVM_DEV_URL.html +0 -1
- package/docs/variables/FAUCET_PRIVATE_ADDRESS.html +0 -1
- package/docs/variables/NORD_GETTERS_FACET_ABI.html +0 -1
- package/docs/variables/NORD_RAMP_FACET_ABI.html +0 -1
- package/src/abis/ERC20_ABI.ts +0 -310
- package/src/abis/NORD_GETTERS_FACET_ABI.ts +0 -192
- package/src/abis/NORD_RAMP_FACET_ABI.ts +0 -141
- package/src/abis/index.ts +0 -3
- package/src/nord/Nord.ts +0 -504
- package/src/nord/NordImpl.ts +0 -8
- package/src/nord/NordUser.ts +0 -469
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.NordUser = void 0;
|
|
37
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
38
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
39
|
+
const nacl = __importStar(require("tweetnacl"));
|
|
40
|
+
const client_1 = require("../../bridge/client");
|
|
41
|
+
const utils_1 = require("../../bridge/utils");
|
|
42
|
+
const utils_2 = require("../../utils");
|
|
43
|
+
const actions_1 = require("../api/actions");
|
|
44
|
+
const NordError_1 = require("../utils/NordError");
|
|
45
|
+
/**
|
|
46
|
+
* User class for interacting with the Nord protocol
|
|
47
|
+
*/
|
|
48
|
+
class NordUser {
|
|
49
|
+
/**
|
|
50
|
+
* Create a new NordUser instance
|
|
51
|
+
*
|
|
52
|
+
* @param params - Parameters for creating a NordUser
|
|
53
|
+
* @throws {NordError} If required parameters are missing
|
|
54
|
+
*/
|
|
55
|
+
constructor(params) {
|
|
56
|
+
/** User balances by token symbol */
|
|
57
|
+
this.balances = {};
|
|
58
|
+
/** User orders by market symbol */
|
|
59
|
+
this.orders = {};
|
|
60
|
+
/** User positions by account ID */
|
|
61
|
+
this.positions = {};
|
|
62
|
+
/** User margins by account ID */
|
|
63
|
+
this.margins = {};
|
|
64
|
+
/** Last timestamp used */
|
|
65
|
+
this.lastTs = 0;
|
|
66
|
+
/** Last nonce used */
|
|
67
|
+
this.lastNonce = 0;
|
|
68
|
+
/** SPL token information */
|
|
69
|
+
this.splTokenInfos = [];
|
|
70
|
+
if (!params.nord) {
|
|
71
|
+
throw new NordError_1.NordError("Nord instance is required");
|
|
72
|
+
}
|
|
73
|
+
if (!params.address) {
|
|
74
|
+
throw new NordError_1.NordError("Address is required");
|
|
75
|
+
}
|
|
76
|
+
if (!params.walletSignFn) {
|
|
77
|
+
throw new NordError_1.NordError("Wallet sign function is required");
|
|
78
|
+
}
|
|
79
|
+
if (!params.sessionSignFn) {
|
|
80
|
+
throw new NordError_1.NordError("Session sign function is required");
|
|
81
|
+
}
|
|
82
|
+
if (!params.sessionPubKey) {
|
|
83
|
+
throw new NordError_1.NordError("Session public key is required");
|
|
84
|
+
}
|
|
85
|
+
this.nord = params.nord;
|
|
86
|
+
this.address = params.address;
|
|
87
|
+
this.walletSignFn = params.walletSignFn;
|
|
88
|
+
this.sessionSignFn = params.sessionSignFn;
|
|
89
|
+
this.transactionSignFn = params.transactionSignFn;
|
|
90
|
+
this.sessionPubKey = params.sessionPubKey;
|
|
91
|
+
this.publicKey = params.publicKey;
|
|
92
|
+
this.connection =
|
|
93
|
+
params.connection ||
|
|
94
|
+
new web3_js_1.Connection(params.nord.solanaUrl, {
|
|
95
|
+
commitment: "confirmed",
|
|
96
|
+
});
|
|
97
|
+
// Set sessionId if provided
|
|
98
|
+
if (params.sessionId !== undefined) {
|
|
99
|
+
this.sessionId = params.sessionId;
|
|
100
|
+
}
|
|
101
|
+
// Initialize bridge client if needed
|
|
102
|
+
try {
|
|
103
|
+
this.initBridgeClient();
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.warn("Failed to initialize bridge client:", error);
|
|
107
|
+
}
|
|
108
|
+
// Convert tokens from info endpoint to SPLTokenInfo
|
|
109
|
+
if (this.nord.tokens && this.nord.tokens.length > 0) {
|
|
110
|
+
this.splTokenInfos = this.nord.tokens.map((token) => ({
|
|
111
|
+
mint: token.mintAddr, // Use mintAddr as mint
|
|
112
|
+
precision: token.decimals,
|
|
113
|
+
tokenId: token.tokenId,
|
|
114
|
+
name: token.symbol,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Create a clone of this NordUser instance
|
|
120
|
+
*
|
|
121
|
+
* @returns A new NordUser instance with the same properties
|
|
122
|
+
*/
|
|
123
|
+
clone() {
|
|
124
|
+
const cloned = new NordUser({
|
|
125
|
+
nord: this.nord,
|
|
126
|
+
address: this.address,
|
|
127
|
+
walletSignFn: this.walletSignFn,
|
|
128
|
+
sessionSignFn: this.sessionSignFn,
|
|
129
|
+
transactionSignFn: this.transactionSignFn,
|
|
130
|
+
connection: this.connection,
|
|
131
|
+
sessionPubKey: this.sessionPubKey,
|
|
132
|
+
publicKey: this.publicKey,
|
|
133
|
+
});
|
|
134
|
+
// Copy other properties
|
|
135
|
+
cloned.balances = { ...this.balances };
|
|
136
|
+
cloned.orders = { ...this.orders };
|
|
137
|
+
cloned.positions = { ...this.positions };
|
|
138
|
+
cloned.margins = { ...this.margins };
|
|
139
|
+
cloned.accountIds = this.accountIds ? [...this.accountIds] : undefined;
|
|
140
|
+
cloned.sessionId = this.sessionId;
|
|
141
|
+
cloned.publicKey = this.publicKey;
|
|
142
|
+
cloned.lastTs = this.lastTs;
|
|
143
|
+
cloned.lastNonce = this.lastNonce;
|
|
144
|
+
cloned.splTokenInfos = [...this.splTokenInfos];
|
|
145
|
+
return cloned;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Initialize the Solana bridge client
|
|
149
|
+
*
|
|
150
|
+
* @private
|
|
151
|
+
* @throws {NordError} If required parameters are missing
|
|
152
|
+
*/
|
|
153
|
+
initBridgeClient() {
|
|
154
|
+
if (!this.getSolanaPublicKey() ||
|
|
155
|
+
!this.connection ||
|
|
156
|
+
!this.nord.solanaProgramId) {
|
|
157
|
+
throw new NordError_1.NordError("Solana public key, connection, and program ID are required to initialize bridge client");
|
|
158
|
+
}
|
|
159
|
+
// Create an Anchor wallet that uses walletSignFn for signing
|
|
160
|
+
const wallet = {
|
|
161
|
+
publicKey: this.getSolanaPublicKey(),
|
|
162
|
+
signTransaction: async (tx) => {
|
|
163
|
+
return await this.transactionSignFn(tx);
|
|
164
|
+
},
|
|
165
|
+
signAllTransactions: async (txs) => {
|
|
166
|
+
return Promise.all(txs.map(async (tx) => {
|
|
167
|
+
return await this.transactionSignFn(tx);
|
|
168
|
+
}));
|
|
169
|
+
},
|
|
170
|
+
// Create a keypair-like object with just the public key
|
|
171
|
+
payer: {
|
|
172
|
+
publicKey: this.getSolanaPublicKey(),
|
|
173
|
+
secretKey: new Uint8Array(64), // Dummy secret key to satisfy the type
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
// Initialize the bridge client
|
|
177
|
+
this.bridgeClient = new client_1.SolanaBridgeClient({
|
|
178
|
+
rpcUrl: this.connection.rpcEndpoint,
|
|
179
|
+
programId: this.nord.solanaProgramId,
|
|
180
|
+
commitment: "confirmed",
|
|
181
|
+
tokenInfos: this.splTokenInfos,
|
|
182
|
+
}, wallet);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create a NordUser from a private key
|
|
186
|
+
*
|
|
187
|
+
* @param nord - Nord instance
|
|
188
|
+
* @param privateKey - Private key as string or Uint8Array
|
|
189
|
+
* @param connection - Solana connection (optional)
|
|
190
|
+
* @returns NordUser instance
|
|
191
|
+
* @throws {NordError} If the private key is invalid
|
|
192
|
+
*/
|
|
193
|
+
static fromPrivateKey(nord, privateKey, connection) {
|
|
194
|
+
try {
|
|
195
|
+
const keypair = (0, utils_1.keypairFromPrivateKey)(privateKey);
|
|
196
|
+
const publicKey = keypair.publicKey;
|
|
197
|
+
// Create a signing function that uses the keypair but doesn't expose it
|
|
198
|
+
const walletSignFn = async (message) => {
|
|
199
|
+
const messageBuffer = typeof message === "string"
|
|
200
|
+
? Buffer.from(message)
|
|
201
|
+
: Buffer.from(message);
|
|
202
|
+
// Use the keypair to sign the message
|
|
203
|
+
const signature = nacl.sign.detached(messageBuffer, keypair.secretKey);
|
|
204
|
+
return signature;
|
|
205
|
+
};
|
|
206
|
+
const sessionSignFn = async (message) => {
|
|
207
|
+
// Use the keypair to sign the message
|
|
208
|
+
return nacl.sign.detached(message, keypair.secretKey);
|
|
209
|
+
};
|
|
210
|
+
// Create a transaction signing function
|
|
211
|
+
const transactionSignFn = async (transaction) => {
|
|
212
|
+
// This is a basic implementation - actual implementation would depend on the transaction type
|
|
213
|
+
if (transaction.serializeMessage) {
|
|
214
|
+
// Solana transaction
|
|
215
|
+
transaction.sign([keypair]);
|
|
216
|
+
return transaction;
|
|
217
|
+
}
|
|
218
|
+
// For other transaction types, would need specific implementation
|
|
219
|
+
throw new NordError_1.NordError("Unsupported transaction type for signing");
|
|
220
|
+
};
|
|
221
|
+
return new NordUser({
|
|
222
|
+
nord,
|
|
223
|
+
address: publicKey.toBase58(),
|
|
224
|
+
walletSignFn,
|
|
225
|
+
sessionSignFn,
|
|
226
|
+
transactionSignFn,
|
|
227
|
+
connection,
|
|
228
|
+
publicKey,
|
|
229
|
+
sessionPubKey: publicKey.toBytes(), // Use the public key derived from the private key as the session public key
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
throw new NordError_1.NordError("Failed to create NordUser from private key", {
|
|
234
|
+
cause: error,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get the associated token account for a token mint
|
|
240
|
+
*
|
|
241
|
+
* @param mint - Token mint address
|
|
242
|
+
* @returns Associated token account address
|
|
243
|
+
* @throws {NordError} If required parameters are missing or operation fails
|
|
244
|
+
*/
|
|
245
|
+
async getAssociatedTokenAccount(mint) {
|
|
246
|
+
if (!this.getSolanaPublicKey()) {
|
|
247
|
+
throw new NordError_1.NordError("Solana public key is required to get associated token account");
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
return await (0, spl_token_1.getAssociatedTokenAddress)(mint, this.getSolanaPublicKey(), false, spl_token_1.TOKEN_2022_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
throw new NordError_1.NordError("Failed to get associated token account", {
|
|
254
|
+
cause: error,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Deposit SPL tokens to the bridge
|
|
260
|
+
*
|
|
261
|
+
* @param amount - Amount to deposit
|
|
262
|
+
* @param tokenId - Token ID
|
|
263
|
+
* @returns Transaction signature
|
|
264
|
+
* @throws {NordError} If required parameters are missing or operation fails
|
|
265
|
+
*/
|
|
266
|
+
async depositSpl(amount, tokenId) {
|
|
267
|
+
if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
|
|
268
|
+
throw new NordError_1.NordError("Bridge client, Solana public key, and connection are required for deposit");
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
// Find the token info
|
|
272
|
+
const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === tokenId);
|
|
273
|
+
if (!tokenInfo) {
|
|
274
|
+
throw new NordError_1.NordError(`Token with ID ${tokenId} not found`);
|
|
275
|
+
}
|
|
276
|
+
const mint = new web3_js_1.PublicKey(tokenInfo.mint);
|
|
277
|
+
// Get the user's token account
|
|
278
|
+
const fromAccount = await this.getAssociatedTokenAccount(mint);
|
|
279
|
+
// Get the bridge's token account
|
|
280
|
+
const [authority] = await this.bridgeClient.findAuthorityPda();
|
|
281
|
+
const toAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
282
|
+
// Convert amount to BN with proper decimals
|
|
283
|
+
const amountBN = (0, utils_2.toBN)(amount, tokenInfo.precision);
|
|
284
|
+
// Deposit tokens
|
|
285
|
+
return await this.bridgeClient.depositSpl({
|
|
286
|
+
amount: amountBN,
|
|
287
|
+
mint,
|
|
288
|
+
fromAccount,
|
|
289
|
+
toAccount,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
throw new NordError_1.NordError(`Failed to deposit ${amount} of token ID ${tokenId}`, { cause: error });
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Withdraw SPL tokens from the bridge
|
|
298
|
+
*
|
|
299
|
+
* @param claim - Claim data
|
|
300
|
+
* @returns Transaction signature
|
|
301
|
+
* @throws {NordError} If required parameters are missing or operation fails
|
|
302
|
+
*/
|
|
303
|
+
async withdrawSpl(claim) {
|
|
304
|
+
if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
|
|
305
|
+
throw new NordError_1.NordError("Bridge client, Solana public key, and connection are required for withdrawal");
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
// Find the token info
|
|
309
|
+
const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === claim.tokenId);
|
|
310
|
+
if (!tokenInfo) {
|
|
311
|
+
throw new NordError_1.NordError(`Token with ID ${claim.tokenId} not found`);
|
|
312
|
+
}
|
|
313
|
+
const mint = new web3_js_1.PublicKey(tokenInfo.mint);
|
|
314
|
+
// Get the user's token account
|
|
315
|
+
const toAccount = await this.getAssociatedTokenAccount(mint);
|
|
316
|
+
// Get the bridge's token account
|
|
317
|
+
const [authority] = await this.bridgeClient.findAuthorityPda();
|
|
318
|
+
const fromAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
319
|
+
// Create a transaction signer that uses walletSignFn
|
|
320
|
+
const transactionSigner = {
|
|
321
|
+
publicKey: this.getSolanaPublicKey(),
|
|
322
|
+
secretKey: new Uint8Array(64), // Dummy secret key, not actually used
|
|
323
|
+
sign: async (tx) => {
|
|
324
|
+
const message = tx.serializeMessage();
|
|
325
|
+
await this.walletSignFn(message);
|
|
326
|
+
return tx;
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
// Withdraw tokens
|
|
330
|
+
return await this.bridgeClient.withdraw({
|
|
331
|
+
claim,
|
|
332
|
+
fromAccount,
|
|
333
|
+
toAccount,
|
|
334
|
+
}, transactionSigner);
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
throw new NordError_1.NordError("Failed to withdraw SPL tokens", { cause: error });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get a new nonce for actions
|
|
342
|
+
*
|
|
343
|
+
* @returns Nonce as number
|
|
344
|
+
*/
|
|
345
|
+
getNonce() {
|
|
346
|
+
return ++this.lastNonce;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Update account IDs for this user
|
|
350
|
+
*
|
|
351
|
+
* @throws {NordError} If the operation fails
|
|
352
|
+
*/
|
|
353
|
+
async updateAccountId() {
|
|
354
|
+
try {
|
|
355
|
+
if (!this.publicKey) {
|
|
356
|
+
throw new NordError_1.NordError("Public key is required to update account ID");
|
|
357
|
+
}
|
|
358
|
+
const resp = await this.nord.getUserAccountIds({
|
|
359
|
+
pubkey: this.publicKey.toBase58(),
|
|
360
|
+
});
|
|
361
|
+
this.accountIds = resp.accountIds;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
throw new NordError_1.NordError("Failed to update account ID", { cause: error });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Fetch user information including balances and orders
|
|
369
|
+
*
|
|
370
|
+
* @throws {NordError} If the operation fails
|
|
371
|
+
*/
|
|
372
|
+
async fetchInfo() {
|
|
373
|
+
if (this.accountIds !== undefined) {
|
|
374
|
+
const accountsData = await Promise.all(this.accountIds.map(async (accountId) => {
|
|
375
|
+
const response = await (0, utils_2.checkedFetch)(`${this.nord.webServerUrl}/account?account_id=${accountId}`);
|
|
376
|
+
const accountData = (await response.json());
|
|
377
|
+
// Ensure we have the correct accountId
|
|
378
|
+
return {
|
|
379
|
+
...accountData,
|
|
380
|
+
accountId,
|
|
381
|
+
};
|
|
382
|
+
}));
|
|
383
|
+
for (const accountData of accountsData) {
|
|
384
|
+
// Process balances
|
|
385
|
+
this.balances[accountData.accountId] = [];
|
|
386
|
+
for (const balance of accountData.balances) {
|
|
387
|
+
this.balances[accountData.accountId].push({
|
|
388
|
+
accountId: accountData.accountId,
|
|
389
|
+
balance: balance.amount,
|
|
390
|
+
symbol: balance.token,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
// Process orders
|
|
394
|
+
this.orders[accountData.accountId] = accountData.orders.map((order) => {
|
|
395
|
+
return {
|
|
396
|
+
orderId: order.orderId,
|
|
397
|
+
isLong: order.side === "bid",
|
|
398
|
+
size: order.size,
|
|
399
|
+
price: order.price,
|
|
400
|
+
marketId: order.marketId,
|
|
401
|
+
};
|
|
402
|
+
});
|
|
403
|
+
// Process positions
|
|
404
|
+
this.positions[accountData.accountId] = accountData.positions;
|
|
405
|
+
// Process margins
|
|
406
|
+
this.margins[accountData.accountId] = accountData.margins;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Refresh the user's session
|
|
412
|
+
*
|
|
413
|
+
* @throws {NordError} If the operation fails
|
|
414
|
+
*/
|
|
415
|
+
async refreshSession() {
|
|
416
|
+
console.log(this.publicKey);
|
|
417
|
+
this.sessionId = await (0, actions_1.createSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
418
|
+
userPubkey: (0, utils_2.optExpect)(this.publicKey.toBytes(), "No user's public key"),
|
|
419
|
+
sessionPubkey: this.sessionPubKey,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Revoke a session
|
|
424
|
+
*
|
|
425
|
+
* @param sessionId - Session ID to revoke
|
|
426
|
+
* @throws {NordError} If the operation fails
|
|
427
|
+
*/
|
|
428
|
+
async revokeSession(sessionId) {
|
|
429
|
+
try {
|
|
430
|
+
await (0, actions_1.revokeSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
431
|
+
sessionId,
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
throw new NordError_1.NordError(`Failed to revoke session ${sessionId}`, {
|
|
436
|
+
cause: error,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Checks if the session is valid
|
|
442
|
+
* @private
|
|
443
|
+
* @throws {NordError} If the session is not valid
|
|
444
|
+
*/
|
|
445
|
+
checkSessionValidity() {
|
|
446
|
+
if (this.sessionId === undefined || this.sessionId === BigInt(0)) {
|
|
447
|
+
throw new NordError_1.NordError("Invalid or empty session ID. Please create or refresh your session.");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Withdraw tokens from the exchange
|
|
452
|
+
*
|
|
453
|
+
* @param tokenId - Token ID to withdraw
|
|
454
|
+
* @param amount - Amount to withdraw
|
|
455
|
+
* @throws {NordError} If the operation fails
|
|
456
|
+
*/
|
|
457
|
+
async withdraw(tokenId, amount) {
|
|
458
|
+
try {
|
|
459
|
+
this.checkSessionValidity();
|
|
460
|
+
await (0, actions_1.withdraw)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
461
|
+
sizeDecimals: (0, utils_2.findToken)(this.nord.tokens, tokenId).decimals,
|
|
462
|
+
sessionId: (0, utils_2.optExpect)(this.sessionId, "No session"),
|
|
463
|
+
tokenId: tokenId,
|
|
464
|
+
amount,
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
throw new NordError_1.NordError(`Failed to withdraw ${amount} of token ID ${tokenId}`, { cause: error });
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Place an order on the exchange
|
|
473
|
+
*
|
|
474
|
+
* @param params - Order parameters
|
|
475
|
+
* @returns Order ID if successful
|
|
476
|
+
* @throws {NordError} If the operation fails
|
|
477
|
+
*/
|
|
478
|
+
async placeOrder(params) {
|
|
479
|
+
try {
|
|
480
|
+
this.checkSessionValidity();
|
|
481
|
+
const market = (0, utils_2.findMarket)(this.nord.markets, params.marketId);
|
|
482
|
+
if (!market) {
|
|
483
|
+
throw new NordError_1.NordError(`Market with ID ${params.marketId} not found`);
|
|
484
|
+
}
|
|
485
|
+
return (0, actions_1.placeOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
486
|
+
sessionId: (0, utils_2.optExpect)(this.sessionId, "No session"),
|
|
487
|
+
senderId: params.accountId,
|
|
488
|
+
sizeDecimals: market.sizeDecimals,
|
|
489
|
+
priceDecimals: market.priceDecimals,
|
|
490
|
+
marketId: params.marketId,
|
|
491
|
+
side: params.side,
|
|
492
|
+
fillMode: params.fillMode,
|
|
493
|
+
isReduceOnly: params.isReduceOnly,
|
|
494
|
+
size: params.size,
|
|
495
|
+
price: params.price,
|
|
496
|
+
quoteSize: params.quoteSize,
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
catch (error) {
|
|
500
|
+
throw new NordError_1.NordError("Failed to place order", { cause: error });
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Cancel an order
|
|
505
|
+
*
|
|
506
|
+
* @param orderId - Order ID to cancel
|
|
507
|
+
* @param accountId - Account ID that placed the order
|
|
508
|
+
* @returns Action ID if successful
|
|
509
|
+
* @throws {NordError} If the operation fails
|
|
510
|
+
*/
|
|
511
|
+
async cancelOrder(orderId, providedAccountId) {
|
|
512
|
+
const accountId = providedAccountId != null ? providedAccountId : this.accountIds?.[0];
|
|
513
|
+
try {
|
|
514
|
+
this.checkSessionValidity();
|
|
515
|
+
return (0, actions_1.cancelOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
516
|
+
sessionId: (0, utils_2.optExpect)(this.sessionId, "No session"),
|
|
517
|
+
senderId: accountId,
|
|
518
|
+
orderId,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
throw new NordError_1.NordError(`Failed to cancel order ${orderId}`, {
|
|
523
|
+
cause: error,
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Transfer tokens to another account
|
|
529
|
+
*
|
|
530
|
+
* @param params - Transfer parameters
|
|
531
|
+
* @throws {NordError} If the operation fails
|
|
532
|
+
*/
|
|
533
|
+
async transferToAccount(params) {
|
|
534
|
+
try {
|
|
535
|
+
this.checkSessionValidity();
|
|
536
|
+
const token = (0, utils_2.findToken)(this.nord.tokens, params.tokenId);
|
|
537
|
+
await (0, actions_1.transfer)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
538
|
+
sessionId: (0, utils_2.optExpect)(this.sessionId, "No session"),
|
|
539
|
+
fromAccountId: (0, utils_2.optExpect)(params.fromAccountId, "No source account"),
|
|
540
|
+
toAccountId: (0, utils_2.optExpect)(params.toAccountId, "No target account"),
|
|
541
|
+
tokenId: params.tokenId,
|
|
542
|
+
tokenDecimals: token.decimals,
|
|
543
|
+
amount: params.amount,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
throw new NordError_1.NordError("Failed to transfer tokens", { cause: error });
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Create a new account
|
|
552
|
+
*
|
|
553
|
+
* @param params - Account creation parameters
|
|
554
|
+
* @returns New NordUser instance
|
|
555
|
+
* @throws {NordError} If the operation fails
|
|
556
|
+
*/
|
|
557
|
+
async createAccount(params) {
|
|
558
|
+
try {
|
|
559
|
+
this.checkSessionValidity();
|
|
560
|
+
// Create a new keypair for the account
|
|
561
|
+
const keypair = web3_js_1.Keypair.generate();
|
|
562
|
+
// Create a new NordUser
|
|
563
|
+
const newUser = NordUser.fromPrivateKey(this.nord, keypair.secretKey, this.connection);
|
|
564
|
+
// Transfer initial funds
|
|
565
|
+
await this.transferToAccount({
|
|
566
|
+
to: newUser,
|
|
567
|
+
tokenId: params.tokenId,
|
|
568
|
+
amount: params.amount,
|
|
569
|
+
fromAccountId: (0, utils_2.optExpect)(this.accountIds?.[0], "No account ID"),
|
|
570
|
+
toAccountId: (0, utils_2.optExpect)(newUser.accountIds?.[0], "No account ID for new user"),
|
|
571
|
+
});
|
|
572
|
+
return newUser;
|
|
573
|
+
}
|
|
574
|
+
catch (error) {
|
|
575
|
+
throw new NordError_1.NordError("Failed to create account", { cause: error });
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Helper function to retry a promise with exponential backoff
|
|
580
|
+
*
|
|
581
|
+
* @param fn - Function to retry
|
|
582
|
+
* @param maxRetries - Maximum number of retries
|
|
583
|
+
* @param initialDelay - Initial delay in milliseconds
|
|
584
|
+
* @returns Promise result
|
|
585
|
+
*/
|
|
586
|
+
async retryWithBackoff(fn, maxRetries = 3, initialDelay = 500) {
|
|
587
|
+
let retries = 0;
|
|
588
|
+
let delay = initialDelay;
|
|
589
|
+
while (true) {
|
|
590
|
+
try {
|
|
591
|
+
return await fn();
|
|
592
|
+
}
|
|
593
|
+
catch (error) {
|
|
594
|
+
if (retries >= maxRetries) {
|
|
595
|
+
throw error;
|
|
596
|
+
}
|
|
597
|
+
// Check if error is rate limiting related
|
|
598
|
+
const isRateLimitError = error instanceof Error &&
|
|
599
|
+
(error.message.includes("rate limit") ||
|
|
600
|
+
error.message.includes("429") ||
|
|
601
|
+
error.message.includes("too many requests"));
|
|
602
|
+
if (!isRateLimitError) {
|
|
603
|
+
throw error;
|
|
604
|
+
}
|
|
605
|
+
retries++;
|
|
606
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
607
|
+
delay *= 2; // Exponential backoff
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Get user's token balances on Solana chain using mintAddr
|
|
613
|
+
*
|
|
614
|
+
* @param options - Optional parameters
|
|
615
|
+
* @param options.includeZeroBalances - Whether to include tokens with zero balance (default: true)
|
|
616
|
+
* @param options.includeTokenAccounts - Whether to include token account addresses in the result (default: false)
|
|
617
|
+
* @param options.maxConcurrent - Maximum number of concurrent requests (default: 5)
|
|
618
|
+
* @param options.maxRetries - Maximum number of retries for rate-limited requests (default: 3)
|
|
619
|
+
* @returns Object with token balances and optional token account addresses
|
|
620
|
+
* @throws {NordError} If required parameters are missing or operation fails
|
|
621
|
+
*/
|
|
622
|
+
async getSolanaBalances(options = {}) {
|
|
623
|
+
const { includeZeroBalances = true, includeTokenAccounts = false, maxConcurrent = 5, maxRetries = 3, } = options;
|
|
624
|
+
if (!this.connection || !this.getSolanaPublicKey()) {
|
|
625
|
+
throw new NordError_1.NordError("Connection and Solana public key are required to get Solana balances");
|
|
626
|
+
}
|
|
627
|
+
const balances = {};
|
|
628
|
+
const tokenAccounts = {};
|
|
629
|
+
try {
|
|
630
|
+
// Get SOL balance (native token)
|
|
631
|
+
const solBalance = await this.retryWithBackoff(() => this.connection.getBalance(this.getSolanaPublicKey()), maxRetries);
|
|
632
|
+
balances["SOL"] = solBalance / 1e9; // Convert lamports to SOL
|
|
633
|
+
if (includeTokenAccounts) {
|
|
634
|
+
tokenAccounts["SOL"] = this.getSolanaPublicKey().toString();
|
|
635
|
+
}
|
|
636
|
+
// Get SPL token balances using mintAddr from Nord tokens
|
|
637
|
+
if (this.nord.tokens && this.nord.tokens.length > 0) {
|
|
638
|
+
const tokens = this.nord.tokens.filter((token) => !!token.mintAddr);
|
|
639
|
+
// Process tokens in batches to avoid rate limiting
|
|
640
|
+
for (let i = 0; i < tokens.length; i += maxConcurrent) {
|
|
641
|
+
const batch = tokens.slice(i, i + maxConcurrent);
|
|
642
|
+
// Process batch in parallel
|
|
643
|
+
const batchPromises = batch.map(async (token) => {
|
|
644
|
+
try {
|
|
645
|
+
const mint = new web3_js_1.PublicKey(token.mintAddr);
|
|
646
|
+
const associatedTokenAddress = await this.retryWithBackoff(() => (0, spl_token_1.getAssociatedTokenAddress)(mint, this.getSolanaPublicKey()), maxRetries);
|
|
647
|
+
if (includeTokenAccounts) {
|
|
648
|
+
tokenAccounts[token.symbol] = associatedTokenAddress.toString();
|
|
649
|
+
}
|
|
650
|
+
try {
|
|
651
|
+
const tokenBalance = await this.retryWithBackoff(() => this.connection.getTokenAccountBalance(associatedTokenAddress), maxRetries);
|
|
652
|
+
const balance = Number(tokenBalance.value.uiAmount);
|
|
653
|
+
if (balance > 0 || includeZeroBalances) {
|
|
654
|
+
balances[token.symbol] = balance;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
catch {
|
|
658
|
+
// Token account might not exist yet, set balance to 0
|
|
659
|
+
if (includeZeroBalances) {
|
|
660
|
+
balances[token.symbol] = 0;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
catch (error) {
|
|
665
|
+
console.error(`Error getting balance for token ${token.symbol}:`, error);
|
|
666
|
+
if (includeZeroBalances) {
|
|
667
|
+
balances[token.symbol] = 0;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
// Wait for current batch to complete before processing next batch
|
|
672
|
+
await Promise.all(batchPromises);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return includeTokenAccounts ? { balances, tokenAccounts } : { balances };
|
|
676
|
+
}
|
|
677
|
+
catch (error) {
|
|
678
|
+
throw new NordError_1.NordError("Failed to get Solana token balances", {
|
|
679
|
+
cause: error,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Get the Solana public key derived from the address
|
|
685
|
+
*
|
|
686
|
+
* @returns The Solana public key
|
|
687
|
+
*/
|
|
688
|
+
getSolanaPublicKey() {
|
|
689
|
+
try {
|
|
690
|
+
return new web3_js_1.PublicKey(this.address);
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
throw new NordError_1.NordError("Invalid Solana address", { cause: error });
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
exports.NordUser = NordUser;
|