@n1xyz/nord-ts 0.0.16 → 0.0.18-8121ed05.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/bridge/client.js +45 -6
- package/dist/gen/nord.d.ts +48 -4
- package/dist/gen/nord.js +634 -34
- package/dist/idl/bridge.d.ts +569 -0
- package/dist/idl/bridge.js +8 -0
- package/dist/idl/bridge.json +75 -62
- package/dist/idl/index.d.ts +71 -49
- package/dist/index.d.ts +1 -3
- package/dist/index.js +6 -13
- package/dist/nord/api/actions.d.ts +7 -2
- package/dist/nord/api/actions.js +7 -1
- package/dist/nord/api/core.d.ts +1 -1
- package/dist/nord/api/core.js +3 -3
- package/dist/nord/api/market.js +1 -3
- package/dist/nord/api/queries.js +2 -2
- package/dist/nord/client/Nord.d.ts +9 -14
- package/dist/nord/client/Nord.js +27 -38
- package/dist/nord/client/NordUser.d.ts +7 -23
- package/dist/nord/client/NordUser.js +67 -143
- package/dist/nord/utils/NordError.js +5 -2
- package/dist/types.d.ts +34 -50
- package/dist/utils.d.ts +2 -9
- package/dist/utils.js +13 -18
- package/package.json +17 -18
- package/protoc-generate.sh +0 -0
- package/src/idl/bridge.json +75 -62
- package/src/index.ts +9 -12
- package/src/nord/api/actions.ts +14 -3
- package/src/nord/api/core.ts +4 -2
- package/src/nord/api/market.ts +1 -4
- package/src/nord/api/queries.ts +2 -2
- package/src/nord/client/Nord.ts +45 -50
- package/src/nord/client/NordUser.ts +90 -171
- package/src/nord/utils/NordError.ts +6 -2
- package/src/types.ts +34 -49
- package/src/utils.ts +16 -19
- package/codebase.md +0 -18886
- package/docs/.nojekyll +0 -1
- package/docs/assets/hierarchy.js +0 -1
- package/docs/assets/highlight.css +0 -92
- package/docs/assets/icons.js +0 -18
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -60
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1611
- package/docs/classes/Nord.html +0 -189
- package/docs/classes/NordError.html +0 -24
- package/docs/classes/NordUser.html +0 -115
- package/docs/classes/NordWebSocketClient.html +0 -330
- package/docs/classes/SolanaBridgeClient.html +0 -91
- package/docs/classes/Subscriber.html +0 -10
- package/docs/enums/FillMode.html +0 -5
- package/docs/enums/KeyType.html +0 -4
- package/docs/enums/MetricPeriod.html +0 -9
- package/docs/enums/PdaSeedType.html +0 -11
- package/docs/enums/PeakTpsPeriodUnit.html +0 -15
- package/docs/enums/Side.html +0 -3
- package/docs/enums/WebSocketMessageType.html +0 -7
- package/docs/functions/actionQueryRollman.html +0 -6
- package/docs/functions/actionsQueryRollman.html +0 -6
- package/docs/functions/aggregateMetrics-1.html +0 -7
- package/docs/functions/assert.html +0 -1
- package/docs/functions/bigIntToProtoU128.html +0 -4
- package/docs/functions/bridgeToBN.html +0 -5
- package/docs/functions/bufferToHex.html +0 -4
- package/docs/functions/cancelOrder.html +0 -1
- package/docs/functions/checkPubKeyLength.html +0 -1
- package/docs/functions/checkedFetch.html +0 -6
- package/docs/functions/createSession.html +0 -1
- package/docs/functions/decodeLengthDelimited.html +0 -11
- package/docs/functions/encodeLengthDelimited.html +0 -6
- package/docs/functions/fillModeToProtoFillMode.html +0 -5
- package/docs/functions/findMarket.html +0 -1
- package/docs/functions/findPda.html +0 -6
- package/docs/functions/findToken.html +0 -1
- package/docs/functions/fromBN.html +0 -5
- package/docs/functions/getAccount.html +0 -6
- package/docs/functions/getActionNonce.html +0 -5
- package/docs/functions/getCurrentTps.html +0 -6
- package/docs/functions/getInfo.html +0 -5
- package/docs/functions/getLastActionId.html +0 -5
- package/docs/functions/getMedianLatency.html +0 -6
- package/docs/functions/getOrderbook.html +0 -6
- package/docs/functions/getPeakTps.html +0 -6
- package/docs/functions/getTimestamp.html +0 -5
- package/docs/functions/getTotalTransactions.html +0 -5
- package/docs/functions/getTrades.html +0 -6
- package/docs/functions/getUserAccountIds.html +0 -6
- package/docs/functions/hexToBuffer.html +0 -4
- package/docs/functions/initWebSocketClient.html +0 -12
- package/docs/functions/keypairFromPrivateKey.html +0 -4
- package/docs/functions/makeSigningFunction.html +0 -4
- package/docs/functions/makeWalletSignFn.html +0 -6
- package/docs/functions/marketsStats.html +0 -5
- package/docs/functions/optExpect.html +0 -5
- package/docs/functions/optMap.html +0 -5
- package/docs/functions/optUnwrap.html +0 -2
- package/docs/functions/panic.html +0 -1
- package/docs/functions/placeOrder.html +0 -1
- package/docs/functions/queryAction.html +0 -6
- package/docs/functions/queryPrometheus.html +0 -6
- package/docs/functions/queryRecentActions.html +0 -7
- package/docs/functions/revokeSession.html +0 -1
- package/docs/functions/shortenPublicKey.html +0 -5
- package/docs/functions/signAction.html +0 -6
- package/docs/functions/toBN.html +0 -5
- package/docs/functions/toScaledU128.html +0 -8
- package/docs/functions/toScaledU64.html +0 -8
- package/docs/functions/transfer.html +0 -1
- package/docs/functions/withdraw.html +0 -1
- package/docs/hierarchy.html +0 -1
- package/docs/index.html +0 -40
- package/docs/interfaces/Account.html +0 -8
- package/docs/interfaces/ActionInfo.html +0 -8
- package/docs/interfaces/ActionNonceResponse.html +0 -3
- package/docs/interfaces/ActionQuery.html +0 -4
- package/docs/interfaces/ActionResponse.html +0 -8
- package/docs/interfaces/ActionsExtendedInfo.html +0 -10
- package/docs/interfaces/ActionsQuery.html +0 -5
- package/docs/interfaces/ActionsResponse.html +0 -6
- package/docs/interfaces/AggregateMetrics.html +0 -12
- package/docs/interfaces/BlockFacts.html +0 -10
- package/docs/interfaces/BlockQuery.html +0 -6
- package/docs/interfaces/BlockResponse.html +0 -6
- package/docs/interfaces/BlockSummary.html +0 -8
- package/docs/interfaces/BlockSummaryResponse.html +0 -6
- package/docs/interfaces/DeltaEvent.html +0 -6
- package/docs/interfaces/DepositSplParams.html +0 -8
- package/docs/interfaces/Info.html +0 -3
- package/docs/interfaces/Market.html +0 -8
- package/docs/interfaces/MarketStats.html +0 -7
- package/docs/interfaces/MarketsStatsResponse.html +0 -2
- package/docs/interfaces/NordConfig.html +0 -24
- package/docs/interfaces/NordWebSocketClientEvents.html +0 -4
- package/docs/interfaces/NordWebSocketEvents.html +0 -8
- package/docs/interfaces/Order.html +0 -6
- package/docs/interfaces/OrderInfo.html +0 -6
- package/docs/interfaces/OrderbookEntry.html +0 -4
- package/docs/interfaces/OrderbookQuery.html +0 -6
- package/docs/interfaces/OrderbookResponse.html +0 -6
- package/docs/interfaces/OrderbookSubscription.html +0 -159
- package/docs/interfaces/PerpMarketStats.html +0 -5
- package/docs/interfaces/RollmanActionExtendedInfo.html +0 -4
- package/docs/interfaces/RollmanActionInfo.html +0 -4
- package/docs/interfaces/RollmanActionResponse.html +0 -4
- package/docs/interfaces/RollmanActionsResponse.html +0 -2
- package/docs/interfaces/RollmanBlockResponse.html +0 -3
- package/docs/interfaces/SPLTokenInfo.html +0 -10
- package/docs/interfaces/SolanaBridgeConfig.html +0 -12
- package/docs/interfaces/StateFacts.html +0 -10
- package/docs/interfaces/SubscriberConfig.html +0 -3
- package/docs/interfaces/TimestampResponse.html +0 -3
- package/docs/interfaces/Token.html +0 -5
- package/docs/interfaces/TokenInfo.html +0 -6
- package/docs/interfaces/Trade.html +0 -5
- package/docs/interfaces/TradeSubscription.html +0 -159
- package/docs/interfaces/Trades.html +0 -5
- package/docs/interfaces/TradesQuery.html +0 -6
- package/docs/interfaces/TradesResponse.html +0 -7
- package/docs/interfaces/TransferParams.html +0 -8
- package/docs/interfaces/UserAccountIdsQuery.html +0 -3
- package/docs/interfaces/UserAccountIdsResponse.html +0 -3
- package/docs/interfaces/WebSocketAccountUpdate.html +0 -6
- package/docs/interfaces/WebSocketDeltaUpdate.html +0 -9
- package/docs/interfaces/WebSocketSubscription.html +0 -4
- package/docs/interfaces/WebSocketTradeUpdate.html +0 -6
- package/docs/interfaces/WithdrawalClaim.html +0 -14
- package/docs/interfaces/WithdrawalParams.html +0 -8
- package/docs/modules.html +0 -1
- package/docs/types/BigIntValue.html +0 -2
- package/docs/types/SubscriptionPattern.html +0 -4
- package/docs/types/SubscriptionType.html +0 -2
- package/docs/types/WebSocketMessage.html +0 -1
- package/docs/variables/DEBUG_KEYS.html +0 -1
- package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +0 -1
- package/docs/variables/DEV_TOKEN_INFOS.html +0 -1
- package/docs/variables/DEV_URL.html +0 -1
- package/docs/variables/MAX_BUFFER_LEN.html +0 -1
- package/docs/variables/SESSION_TTL.html +0 -1
- package/docs/variables/WEBSERVER_DEV_URL.html +0 -1
- package/docs/variables/ZERO_DECIMAL.html +0 -1
- package/docs/variables/_private.html +0 -2
- package/idl-generate.sh +0 -4
- package/src/bridge/client.ts +0 -498
- package/src/bridge/const.ts +0 -53
- package/src/bridge/index.ts +0 -6
- package/src/bridge/types.ts +0 -129
- package/src/bridge/utils.ts +0 -140
- package/src/gen/common.ts +0 -297
- package/src/gen/nord.ts +0 -6716
- package/src/idl/index.ts +0 -2
package/src/nord/client/Nord.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { EventEmitter } from "events";
|
|
2
|
-
import { Connection, PublicKey } from "@solana/web3.js";
|
|
3
2
|
import {
|
|
4
3
|
Account,
|
|
5
4
|
ActionQuery,
|
|
@@ -22,6 +21,7 @@ import {
|
|
|
22
21
|
UserAccountIdsQuery,
|
|
23
22
|
UserAccountIdsResponse,
|
|
24
23
|
} from "../../types";
|
|
24
|
+
import { ProtonClient } from "@n1xyz/proton";
|
|
25
25
|
import { NordWebSocketClient } from "../../websocket/index";
|
|
26
26
|
import * as core from "../api/core";
|
|
27
27
|
import * as market from "../api/market";
|
|
@@ -29,6 +29,7 @@ import * as metrics from "../api/metrics";
|
|
|
29
29
|
import * as queries from "../api/queries";
|
|
30
30
|
import { OrderbookSubscription, TradeSubscription } from "../models/Subscriber";
|
|
31
31
|
import { NordError } from "../utils/NordError";
|
|
32
|
+
import { PublicKey, Connection } from "@solana/web3.js";
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* User subscription interface
|
|
@@ -57,10 +58,7 @@ export class Nord {
|
|
|
57
58
|
public readonly webServerUrl: string;
|
|
58
59
|
|
|
59
60
|
/** Bridge verification key */
|
|
60
|
-
public readonly bridgeVk:
|
|
61
|
-
|
|
62
|
-
/** Optional Solana program ID (will be derived from bridgeVk) */
|
|
63
|
-
private _solanaProgramId!: string;
|
|
61
|
+
public readonly bridgeVk: PublicKey;
|
|
64
62
|
|
|
65
63
|
/** Solana RPC URL */
|
|
66
64
|
public readonly solanaUrl: string;
|
|
@@ -74,6 +72,9 @@ export class Nord {
|
|
|
74
72
|
/** Map of symbol to market_id */
|
|
75
73
|
private symbolToMarketId: Map<string, number> = new Map();
|
|
76
74
|
|
|
75
|
+
/** Proton client for bridge and indexd operations */
|
|
76
|
+
public protonClient: ProtonClient;
|
|
77
|
+
|
|
77
78
|
/**
|
|
78
79
|
* Create a new Nord client
|
|
79
80
|
*
|
|
@@ -83,22 +84,21 @@ export class Nord {
|
|
|
83
84
|
* @param config.solanaUrl - Solana cluster URL
|
|
84
85
|
* @throws {Error} If required configuration is missing
|
|
85
86
|
*/
|
|
86
|
-
constructor(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.
|
|
100
|
-
this.
|
|
101
|
-
this.solanaUrl = config.solanaUrl;
|
|
87
|
+
private constructor({
|
|
88
|
+
bridgeVk,
|
|
89
|
+
solanaUrl,
|
|
90
|
+
webServerUrl,
|
|
91
|
+
protonClient,
|
|
92
|
+
}: Readonly<{
|
|
93
|
+
bridgeVk: PublicKey;
|
|
94
|
+
solanaUrl: string;
|
|
95
|
+
webServerUrl: string;
|
|
96
|
+
protonClient: ProtonClient;
|
|
97
|
+
}>) {
|
|
98
|
+
this.webServerUrl = webServerUrl;
|
|
99
|
+
this.bridgeVk = bridgeVk;
|
|
100
|
+
this.solanaUrl = solanaUrl;
|
|
101
|
+
this.protonClient = protonClient;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
@@ -173,13 +173,13 @@ export class Nord {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
* Get the
|
|
176
|
+
* Get the last event nonce from the Nord server
|
|
177
177
|
*
|
|
178
178
|
* @returns Next action nonce
|
|
179
179
|
* @throws {NordError} If the request fails
|
|
180
180
|
*/
|
|
181
181
|
async getActionNonce(): Promise<number> {
|
|
182
|
-
return core.
|
|
182
|
+
return core.getLastEventNonce(this.webServerUrl);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
/**
|
|
@@ -213,44 +213,39 @@ export class Nord {
|
|
|
213
213
|
* @returns Initialized Nord client
|
|
214
214
|
* @throws {NordError} If initialization fails
|
|
215
215
|
*/
|
|
216
|
-
public static async initNord(
|
|
217
|
-
|
|
216
|
+
public static async initNord({
|
|
217
|
+
bridgeVk: bridgeVk_,
|
|
218
|
+
solanaUrl,
|
|
219
|
+
webServerUrl,
|
|
220
|
+
}: Readonly<NordConfig>): Promise<Nord> {
|
|
221
|
+
// TODO: we should parametrize the connectionn not have it done here.
|
|
222
|
+
// this is a dogshit api, only here to be compatible with the shitty
|
|
223
|
+
// vibecoded code and not break zero one team's workflow.
|
|
224
|
+
const connection = new Connection(solanaUrl, { commitment: "confirmed" });
|
|
225
|
+
const bridgeVk = new PublicKey(bridgeVk_);
|
|
226
|
+
const protonClient = await ProtonClient.init({
|
|
227
|
+
protonUrl: webServerUrl,
|
|
228
|
+
bridgeVk,
|
|
229
|
+
solConn: connection,
|
|
230
|
+
});
|
|
231
|
+
const nord = new Nord({
|
|
232
|
+
bridgeVk,
|
|
233
|
+
protonClient,
|
|
234
|
+
solanaUrl,
|
|
235
|
+
webServerUrl,
|
|
236
|
+
});
|
|
218
237
|
await nord.init();
|
|
219
238
|
return nord;
|
|
220
239
|
}
|
|
221
240
|
|
|
222
241
|
/**
|
|
223
|
-
* Initialize the Nord client
|
|
242
|
+
* Initialize the Nord client
|
|
224
243
|
* @private
|
|
225
244
|
*/
|
|
226
245
|
private async init(): Promise<void> {
|
|
227
|
-
const connection = new Connection(this.solanaUrl);
|
|
228
|
-
const bridgeVkPubkey = new PublicKey(this.bridgeVk);
|
|
229
|
-
|
|
230
|
-
const bridgeAccount = await connection.getAccountInfo(bridgeVkPubkey);
|
|
231
|
-
if (!bridgeAccount) {
|
|
232
|
-
throw new NordError(`Bridge account ${this.bridgeVk} not found`);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
this._solanaProgramId = bridgeAccount.owner.toString();
|
|
236
246
|
await this.fetchNordInfo();
|
|
237
247
|
}
|
|
238
248
|
|
|
239
|
-
/**
|
|
240
|
-
* Get the Solana program ID derived from bridge VK
|
|
241
|
-
*
|
|
242
|
-
* @returns Program ID string
|
|
243
|
-
* @throws {NordError} If program ID hasn't been initialized
|
|
244
|
-
*/
|
|
245
|
-
public getSolanaProgramId(): string {
|
|
246
|
-
if (!this._solanaProgramId) {
|
|
247
|
-
throw new NordError(
|
|
248
|
-
"Solana program ID not initialized. Have you called Nord.initNord()?",
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
return this._solanaProgramId;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
249
|
/**
|
|
255
250
|
* Get market statistics
|
|
256
251
|
*
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import * as anchor from "@coral-xyz/anchor";
|
|
2
1
|
import {
|
|
3
2
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
4
3
|
getAssociatedTokenAddress,
|
|
4
|
+
TOKEN_PROGRAM_ID,
|
|
5
5
|
TOKEN_2022_PROGRAM_ID,
|
|
6
6
|
} from "@solana/spl-token";
|
|
7
|
-
import { Connection,
|
|
7
|
+
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
|
|
8
8
|
import Decimal from "decimal.js";
|
|
9
9
|
import * as ed from "@noble/ed25519";
|
|
10
10
|
import { sha512 } from "@noble/hashes/sha512";
|
|
11
11
|
ed.etc.sha512Sync = sha512;
|
|
12
|
-
import {
|
|
13
|
-
import { SPLTokenInfo } from "../../bridge/types";
|
|
14
|
-
import { keypairFromPrivateKey } from "../../bridge/utils";
|
|
12
|
+
import { SPLTokenInfo, DepositSplParams, floatToBn } from "@n1xyz/proton";
|
|
15
13
|
import { FillMode, Order, Side } from "../../types";
|
|
16
14
|
import {
|
|
17
15
|
BigIntValue,
|
|
@@ -19,7 +17,7 @@ import {
|
|
|
19
17
|
findMarket,
|
|
20
18
|
findToken,
|
|
21
19
|
optExpect,
|
|
22
|
-
|
|
20
|
+
keypairFromPrivateKey,
|
|
23
21
|
} from "../../utils";
|
|
24
22
|
import {
|
|
25
23
|
cancelOrder,
|
|
@@ -121,7 +119,7 @@ export class NordUser {
|
|
|
121
119
|
public readonly nord: Nord;
|
|
122
120
|
|
|
123
121
|
/** User's blockchain address */
|
|
124
|
-
public readonly address:
|
|
122
|
+
public readonly address: PublicKey;
|
|
125
123
|
|
|
126
124
|
/** Function to sign messages with the user's wallet */
|
|
127
125
|
public readonly walletSignFn: (
|
|
@@ -191,10 +189,6 @@ export class NordUser {
|
|
|
191
189
|
/** Last nonce used */
|
|
192
190
|
public lastNonce = 0;
|
|
193
191
|
|
|
194
|
-
// Solana-specific properties
|
|
195
|
-
/** Solana bridge client */
|
|
196
|
-
public bridgeClient?: SolanaBridgeClient;
|
|
197
|
-
|
|
198
192
|
/** Solana connection */
|
|
199
193
|
public connection: Connection;
|
|
200
194
|
|
|
@@ -207,46 +201,48 @@ export class NordUser {
|
|
|
207
201
|
* @param params - Parameters for creating a NordUser
|
|
208
202
|
* @throws {NordError} If required parameters are missing
|
|
209
203
|
*/
|
|
210
|
-
constructor(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
204
|
+
constructor({
|
|
205
|
+
address,
|
|
206
|
+
nord,
|
|
207
|
+
publicKey,
|
|
208
|
+
sessionPubKey,
|
|
209
|
+
sessionSignFn,
|
|
210
|
+
transactionSignFn,
|
|
211
|
+
walletSignFn,
|
|
212
|
+
connection,
|
|
213
|
+
sessionId,
|
|
214
|
+
}: NordUserParams) {
|
|
215
|
+
if (!walletSignFn) {
|
|
218
216
|
throw new NordError("Wallet sign function is required");
|
|
219
217
|
}
|
|
220
|
-
if (!
|
|
218
|
+
if (!sessionSignFn) {
|
|
221
219
|
throw new NordError("Session sign function is required");
|
|
222
220
|
}
|
|
223
|
-
if (!
|
|
221
|
+
if (!sessionPubKey) {
|
|
224
222
|
throw new NordError("Session public key is required");
|
|
225
223
|
}
|
|
226
224
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
this.
|
|
225
|
+
try {
|
|
226
|
+
this.address = new PublicKey(address);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
throw new NordError("Invalid Solana address", { cause: error });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.nord = nord;
|
|
232
|
+
this.walletSignFn = walletSignFn;
|
|
233
|
+
this.sessionSignFn = sessionSignFn;
|
|
234
|
+
this.transactionSignFn = transactionSignFn;
|
|
235
|
+
this.sessionPubKey = sessionPubKey;
|
|
236
|
+
this.publicKey = publicKey;
|
|
234
237
|
this.connection =
|
|
235
|
-
|
|
236
|
-
new Connection(
|
|
238
|
+
connection ||
|
|
239
|
+
new Connection(nord.solanaUrl, {
|
|
237
240
|
commitment: "confirmed",
|
|
238
241
|
});
|
|
239
242
|
|
|
240
243
|
// Set sessionId if provided
|
|
241
|
-
if (
|
|
242
|
-
this.sessionId =
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Initialize bridge client if needed
|
|
246
|
-
try {
|
|
247
|
-
this.initBridgeClient();
|
|
248
|
-
} catch (error) {
|
|
249
|
-
console.warn("Failed to initialize bridge client:", error);
|
|
244
|
+
if (sessionId !== undefined) {
|
|
245
|
+
this.sessionId = sessionId;
|
|
250
246
|
}
|
|
251
247
|
|
|
252
248
|
// Convert tokens from info endpoint to SPLTokenInfo
|
|
@@ -268,7 +264,7 @@ export class NordUser {
|
|
|
268
264
|
clone(): NordUser {
|
|
269
265
|
const cloned = new NordUser({
|
|
270
266
|
nord: this.nord,
|
|
271
|
-
address: this.address,
|
|
267
|
+
address: this.address.toBase58(),
|
|
272
268
|
walletSignFn: this.walletSignFn,
|
|
273
269
|
sessionSignFn: this.sessionSignFn,
|
|
274
270
|
transactionSignFn: this.transactionSignFn,
|
|
@@ -292,56 +288,6 @@ export class NordUser {
|
|
|
292
288
|
return cloned;
|
|
293
289
|
}
|
|
294
290
|
|
|
295
|
-
/**
|
|
296
|
-
* Initialize the Solana bridge client
|
|
297
|
-
*
|
|
298
|
-
* @private
|
|
299
|
-
* @throws {NordError} If required parameters are missing
|
|
300
|
-
*/
|
|
301
|
-
private initBridgeClient(): void {
|
|
302
|
-
if (
|
|
303
|
-
!this.getSolanaPublicKey() ||
|
|
304
|
-
!this.connection ||
|
|
305
|
-
!this.nord.getSolanaProgramId()
|
|
306
|
-
) {
|
|
307
|
-
throw new NordError(
|
|
308
|
-
"Solana public key, connection, and program ID are required to initialize bridge client",
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Create an Anchor wallet that uses walletSignFn for signing
|
|
313
|
-
const wallet: anchor.Wallet = {
|
|
314
|
-
publicKey: this.getSolanaPublicKey(),
|
|
315
|
-
signTransaction: async (tx: any) => {
|
|
316
|
-
return await this.transactionSignFn(tx);
|
|
317
|
-
},
|
|
318
|
-
signAllTransactions: async (txs: any[]) => {
|
|
319
|
-
return Promise.all(
|
|
320
|
-
txs.map(async (tx) => {
|
|
321
|
-
return await this.transactionSignFn(tx);
|
|
322
|
-
}),
|
|
323
|
-
);
|
|
324
|
-
},
|
|
325
|
-
// Create a keypair-like object with just the public key
|
|
326
|
-
payer: {
|
|
327
|
-
publicKey: this.getSolanaPublicKey(),
|
|
328
|
-
secretKey: new Uint8Array(64), // Dummy secret key to satisfy the type
|
|
329
|
-
} as Keypair,
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
// Initialize the bridge client
|
|
333
|
-
this.bridgeClient = new SolanaBridgeClient(
|
|
334
|
-
{
|
|
335
|
-
rpcUrl: this.connection.rpcEndpoint,
|
|
336
|
-
programId: this.nord.getSolanaProgramId(),
|
|
337
|
-
commitment: "confirmed",
|
|
338
|
-
tokenInfos: this.splTokenInfos,
|
|
339
|
-
bridgeVk: this.nord.bridgeVk,
|
|
340
|
-
},
|
|
341
|
-
wallet,
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
291
|
/**
|
|
346
292
|
* Create a NordUser from a private key
|
|
347
293
|
*
|
|
@@ -391,9 +337,9 @@ export class NordUser {
|
|
|
391
337
|
// Create a transaction signing function
|
|
392
338
|
const transactionSignFn = async (transaction: any): Promise<any> => {
|
|
393
339
|
// This is a basic implementation - actual implementation would depend on the transaction type
|
|
394
|
-
if (transaction.
|
|
340
|
+
if (transaction.sign) {
|
|
395
341
|
// Solana transaction
|
|
396
|
-
transaction.sign(
|
|
342
|
+
transaction.sign(keypair);
|
|
397
343
|
return transaction;
|
|
398
344
|
}
|
|
399
345
|
|
|
@@ -433,13 +379,31 @@ export class NordUser {
|
|
|
433
379
|
}
|
|
434
380
|
|
|
435
381
|
try {
|
|
436
|
-
|
|
382
|
+
// Get the token program ID from the mint account
|
|
383
|
+
const mintAccount = await this.connection.getAccountInfo(mint);
|
|
384
|
+
if (!mintAccount) {
|
|
385
|
+
throw new NordError("Mint account not found");
|
|
386
|
+
}
|
|
387
|
+
const tokenProgramId = mintAccount.owner;
|
|
388
|
+
|
|
389
|
+
// Validate that the mint is owned by a supported SPL token program
|
|
390
|
+
if (
|
|
391
|
+
!tokenProgramId.equals(TOKEN_PROGRAM_ID) &&
|
|
392
|
+
!tokenProgramId.equals(TOKEN_2022_PROGRAM_ID)
|
|
393
|
+
) {
|
|
394
|
+
throw new NordError(
|
|
395
|
+
"Mint Account is not owned by a supported SPL token program",
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const associatedTokenAddress = await getAssociatedTokenAddress(
|
|
437
400
|
mint,
|
|
438
401
|
this.getSolanaPublicKey(),
|
|
439
402
|
false,
|
|
440
|
-
|
|
403
|
+
tokenProgramId,
|
|
441
404
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
442
405
|
);
|
|
406
|
+
return associatedTokenAddress;
|
|
443
407
|
} catch (error) {
|
|
444
408
|
throw new NordError("Failed to get associated token account", {
|
|
445
409
|
cause: error,
|
|
@@ -456,12 +420,6 @@ export class NordUser {
|
|
|
456
420
|
* @throws {NordError} If required parameters are missing or operation fails
|
|
457
421
|
*/
|
|
458
422
|
async depositSpl(amount: number, tokenId: number): Promise<string> {
|
|
459
|
-
if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
|
|
460
|
-
throw new NordError(
|
|
461
|
-
"Bridge client, Solana public key, and connection are required for deposit",
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
423
|
try {
|
|
466
424
|
// Find the token info
|
|
467
425
|
const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === tokenId);
|
|
@@ -472,82 +430,43 @@ export class NordUser {
|
|
|
472
430
|
const mint = new PublicKey(tokenInfo.mint);
|
|
473
431
|
// Get the user's token account
|
|
474
432
|
const fromAccount = await this.getAssociatedTokenAccount(mint);
|
|
433
|
+
|
|
475
434
|
// Convert amount to BN with proper decimals
|
|
476
|
-
const amountBN =
|
|
435
|
+
const amountBN = floatToBn(amount, tokenInfo.precision);
|
|
477
436
|
|
|
478
|
-
//
|
|
479
|
-
|
|
437
|
+
// Create deposit parameters
|
|
438
|
+
const depositParams: DepositSplParams = {
|
|
480
439
|
amount: amountBN,
|
|
481
440
|
mint,
|
|
482
441
|
fromAccount,
|
|
483
|
-
}
|
|
484
|
-
} catch (error) {
|
|
485
|
-
throw new NordError(
|
|
486
|
-
`Failed to deposit ${amount} of token ID ${tokenId}`,
|
|
487
|
-
{ cause: error },
|
|
488
|
-
);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
442
|
+
};
|
|
491
443
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
* @throws {NordError} If required parameters are missing or operation fails
|
|
498
|
-
*/
|
|
499
|
-
async withdrawSpl(claim: any): Promise<string> {
|
|
500
|
-
if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
|
|
501
|
-
throw new NordError(
|
|
502
|
-
"Bridge client, Solana public key, and connection are required for withdrawal",
|
|
444
|
+
// Build the deposit transaction using proton client
|
|
445
|
+
const depositTx = await this.nord.protonClient.buildDepositTx(
|
|
446
|
+
depositParams,
|
|
447
|
+
this.getSolanaPublicKey(),
|
|
448
|
+
this.connection,
|
|
503
449
|
);
|
|
504
|
-
}
|
|
505
450
|
|
|
506
|
-
|
|
507
|
-
// Find the token info
|
|
508
|
-
const tokenInfo = this.splTokenInfos.find(
|
|
509
|
-
(t) => t.tokenId === claim.tokenId,
|
|
510
|
-
);
|
|
511
|
-
if (!tokenInfo) {
|
|
512
|
-
throw new NordError(`Token with ID ${claim.tokenId} not found`);
|
|
513
|
-
}
|
|
451
|
+
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
514
452
|
|
|
515
|
-
|
|
453
|
+
depositTx.recentBlockhash = blockhash;
|
|
454
|
+
depositTx.feePayer = this.getSolanaPublicKey();
|
|
516
455
|
|
|
517
|
-
|
|
518
|
-
const toAccount = await this.getAssociatedTokenAccount(mint);
|
|
456
|
+
const signedTx = await this.transactionSignFn(depositTx);
|
|
519
457
|
|
|
520
|
-
//
|
|
521
|
-
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
authority,
|
|
525
|
-
true,
|
|
526
|
-
TOKEN_2022_PROGRAM_ID,
|
|
458
|
+
// TODO: should use `VersionedTransaction` and remove any for `transactionSignFn`,
|
|
459
|
+
// this is incredibly annoying to debug and i could've saved 30 mins.
|
|
460
|
+
const signature = await this.connection.sendRawTransaction(
|
|
461
|
+
signedTx.serialize(),
|
|
527
462
|
);
|
|
528
463
|
|
|
529
|
-
|
|
530
|
-
const transactionSigner = {
|
|
531
|
-
publicKey: this.getSolanaPublicKey(),
|
|
532
|
-
secretKey: new Uint8Array(64), // Dummy secret key, not actually used
|
|
533
|
-
sign: async (tx: Transaction) => {
|
|
534
|
-
const message = tx.serializeMessage();
|
|
535
|
-
await this.walletSignFn(message);
|
|
536
|
-
return tx;
|
|
537
|
-
},
|
|
538
|
-
};
|
|
539
|
-
|
|
540
|
-
// Withdraw tokens
|
|
541
|
-
return await this.bridgeClient.withdraw(
|
|
542
|
-
{
|
|
543
|
-
claim,
|
|
544
|
-
fromAccount,
|
|
545
|
-
toAccount,
|
|
546
|
-
},
|
|
547
|
-
transactionSigner as unknown as Keypair, // Type cast to satisfy the API
|
|
548
|
-
);
|
|
464
|
+
return signature;
|
|
549
465
|
} catch (error) {
|
|
550
|
-
throw new NordError(
|
|
466
|
+
throw new NordError(
|
|
467
|
+
`Failed to deposit ${amount} of token ID ${tokenId}`,
|
|
468
|
+
{ cause: error },
|
|
469
|
+
);
|
|
551
470
|
}
|
|
552
471
|
}
|
|
553
472
|
|
|
@@ -747,10 +666,13 @@ export class NordUser {
|
|
|
747
666
|
* @param amount - Amount to withdraw
|
|
748
667
|
* @throws {NordError} If the operation fails
|
|
749
668
|
*/
|
|
750
|
-
async withdraw(
|
|
669
|
+
async withdraw(
|
|
670
|
+
tokenId: number,
|
|
671
|
+
amount: number,
|
|
672
|
+
): Promise<{ actionId: bigint }> {
|
|
751
673
|
try {
|
|
752
674
|
this.checkSessionValidity();
|
|
753
|
-
await withdraw(
|
|
675
|
+
const { actionId } = await withdraw(
|
|
754
676
|
this.nord.webServerUrl,
|
|
755
677
|
this.sessionSignFn,
|
|
756
678
|
await this.nord.getTimestamp(),
|
|
@@ -762,6 +684,7 @@ export class NordUser {
|
|
|
762
684
|
amount,
|
|
763
685
|
},
|
|
764
686
|
);
|
|
687
|
+
return { actionId };
|
|
765
688
|
} catch (error) {
|
|
766
689
|
throw new NordError(
|
|
767
690
|
`Failed to withdraw ${amount} of token ID ${tokenId}`,
|
|
@@ -813,7 +736,7 @@ export class NordUser {
|
|
|
813
736
|
* Cancel an order
|
|
814
737
|
*
|
|
815
738
|
* @param orderId - Order ID to cancel
|
|
816
|
-
* @param
|
|
739
|
+
* @param providedAccountId - Account ID that placed the order
|
|
817
740
|
* @returns Action ID if successful
|
|
818
741
|
* @throws {NordError} If the operation fails
|
|
819
742
|
*/
|
|
@@ -989,7 +912,7 @@ export class NordUser {
|
|
|
989
912
|
try {
|
|
990
913
|
const tokenBalance = await this.retryWithBackoff(
|
|
991
914
|
() =>
|
|
992
|
-
this.connection
|
|
915
|
+
this.connection.getTokenAccountBalance(
|
|
993
916
|
associatedTokenAddress,
|
|
994
917
|
),
|
|
995
918
|
maxRetries,
|
|
@@ -1035,10 +958,6 @@ export class NordUser {
|
|
|
1035
958
|
* @returns The Solana public key
|
|
1036
959
|
*/
|
|
1037
960
|
getSolanaPublicKey(): PublicKey {
|
|
1038
|
-
|
|
1039
|
-
return new PublicKey(this.address);
|
|
1040
|
-
} catch (error) {
|
|
1041
|
-
throw new NordError("Invalid Solana address", { cause: error });
|
|
1042
|
-
}
|
|
961
|
+
return this.address;
|
|
1043
962
|
}
|
|
1044
963
|
}
|
|
@@ -60,11 +60,15 @@ export class NordError extends Error {
|
|
|
60
60
|
let result = `${this.name}: ${this.message}`;
|
|
61
61
|
|
|
62
62
|
if (this.statusCode) {
|
|
63
|
-
result += `
|
|
63
|
+
result += ` \nstatus: ${this.statusCode}`;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
if (this.details && Object.keys(this.details).length > 0) {
|
|
67
|
-
result +=
|
|
67
|
+
result += ` \ndetails: ${JSON.stringify(this.details, null, 2)}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (this.cause) {
|
|
71
|
+
result += ` \ncause: ${this.cause.toString()}`;
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
return result;
|