@n1xyz/nord-ts 0.0.15 → 0.0.17
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/common.js +1 -1
- package/dist/gen/nord.d.ts +61 -29
- package/dist/gen/nord.js +723 -130
- package/dist/idl/bridge.d.ts +569 -2
- package/dist/idl/bridge.js +5 -927
- 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 +79 -151
- package/dist/nord/utils/NordError.js +5 -2
- package/dist/types.d.ts +34 -50
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +14 -0
- package/dist/websocket/NordWebSocketClient.js +0 -2
- package/package.json +20 -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 +107 -178
- package/src/nord/utils/NordError.ts +6 -2
- package/src/types.ts +34 -49
- package/src/utils.ts +18 -0
- package/src/websocket/NordWebSocketClient.ts +0 -2
- package/tsconfig.json +1 -1
- 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 -86
- 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 -9
- 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 -10
- 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 -10
- 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 -6723
- 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,15 +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
|
-
import * as
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
import {
|
|
9
|
+
import * as ed from "@noble/ed25519";
|
|
10
|
+
import { sha512 } from "@noble/hashes/sha512";
|
|
11
|
+
ed.etc.sha512Sync = sha512;
|
|
12
|
+
import { SPLTokenInfo, DepositSplParams } from "@n1xyz/proton";
|
|
13
13
|
import { FillMode, Order, Side } from "../../types";
|
|
14
14
|
import {
|
|
15
15
|
BigIntValue,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
findToken,
|
|
19
19
|
optExpect,
|
|
20
20
|
toBN as utilsToBN,
|
|
21
|
+
keypairFromPrivateKey,
|
|
21
22
|
} from "../../utils";
|
|
22
23
|
import {
|
|
23
24
|
cancelOrder,
|
|
@@ -119,7 +120,7 @@ export class NordUser {
|
|
|
119
120
|
public readonly nord: Nord;
|
|
120
121
|
|
|
121
122
|
/** User's blockchain address */
|
|
122
|
-
public readonly address:
|
|
123
|
+
public readonly address: PublicKey;
|
|
123
124
|
|
|
124
125
|
/** Function to sign messages with the user's wallet */
|
|
125
126
|
public readonly walletSignFn: (
|
|
@@ -189,10 +190,6 @@ export class NordUser {
|
|
|
189
190
|
/** Last nonce used */
|
|
190
191
|
public lastNonce = 0;
|
|
191
192
|
|
|
192
|
-
// Solana-specific properties
|
|
193
|
-
/** Solana bridge client */
|
|
194
|
-
public bridgeClient?: SolanaBridgeClient;
|
|
195
|
-
|
|
196
193
|
/** Solana connection */
|
|
197
194
|
public connection: Connection;
|
|
198
195
|
|
|
@@ -205,46 +202,48 @@ export class NordUser {
|
|
|
205
202
|
* @param params - Parameters for creating a NordUser
|
|
206
203
|
* @throws {NordError} If required parameters are missing
|
|
207
204
|
*/
|
|
208
|
-
constructor(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
205
|
+
constructor({
|
|
206
|
+
address,
|
|
207
|
+
nord,
|
|
208
|
+
publicKey,
|
|
209
|
+
sessionPubKey,
|
|
210
|
+
sessionSignFn,
|
|
211
|
+
transactionSignFn,
|
|
212
|
+
walletSignFn,
|
|
213
|
+
connection,
|
|
214
|
+
sessionId,
|
|
215
|
+
}: NordUserParams) {
|
|
216
|
+
if (!walletSignFn) {
|
|
216
217
|
throw new NordError("Wallet sign function is required");
|
|
217
218
|
}
|
|
218
|
-
if (!
|
|
219
|
+
if (!sessionSignFn) {
|
|
219
220
|
throw new NordError("Session sign function is required");
|
|
220
221
|
}
|
|
221
|
-
if (!
|
|
222
|
+
if (!sessionPubKey) {
|
|
222
223
|
throw new NordError("Session public key is required");
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
this.
|
|
226
|
+
try {
|
|
227
|
+
this.address = new PublicKey(address);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
throw new NordError("Invalid Solana address", { cause: error });
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
this.nord = nord;
|
|
233
|
+
this.walletSignFn = walletSignFn;
|
|
234
|
+
this.sessionSignFn = sessionSignFn;
|
|
235
|
+
this.transactionSignFn = transactionSignFn;
|
|
236
|
+
this.sessionPubKey = sessionPubKey;
|
|
237
|
+
this.publicKey = publicKey;
|
|
232
238
|
this.connection =
|
|
233
|
-
|
|
234
|
-
new Connection(
|
|
239
|
+
connection ||
|
|
240
|
+
new Connection(nord.solanaUrl, {
|
|
235
241
|
commitment: "confirmed",
|
|
236
242
|
});
|
|
237
243
|
|
|
238
244
|
// Set sessionId if provided
|
|
239
|
-
if (
|
|
240
|
-
this.sessionId =
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Initialize bridge client if needed
|
|
244
|
-
try {
|
|
245
|
-
this.initBridgeClient();
|
|
246
|
-
} catch (error) {
|
|
247
|
-
console.warn("Failed to initialize bridge client:", error);
|
|
245
|
+
if (sessionId !== undefined) {
|
|
246
|
+
this.sessionId = sessionId;
|
|
248
247
|
}
|
|
249
248
|
|
|
250
249
|
// Convert tokens from info endpoint to SPLTokenInfo
|
|
@@ -266,7 +265,7 @@ export class NordUser {
|
|
|
266
265
|
clone(): NordUser {
|
|
267
266
|
const cloned = new NordUser({
|
|
268
267
|
nord: this.nord,
|
|
269
|
-
address: this.address,
|
|
268
|
+
address: this.address.toBase58(),
|
|
270
269
|
walletSignFn: this.walletSignFn,
|
|
271
270
|
sessionSignFn: this.sessionSignFn,
|
|
272
271
|
transactionSignFn: this.transactionSignFn,
|
|
@@ -290,56 +289,6 @@ export class NordUser {
|
|
|
290
289
|
return cloned;
|
|
291
290
|
}
|
|
292
291
|
|
|
293
|
-
/**
|
|
294
|
-
* Initialize the Solana bridge client
|
|
295
|
-
*
|
|
296
|
-
* @private
|
|
297
|
-
* @throws {NordError} If required parameters are missing
|
|
298
|
-
*/
|
|
299
|
-
private initBridgeClient(): void {
|
|
300
|
-
if (
|
|
301
|
-
!this.getSolanaPublicKey() ||
|
|
302
|
-
!this.connection ||
|
|
303
|
-
!this.nord.getSolanaProgramId()
|
|
304
|
-
) {
|
|
305
|
-
throw new NordError(
|
|
306
|
-
"Solana public key, connection, and program ID are required to initialize bridge client",
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Create an Anchor wallet that uses walletSignFn for signing
|
|
311
|
-
const wallet: anchor.Wallet = {
|
|
312
|
-
publicKey: this.getSolanaPublicKey(),
|
|
313
|
-
signTransaction: async (tx: any) => {
|
|
314
|
-
return await this.transactionSignFn(tx);
|
|
315
|
-
},
|
|
316
|
-
signAllTransactions: async (txs: any[]) => {
|
|
317
|
-
return Promise.all(
|
|
318
|
-
txs.map(async (tx) => {
|
|
319
|
-
return await this.transactionSignFn(tx);
|
|
320
|
-
}),
|
|
321
|
-
);
|
|
322
|
-
},
|
|
323
|
-
// Create a keypair-like object with just the public key
|
|
324
|
-
payer: {
|
|
325
|
-
publicKey: this.getSolanaPublicKey(),
|
|
326
|
-
secretKey: new Uint8Array(64), // Dummy secret key to satisfy the type
|
|
327
|
-
} as Keypair,
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
// Initialize the bridge client
|
|
331
|
-
this.bridgeClient = new SolanaBridgeClient(
|
|
332
|
-
{
|
|
333
|
-
rpcUrl: this.connection.rpcEndpoint,
|
|
334
|
-
programId: this.nord.getSolanaProgramId(),
|
|
335
|
-
commitment: "confirmed",
|
|
336
|
-
tokenInfos: this.splTokenInfos,
|
|
337
|
-
bridgeVk: this.nord.bridgeVk,
|
|
338
|
-
},
|
|
339
|
-
wallet,
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
292
|
/**
|
|
344
293
|
* Create a NordUser from a private key
|
|
345
294
|
*
|
|
@@ -362,29 +311,36 @@ export class NordUser {
|
|
|
362
311
|
const walletSignFn = async (
|
|
363
312
|
message: Uint8Array | string,
|
|
364
313
|
): Promise<Uint8Array> => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
314
|
+
function toHex(buffer: Uint8Array) {
|
|
315
|
+
return Array.from(buffer)
|
|
316
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
317
|
+
.join("");
|
|
318
|
+
}
|
|
319
|
+
const messageBuffer = new TextEncoder().encode(
|
|
320
|
+
toHex(message as Uint8Array),
|
|
321
|
+
);
|
|
369
322
|
|
|
370
|
-
// Use
|
|
371
|
-
const signature =
|
|
323
|
+
// Use ed25519 to sign the message
|
|
324
|
+
const signature = ed.sign(
|
|
325
|
+
messageBuffer,
|
|
326
|
+
keypair.secretKey.slice(0, 32),
|
|
327
|
+
);
|
|
372
328
|
return signature;
|
|
373
329
|
};
|
|
374
330
|
|
|
375
331
|
const sessionSignFn = async (
|
|
376
332
|
message: Uint8Array,
|
|
377
333
|
): Promise<Uint8Array> => {
|
|
378
|
-
// Use
|
|
379
|
-
return
|
|
334
|
+
// Use ed25519 to sign the message
|
|
335
|
+
return ed.sign(message, keypair.secretKey.slice(0, 32));
|
|
380
336
|
};
|
|
381
337
|
|
|
382
338
|
// Create a transaction signing function
|
|
383
339
|
const transactionSignFn = async (transaction: any): Promise<any> => {
|
|
384
340
|
// This is a basic implementation - actual implementation would depend on the transaction type
|
|
385
|
-
if (transaction.
|
|
341
|
+
if (transaction.sign) {
|
|
386
342
|
// Solana transaction
|
|
387
|
-
transaction.sign(
|
|
343
|
+
transaction.sign(keypair);
|
|
388
344
|
return transaction;
|
|
389
345
|
}
|
|
390
346
|
|
|
@@ -424,13 +380,31 @@ export class NordUser {
|
|
|
424
380
|
}
|
|
425
381
|
|
|
426
382
|
try {
|
|
427
|
-
|
|
383
|
+
// Get the token program ID from the mint account
|
|
384
|
+
const mintAccount = await this.connection.getAccountInfo(mint);
|
|
385
|
+
if (!mintAccount) {
|
|
386
|
+
throw new NordError("Mint account not found");
|
|
387
|
+
}
|
|
388
|
+
const tokenProgramId = mintAccount.owner;
|
|
389
|
+
|
|
390
|
+
// Validate that the mint is owned by a supported SPL token program
|
|
391
|
+
if (
|
|
392
|
+
!tokenProgramId.equals(TOKEN_PROGRAM_ID) &&
|
|
393
|
+
!tokenProgramId.equals(TOKEN_2022_PROGRAM_ID)
|
|
394
|
+
) {
|
|
395
|
+
throw new NordError(
|
|
396
|
+
"Mint Account is not owned by a supported SPL token program",
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const associatedTokenAddress = await getAssociatedTokenAddress(
|
|
428
401
|
mint,
|
|
429
402
|
this.getSolanaPublicKey(),
|
|
430
403
|
false,
|
|
431
|
-
|
|
404
|
+
tokenProgramId,
|
|
432
405
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
433
406
|
);
|
|
407
|
+
return associatedTokenAddress;
|
|
434
408
|
} catch (error) {
|
|
435
409
|
throw new NordError("Failed to get associated token account", {
|
|
436
410
|
cause: error,
|
|
@@ -447,12 +421,6 @@ export class NordUser {
|
|
|
447
421
|
* @throws {NordError} If required parameters are missing or operation fails
|
|
448
422
|
*/
|
|
449
423
|
async depositSpl(amount: number, tokenId: number): Promise<string> {
|
|
450
|
-
if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
|
|
451
|
-
throw new NordError(
|
|
452
|
-
"Bridge client, Solana public key, and connection are required for deposit",
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
424
|
try {
|
|
457
425
|
// Find the token info
|
|
458
426
|
const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === tokenId);
|
|
@@ -463,82 +431,43 @@ export class NordUser {
|
|
|
463
431
|
const mint = new PublicKey(tokenInfo.mint);
|
|
464
432
|
// Get the user's token account
|
|
465
433
|
const fromAccount = await this.getAssociatedTokenAccount(mint);
|
|
434
|
+
|
|
466
435
|
// Convert amount to BN with proper decimals
|
|
467
436
|
const amountBN = utilsToBN(amount, tokenInfo.precision);
|
|
468
437
|
|
|
469
|
-
//
|
|
470
|
-
|
|
438
|
+
// Create deposit parameters
|
|
439
|
+
const depositParams: DepositSplParams = {
|
|
471
440
|
amount: amountBN,
|
|
472
441
|
mint,
|
|
473
442
|
fromAccount,
|
|
474
|
-
}
|
|
475
|
-
} catch (error) {
|
|
476
|
-
throw new NordError(
|
|
477
|
-
`Failed to deposit ${amount} of token ID ${tokenId}`,
|
|
478
|
-
{ cause: error },
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
443
|
+
};
|
|
482
444
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
* @throws {NordError} If required parameters are missing or operation fails
|
|
489
|
-
*/
|
|
490
|
-
async withdrawSpl(claim: any): Promise<string> {
|
|
491
|
-
if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
|
|
492
|
-
throw new NordError(
|
|
493
|
-
"Bridge client, Solana public key, and connection are required for withdrawal",
|
|
445
|
+
// Build the deposit transaction using proton client
|
|
446
|
+
const depositTx = await this.nord.protonClient.buildDepositTx(
|
|
447
|
+
depositParams,
|
|
448
|
+
this.getSolanaPublicKey(),
|
|
449
|
+
this.connection,
|
|
494
450
|
);
|
|
495
|
-
}
|
|
496
451
|
|
|
497
|
-
|
|
498
|
-
// Find the token info
|
|
499
|
-
const tokenInfo = this.splTokenInfos.find(
|
|
500
|
-
(t) => t.tokenId === claim.tokenId,
|
|
501
|
-
);
|
|
502
|
-
if (!tokenInfo) {
|
|
503
|
-
throw new NordError(`Token with ID ${claim.tokenId} not found`);
|
|
504
|
-
}
|
|
452
|
+
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
505
453
|
|
|
506
|
-
|
|
454
|
+
depositTx.recentBlockhash = blockhash;
|
|
455
|
+
depositTx.feePayer = this.getSolanaPublicKey();
|
|
507
456
|
|
|
508
|
-
|
|
509
|
-
const toAccount = await this.getAssociatedTokenAccount(mint);
|
|
457
|
+
const signedTx = await this.transactionSignFn(depositTx);
|
|
510
458
|
|
|
511
|
-
//
|
|
512
|
-
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
authority,
|
|
516
|
-
true,
|
|
517
|
-
TOKEN_2022_PROGRAM_ID,
|
|
459
|
+
// TODO: should use `VersionedTransaction` and remove any for `transactionSignFn`,
|
|
460
|
+
// this is incredibly annoying to debug and i could've saved 30 mins.
|
|
461
|
+
const signature = await this.connection.sendRawTransaction(
|
|
462
|
+
signedTx.serialize(),
|
|
518
463
|
);
|
|
519
464
|
|
|
520
|
-
|
|
521
|
-
const transactionSigner = {
|
|
522
|
-
publicKey: this.getSolanaPublicKey(),
|
|
523
|
-
secretKey: new Uint8Array(64), // Dummy secret key, not actually used
|
|
524
|
-
sign: async (tx: Transaction) => {
|
|
525
|
-
const message = tx.serializeMessage();
|
|
526
|
-
await this.walletSignFn(message);
|
|
527
|
-
return tx;
|
|
528
|
-
},
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
// Withdraw tokens
|
|
532
|
-
return await this.bridgeClient.withdraw(
|
|
533
|
-
{
|
|
534
|
-
claim,
|
|
535
|
-
fromAccount,
|
|
536
|
-
toAccount,
|
|
537
|
-
},
|
|
538
|
-
transactionSigner as unknown as Keypair, // Type cast to satisfy the API
|
|
539
|
-
);
|
|
465
|
+
return signature;
|
|
540
466
|
} catch (error) {
|
|
541
|
-
throw new NordError(
|
|
467
|
+
throw new NordError(
|
|
468
|
+
`Failed to deposit ${amount} of token ID ${tokenId}`,
|
|
469
|
+
{ cause: error },
|
|
470
|
+
);
|
|
542
471
|
}
|
|
543
472
|
}
|
|
544
473
|
|
|
@@ -738,10 +667,13 @@ export class NordUser {
|
|
|
738
667
|
* @param amount - Amount to withdraw
|
|
739
668
|
* @throws {NordError} If the operation fails
|
|
740
669
|
*/
|
|
741
|
-
async withdraw(
|
|
670
|
+
async withdraw(
|
|
671
|
+
tokenId: number,
|
|
672
|
+
amount: number,
|
|
673
|
+
): Promise<{ actionId: bigint }> {
|
|
742
674
|
try {
|
|
743
675
|
this.checkSessionValidity();
|
|
744
|
-
await withdraw(
|
|
676
|
+
const { actionId } = await withdraw(
|
|
745
677
|
this.nord.webServerUrl,
|
|
746
678
|
this.sessionSignFn,
|
|
747
679
|
await this.nord.getTimestamp(),
|
|
@@ -753,6 +685,7 @@ export class NordUser {
|
|
|
753
685
|
amount,
|
|
754
686
|
},
|
|
755
687
|
);
|
|
688
|
+
return { actionId };
|
|
756
689
|
} catch (error) {
|
|
757
690
|
throw new NordError(
|
|
758
691
|
`Failed to withdraw ${amount} of token ID ${tokenId}`,
|
|
@@ -804,7 +737,7 @@ export class NordUser {
|
|
|
804
737
|
* Cancel an order
|
|
805
738
|
*
|
|
806
739
|
* @param orderId - Order ID to cancel
|
|
807
|
-
* @param
|
|
740
|
+
* @param providedAccountId - Account ID that placed the order
|
|
808
741
|
* @returns Action ID if successful
|
|
809
742
|
* @throws {NordError} If the operation fails
|
|
810
743
|
*/
|
|
@@ -980,7 +913,7 @@ export class NordUser {
|
|
|
980
913
|
try {
|
|
981
914
|
const tokenBalance = await this.retryWithBackoff(
|
|
982
915
|
() =>
|
|
983
|
-
this.connection
|
|
916
|
+
this.connection.getTokenAccountBalance(
|
|
984
917
|
associatedTokenAddress,
|
|
985
918
|
),
|
|
986
919
|
maxRetries,
|
|
@@ -1026,10 +959,6 @@ export class NordUser {
|
|
|
1026
959
|
* @returns The Solana public key
|
|
1027
960
|
*/
|
|
1028
961
|
getSolanaPublicKey(): PublicKey {
|
|
1029
|
-
|
|
1030
|
-
return new PublicKey(this.address);
|
|
1031
|
-
} catch (error) {
|
|
1032
|
-
throw new NordError("Invalid Solana address", { cause: error });
|
|
1033
|
-
}
|
|
962
|
+
return this.address;
|
|
1034
963
|
}
|
|
1035
964
|
}
|
|
@@ -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;
|