@bluefin-exchange/pro-sdk 0.1.12 → 0.1.13
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/example.js +17 -9
- package/dist/src/request-signer.d.ts +10 -75
- package/dist/src/request-signer.js +75 -109
- package/dist/src/sdk.d.ts +11 -2
- package/dist/src/sdk.js +97 -12
- package/example.ts +27 -9
- package/package.json +3 -2
- package/src/request-signer.ts +143 -159
- package/src/sdk.ts +134 -17
package/dist/example.js
CHANGED
|
@@ -13,6 +13,8 @@ const index_1 = require("./index");
|
|
|
13
13
|
const ed25519_1 = require("@mysten/sui/keypairs/ed25519");
|
|
14
14
|
const index_2 = require("./index");
|
|
15
15
|
const index_3 = require("./index");
|
|
16
|
+
const utils_1 = require("@noble/hashes/utils");
|
|
17
|
+
const library_sui_1 = require("@firefly-exchange/library-sui");
|
|
16
18
|
// Configure logging
|
|
17
19
|
const logger = {
|
|
18
20
|
info: (message) => console.log(new Date().toISOString(), "-", message),
|
|
@@ -77,21 +79,27 @@ function handleAccountDataEvent(msg) {
|
|
|
77
79
|
function main() {
|
|
78
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
79
81
|
// Create wallet from mnemonic
|
|
80
|
-
const suiWallet =
|
|
81
|
-
// "dilemma salmon lake ceiling moral glide cute that ginger float area aunt vague remind cage mother concert inch dizzy present proud program time urge",
|
|
82
|
-
"know puzzle puzzle table miss member token image loop velvet skin legend clarify affair wisdom alert lucky unveil mean two question nice spatial grape"
|
|
82
|
+
// const suiWallet = Ed25519Keypair.deriveKeypair(
|
|
83
|
+
// // "dilemma salmon lake ceiling moral glide cute that ginger float area aunt vague remind cage mother concert inch dizzy present proud program time urge",
|
|
84
|
+
// "know puzzle puzzle table miss member token image loop velvet skin legend clarify affair wisdom alert lucky unveil mean two question nice spatial grape"
|
|
85
|
+
// );
|
|
86
|
+
const suiWallet = ed25519_1.Ed25519Keypair.fromSecretKey((0, utils_1.hexToBytes)("3427d19dcf5781f0874c36c78aec22c03acda435d69efcbf249e8821793567a1"));
|
|
83
87
|
logger.info(`Sui Address: ${suiWallet.getPublicKey().toSuiAddress()}`);
|
|
84
88
|
const bfSigner = new index_3.BluefinRequestSigner((0, index_3.makeAddressableKeyPair)(suiWallet));
|
|
85
|
-
const client = new index_2.BluefinProSdk(bfSigner, "devnet",
|
|
89
|
+
const client = new index_2.BluefinProSdk(bfSigner, "devnet", new library_sui_1.SuiClient({ url: "https://fullnode.testnet.sui.io:443" }));
|
|
86
90
|
yield client.initialize();
|
|
87
91
|
try {
|
|
92
|
+
yield client.deposit("1000");
|
|
88
93
|
// Get Market Data from Exchange Data API
|
|
89
94
|
const exchangeInfo = (yield client.exchangeDataApi.getExchangeInfo()).data;
|
|
90
95
|
logger.info(`Exchange Info: ${JSON.stringify(exchangeInfo)}`);
|
|
91
|
-
//
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
// Find SUI-PERP market
|
|
97
|
+
const perpMarket = exchangeInfo.markets.find((m) => m.symbol === "SUI-PERP");
|
|
98
|
+
if (!perpMarket) {
|
|
99
|
+
throw new Error("SUI-PERP market not found");
|
|
100
|
+
}
|
|
101
|
+
logger.info(`Selected market: ${JSON.stringify(perpMarket)}`);
|
|
102
|
+
const symbol = perpMarket.symbol;
|
|
95
103
|
// Get market data
|
|
96
104
|
const candleStick = (yield client.exchangeDataApi.getCandlestickData(symbol, index_1.KlineInterval._1m, index_1.CandlePriceType.Oracle)).data;
|
|
97
105
|
logger.info(`Candle stick: ${JSON.stringify(candleStick)}`);
|
|
@@ -154,7 +162,7 @@ function main() {
|
|
|
154
162
|
side: index_1.OrderSide.Long,
|
|
155
163
|
leverageE9: "1000000000",
|
|
156
164
|
isIsolated: false,
|
|
157
|
-
expiresAtUtcMillis: Date.now() +
|
|
165
|
+
expiresAtUtcMillis: Date.now() + 6 * 60 * 1000,
|
|
158
166
|
postOnly: false,
|
|
159
167
|
reduceOnly: false,
|
|
160
168
|
timeInForce: index_1.OrderTimeInForce.Gtt,
|
|
@@ -1,84 +1,18 @@
|
|
|
1
1
|
import { Keypair, Signer } from "@mysten/sui/cryptography";
|
|
2
|
-
import { LoginRequest,
|
|
2
|
+
import { LoginRequest, AccountPositionLeverageUpdateRequestSignedFields, CreateOrderRequestSignedFields, WithdrawRequestSignedFields } from "./api";
|
|
3
|
+
import { DryRunTransactionBlockResponse, SuiClient, SuiTransactionBlockResponse, TransactionBlock } from "@firefly-exchange/library-sui";
|
|
3
4
|
export interface IBluefinSigner {
|
|
4
5
|
getAddress(): string;
|
|
5
|
-
signLeverageUpdateRequest: (fields: AccountPositionLeverageUpdateRequestSignedFields) => Promise<
|
|
6
|
-
signOrderRequest: (fields: CreateOrderRequestSignedFields) => Promise<
|
|
7
|
-
signWithdrawRequest: (fields: WithdrawRequestSignedFields) => Promise<
|
|
6
|
+
signLeverageUpdateRequest: (fields: AccountPositionLeverageUpdateRequestSignedFields) => Promise<string>;
|
|
7
|
+
signOrderRequest: (fields: CreateOrderRequestSignedFields) => Promise<string>;
|
|
8
|
+
signWithdrawRequest: (fields: WithdrawRequestSignedFields) => Promise<string>;
|
|
8
9
|
signLoginRequest: (request: LoginRequest) => Promise<string>;
|
|
10
|
+
executeTx: (txb: TransactionBlock, suiClient: SuiClient) => Promise<DryRunTransactionBlockResponse | SuiTransactionBlockResponse>;
|
|
9
11
|
}
|
|
10
12
|
export interface IAddressable {
|
|
11
13
|
getAddress(): string;
|
|
12
14
|
}
|
|
13
15
|
export declare function makeAddressableKeyPair<T extends Keypair>(keyPair: T): T & IAddressable;
|
|
14
|
-
export declare const OrderRequestSignedFieldsBCS: import("@mysten/sui/bcs").BcsType<{
|
|
15
|
-
symbol: string;
|
|
16
|
-
accountAddress: string;
|
|
17
|
-
priceE9: string;
|
|
18
|
-
quantityE9: string;
|
|
19
|
-
leverageE9: string;
|
|
20
|
-
side: string;
|
|
21
|
-
isIsolated: boolean;
|
|
22
|
-
expiresAtUtcMillis: string;
|
|
23
|
-
salt: string;
|
|
24
|
-
idsId: string;
|
|
25
|
-
signedAtUtcMillis: string;
|
|
26
|
-
}, {
|
|
27
|
-
symbol: string;
|
|
28
|
-
accountAddress: string | Uint8Array<ArrayBufferLike>;
|
|
29
|
-
priceE9: string | number | bigint;
|
|
30
|
-
quantityE9: string | number | bigint;
|
|
31
|
-
leverageE9: string | number | bigint;
|
|
32
|
-
side: string;
|
|
33
|
-
isIsolated: boolean;
|
|
34
|
-
expiresAtUtcMillis: string | number | bigint;
|
|
35
|
-
salt: string | number | bigint;
|
|
36
|
-
idsId: string | Uint8Array<ArrayBufferLike>;
|
|
37
|
-
signedAtUtcMillis: string | number | bigint;
|
|
38
|
-
}>;
|
|
39
|
-
export declare const LeverageUpdateRequestSignedFieldsBCS: import("@mysten/sui/bcs").BcsType<{
|
|
40
|
-
accountAddress: string;
|
|
41
|
-
symbol: string;
|
|
42
|
-
leverageE9: string;
|
|
43
|
-
salt: string;
|
|
44
|
-
idsId: string;
|
|
45
|
-
signedAtUtcMillis: string;
|
|
46
|
-
}, {
|
|
47
|
-
accountAddress: string | Uint8Array<ArrayBufferLike>;
|
|
48
|
-
symbol: string;
|
|
49
|
-
leverageE9: string | number | bigint;
|
|
50
|
-
salt: string | number | bigint;
|
|
51
|
-
idsId: string | Uint8Array<ArrayBufferLike>;
|
|
52
|
-
signedAtUtcMillis: string | number | bigint;
|
|
53
|
-
}>;
|
|
54
|
-
export declare const WithdrawRequestSignedFieldsBCS: import("@mysten/sui/bcs").BcsType<{
|
|
55
|
-
assetSymbol: string;
|
|
56
|
-
accountAddress: string;
|
|
57
|
-
amountE9: string;
|
|
58
|
-
salt: string;
|
|
59
|
-
edsId: string;
|
|
60
|
-
signedAtUtcMillis: string;
|
|
61
|
-
}, {
|
|
62
|
-
assetSymbol: string;
|
|
63
|
-
accountAddress: string | Uint8Array<ArrayBufferLike>;
|
|
64
|
-
amountE9: string | number | bigint;
|
|
65
|
-
salt: string | number | bigint;
|
|
66
|
-
edsId: string | Uint8Array<ArrayBufferLike>;
|
|
67
|
-
signedAtUtcMillis: string | number | bigint;
|
|
68
|
-
}>;
|
|
69
|
-
export declare const SerializedSignatureBCS: import("@mysten/sui/bcs").BcsType<{
|
|
70
|
-
signature: number[];
|
|
71
|
-
publicKey: number[];
|
|
72
|
-
scheme: number;
|
|
73
|
-
}, {
|
|
74
|
-
signature: Iterable<number> & {
|
|
75
|
-
length: number;
|
|
76
|
-
};
|
|
77
|
-
publicKey: Iterable<number> & {
|
|
78
|
-
length: number;
|
|
79
|
-
};
|
|
80
|
-
scheme: number;
|
|
81
|
-
}>;
|
|
82
16
|
export declare class BluefinRequestSigner implements IBluefinSigner {
|
|
83
17
|
private readonly wallet;
|
|
84
18
|
constructor(wallet: Pick<Signer, "signPersonalMessage"> & IAddressable);
|
|
@@ -89,15 +23,16 @@ export declare class BluefinRequestSigner implements IBluefinSigner {
|
|
|
89
23
|
/**
|
|
90
24
|
* Sign an order request
|
|
91
25
|
*/
|
|
92
|
-
signOrderRequest(
|
|
26
|
+
signOrderRequest(signedFields: CreateOrderRequestSignedFields): Promise<string>;
|
|
93
27
|
/**
|
|
94
28
|
* Sign a withdraw request
|
|
95
29
|
*/
|
|
96
|
-
signWithdrawRequest(withdrawRequestSignedFields: WithdrawRequestSignedFields): Promise<
|
|
30
|
+
signWithdrawRequest(withdrawRequestSignedFields: WithdrawRequestSignedFields): Promise<string>;
|
|
97
31
|
/**
|
|
98
32
|
* Sign a leverage update request
|
|
99
33
|
*/
|
|
100
|
-
signLeverageUpdateRequest(
|
|
34
|
+
signLeverageUpdateRequest(signedFields: AccountPositionLeverageUpdateRequestSignedFields): Promise<string>;
|
|
35
|
+
executeTx(txb: TransactionBlock, suiClient: SuiClient): Promise<DryRunTransactionBlockResponse | SuiTransactionBlockResponse>;
|
|
101
36
|
/**
|
|
102
37
|
* Get the wallet's address
|
|
103
38
|
*/
|
|
@@ -9,50 +9,72 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.BluefinRequestSigner =
|
|
12
|
+
exports.BluefinRequestSigner = void 0;
|
|
13
13
|
exports.makeAddressableKeyPair = makeAddressableKeyPair;
|
|
14
|
-
const crypto = require("crypto");
|
|
15
14
|
const cryptography_1 = require("@mysten/sui/cryptography");
|
|
16
|
-
const
|
|
15
|
+
const library_sui_1 = require("@firefly-exchange/library-sui");
|
|
17
16
|
function makeAddressableKeyPair(keyPair) {
|
|
18
17
|
return Object.assign(keyPair, {
|
|
19
18
|
getAddress: () => keyPair.getPublicKey().toSuiAddress(),
|
|
20
19
|
});
|
|
21
20
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
21
|
+
// ------- ISerializables ---------
|
|
22
|
+
// Enums
|
|
23
|
+
var ClientPayloadType;
|
|
24
|
+
(function (ClientPayloadType) {
|
|
25
|
+
ClientPayloadType["WithdrawRequest"] = "Bluefin Pro Withdrawal";
|
|
26
|
+
ClientPayloadType["OrderRequest"] = "Bluefin Pro Order";
|
|
27
|
+
ClientPayloadType["LeverageAdjustment"] = "Bluefin Pro Leverage Adjustment";
|
|
28
|
+
})(ClientPayloadType || (ClientPayloadType = {}));
|
|
29
|
+
var PositionType;
|
|
30
|
+
(function (PositionType) {
|
|
31
|
+
PositionType["Isolated"] = "ISOLATED";
|
|
32
|
+
PositionType["Cross"] = "CROSS";
|
|
33
|
+
})(PositionType || (PositionType = {}));
|
|
34
|
+
// Conversion functions
|
|
35
|
+
function toUIWithdrawRequest(val) {
|
|
36
|
+
return {
|
|
37
|
+
type: ClientPayloadType.WithdrawRequest,
|
|
38
|
+
eds: val.edsId,
|
|
39
|
+
assetSymbol: val.assetSymbol,
|
|
40
|
+
account: val.accountAddress,
|
|
41
|
+
amount: val.amountE9,
|
|
42
|
+
salt: val.salt,
|
|
43
|
+
signedAt: val.signedAtUtcMillis.toString(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function toUICreateOrderRequest(val) {
|
|
47
|
+
return {
|
|
48
|
+
type: ClientPayloadType.OrderRequest,
|
|
49
|
+
ids: val.idsId,
|
|
50
|
+
account: val.accountAddress,
|
|
51
|
+
market: val.symbol,
|
|
52
|
+
price: val.priceE9,
|
|
53
|
+
quantity: val.quantityE9,
|
|
54
|
+
leverage: val.leverageE9,
|
|
55
|
+
side: val.side.toString(),
|
|
56
|
+
positionType: val.isIsolated ? PositionType.Isolated : PositionType.Cross,
|
|
57
|
+
expiration: val.expiresAtUtcMillis.toString(),
|
|
58
|
+
salt: val.salt,
|
|
59
|
+
signedAt: val.signedAtUtcMillis.toString(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function toUIUpdateAccountPositionLeverageRequest(val) {
|
|
63
|
+
return {
|
|
64
|
+
type: ClientPayloadType.LeverageAdjustment,
|
|
65
|
+
ids: val.idsId,
|
|
66
|
+
account: val.accountAddress,
|
|
67
|
+
market: val.symbol,
|
|
68
|
+
leverage: val.leverageE9,
|
|
69
|
+
salt: val.salt,
|
|
70
|
+
signedAt: val.signedAtUtcMillis.toString(),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// ---------- Utils ----------
|
|
74
|
+
function toJson(val) {
|
|
75
|
+
return JSON.stringify(val, null, 2);
|
|
76
|
+
}
|
|
77
|
+
// --------------------------------
|
|
56
78
|
class BluefinRequestSigner {
|
|
57
79
|
constructor(wallet) {
|
|
58
80
|
this.wallet = wallet;
|
|
@@ -70,36 +92,15 @@ class BluefinRequestSigner {
|
|
|
70
92
|
/**
|
|
71
93
|
* Sign an order request
|
|
72
94
|
*/
|
|
73
|
-
signOrderRequest(
|
|
95
|
+
signOrderRequest(signedFields) {
|
|
74
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
accountAddress: orderRequestSignedFields.accountAddress,
|
|
78
|
-
priceE9: orderRequestSignedFields.priceE9,
|
|
79
|
-
quantityE9: orderRequestSignedFields.quantityE9,
|
|
80
|
-
leverageE9: orderRequestSignedFields.leverageE9,
|
|
81
|
-
side: orderRequestSignedFields.side,
|
|
82
|
-
isIsolated: orderRequestSignedFields.isIsolated,
|
|
83
|
-
expiresAtUtcMillis: orderRequestSignedFields.expiresAtUtcMillis,
|
|
84
|
-
salt: orderRequestSignedFields.salt,
|
|
85
|
-
idsId: orderRequestSignedFields.idsId,
|
|
86
|
-
signedAtUtcMillis: orderRequestSignedFields.signedAtUtcMillis,
|
|
87
|
-
};
|
|
88
|
-
const orderBytes = exports.OrderRequestSignedFieldsBCS.serialize(signableFields).toBytes();
|
|
89
|
-
const digest = yield (global.crypto ? global.crypto : crypto).subtle.digest("SHA-256", orderBytes);
|
|
90
|
-
const walletHack = this.wallet;
|
|
91
|
-
const signedMessageSerialized = yield this.wallet.signPersonalMessage(orderBytes);
|
|
92
|
-
const signedMessage = yield walletHack.sign(Buffer.from(digest));
|
|
97
|
+
const orderJson = toJson(toUICreateOrderRequest(signedFields));
|
|
98
|
+
const signedMessageSerialized = yield this.wallet.signPersonalMessage(new TextEncoder().encode(orderJson));
|
|
93
99
|
const parsedSignature = (0, cryptography_1.parseSerializedSignature)(signedMessageSerialized.signature);
|
|
94
100
|
if (parsedSignature.signatureScheme == "MultiSig") {
|
|
95
101
|
throw new Error("MultiSig not supported");
|
|
96
102
|
}
|
|
97
|
-
|
|
98
|
-
signature: signedMessage,
|
|
99
|
-
publicKey: parsedSignature.publicKey,
|
|
100
|
-
scheme: cryptography_1.SIGNATURE_SCHEME_TO_FLAG[parsedSignature.signatureScheme],
|
|
101
|
-
}).toHex();
|
|
102
|
-
return [signature, Buffer.from(digest).toString("hex")];
|
|
103
|
+
return signedMessageSerialized.signature;
|
|
103
104
|
});
|
|
104
105
|
}
|
|
105
106
|
/**
|
|
@@ -107,67 +108,32 @@ class BluefinRequestSigner {
|
|
|
107
108
|
*/
|
|
108
109
|
signWithdrawRequest(withdrawRequestSignedFields) {
|
|
109
110
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
accountAddress: withdrawRequestSignedFields.accountAddress,
|
|
113
|
-
amountE9: withdrawRequestSignedFields.amountE9,
|
|
114
|
-
salt: withdrawRequestSignedFields.salt,
|
|
115
|
-
edsId: withdrawRequestSignedFields.edsId,
|
|
116
|
-
signedAtUtcMillis: withdrawRequestSignedFields.signedAtUtcMillis,
|
|
117
|
-
};
|
|
118
|
-
const requestBytes = exports.WithdrawRequestSignedFieldsBCS.serialize(signableFields).toBytes();
|
|
119
|
-
const digest = yield (global.crypto ? global.crypto : crypto).subtle.digest("SHA-256", requestBytes);
|
|
120
|
-
const walletHack = this.wallet;
|
|
121
|
-
const signedMessageSerialized = yield this.wallet.signPersonalMessage(requestBytes);
|
|
122
|
-
const signedMessage = yield walletHack.sign(Buffer.from(digest));
|
|
111
|
+
const requestJson = toJson(toUIWithdrawRequest(withdrawRequestSignedFields));
|
|
112
|
+
const signedMessageSerialized = yield this.wallet.signPersonalMessage(new TextEncoder().encode(requestJson));
|
|
123
113
|
const parsedSignature = (0, cryptography_1.parseSerializedSignature)(signedMessageSerialized.signature);
|
|
124
114
|
if (parsedSignature.signatureScheme == "MultiSig") {
|
|
125
115
|
throw new Error("MultiSig not supported");
|
|
126
116
|
}
|
|
127
|
-
|
|
128
|
-
signature: signedMessage,
|
|
129
|
-
publicKey: parsedSignature.publicKey,
|
|
130
|
-
scheme: cryptography_1.SIGNATURE_SCHEME_TO_FLAG[parsedSignature.signatureScheme],
|
|
131
|
-
}).toHex();
|
|
132
|
-
return {
|
|
133
|
-
signature,
|
|
134
|
-
requestHash: Buffer.from(digest).toString("hex"),
|
|
135
|
-
signedFields: withdrawRequestSignedFields,
|
|
136
|
-
};
|
|
117
|
+
return signedMessageSerialized.signature;
|
|
137
118
|
});
|
|
138
119
|
}
|
|
139
120
|
/**
|
|
140
121
|
* Sign a leverage update request
|
|
141
122
|
*/
|
|
142
|
-
signLeverageUpdateRequest(
|
|
123
|
+
signLeverageUpdateRequest(signedFields) {
|
|
143
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
accountAddress: requestSignedFields.accountAddress,
|
|
147
|
-
leverageE9: requestSignedFields.leverageE9,
|
|
148
|
-
salt: requestSignedFields.salt,
|
|
149
|
-
idsId: requestSignedFields.idsId,
|
|
150
|
-
signedAtUtcMillis: requestSignedFields.signedAtUtcMillis,
|
|
151
|
-
};
|
|
152
|
-
const requestBytes = exports.LeverageUpdateRequestSignedFieldsBCS.serialize(signableFields).toBytes();
|
|
153
|
-
const digest = yield (global.crypto ? global.crypto : crypto).subtle.digest("SHA-256", requestBytes);
|
|
154
|
-
const walletHack = this.wallet;
|
|
155
|
-
const signedMessageSerialized = yield this.wallet.signPersonalMessage(requestBytes);
|
|
156
|
-
const signedMessage = yield walletHack.sign(Buffer.from(digest));
|
|
125
|
+
const requestJson = toJson(toUIUpdateAccountPositionLeverageRequest(signedFields));
|
|
126
|
+
const signedMessageSerialized = yield this.wallet.signPersonalMessage(new TextEncoder().encode(requestJson));
|
|
157
127
|
const parsedSignature = (0, cryptography_1.parseSerializedSignature)(signedMessageSerialized.signature);
|
|
158
128
|
if (parsedSignature.signatureScheme == "MultiSig") {
|
|
159
129
|
throw new Error("MultiSig not supported");
|
|
160
130
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return
|
|
167
|
-
signature,
|
|
168
|
-
requestHash: Buffer.from(digest).toString("hex"),
|
|
169
|
-
signedFields: requestSignedFields,
|
|
170
|
-
};
|
|
131
|
+
return signedMessageSerialized.signature;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
executeTx(txb, suiClient) {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
return library_sui_1.SuiBlocks.execCall(txb, suiClient, this.wallet, false);
|
|
171
137
|
});
|
|
172
138
|
}
|
|
173
139
|
/**
|
package/dist/src/sdk.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OrderType, OrderTimeInForce, SelfTradePreventionType, OrderSide, CancelOrdersRequest, AccountDataApi, ExchangeApi, MarketStreamMessage, AccountStreamMessage } from "./api";
|
|
2
2
|
import { IBluefinSigner } from "./request-signer";
|
|
3
3
|
import { WebSocket } from "ws";
|
|
4
|
+
import { SuiClient } from "@firefly-exchange/library-sui";
|
|
4
5
|
export interface OrderParams {
|
|
5
6
|
clientOrderId: string;
|
|
6
7
|
type: OrderType;
|
|
@@ -21,9 +22,13 @@ type BasePathConfig = {
|
|
|
21
22
|
authHost: string | null;
|
|
22
23
|
apiHost: string | null;
|
|
23
24
|
tradeHost: string | null;
|
|
25
|
+
marketWsHost: string | null;
|
|
26
|
+
accountWsHost: string | null;
|
|
24
27
|
};
|
|
25
28
|
export declare class BluefinProSdk {
|
|
26
29
|
private readonly bfSigner;
|
|
30
|
+
private environment;
|
|
31
|
+
private suiClient;
|
|
27
32
|
private currentAccountAddress;
|
|
28
33
|
private readonly configs;
|
|
29
34
|
readonly exchangeDataApi: ExchangeApi;
|
|
@@ -35,18 +40,22 @@ export declare class BluefinProSdk {
|
|
|
35
40
|
private isConnected;
|
|
36
41
|
private updateTokenInterval;
|
|
37
42
|
private contractsConfig;
|
|
38
|
-
|
|
43
|
+
private assets;
|
|
44
|
+
private txBuilder;
|
|
45
|
+
constructor(bfSigner: IBluefinSigner, environment: "mainnet" | "testnet" | "devnet" | undefined, suiClient: SuiClient, currentAccountAddress?: string | null, basePathConfig?: BasePathConfig | null);
|
|
39
46
|
private generateSalt;
|
|
47
|
+
private initializeTxBuilder;
|
|
40
48
|
initialize(): Promise<void>;
|
|
41
49
|
private setContractsConfig;
|
|
42
50
|
private loginAndUpdateToken;
|
|
43
51
|
private login;
|
|
44
52
|
getAccessToken(): Promise<string>;
|
|
45
|
-
getOpenOrders(symbol
|
|
53
|
+
getOpenOrders(symbol?: string): Promise<import("axios").AxiosResponse<import("./api").OpenOrderResponse[], any>>;
|
|
46
54
|
updateLeverage(symbol: string, leverageE9: string): Promise<import("axios").AxiosResponse<void, any>>;
|
|
47
55
|
createOrder(params: OrderParams): Promise<any>;
|
|
48
56
|
cancelOrder(cancelOrdersRequest: CancelOrdersRequest): Promise<import("axios").AxiosResponse<void, any>>;
|
|
49
57
|
withdraw(assetSymbol: string, amountE9: string): Promise<void>;
|
|
58
|
+
deposit(amountE9: string, accountAddress?: string): Promise<import("@firefly-exchange/library-sui").DryRunTransactionBlockResponse | import("@firefly-exchange/library-sui").SuiTransactionBlockResponse>;
|
|
50
59
|
private setAccessToken;
|
|
51
60
|
private refreshToken;
|
|
52
61
|
createAccountDataStreamListener(handler: (data: AccountStreamMessage) => Promise<void>): Promise<WebSocket>;
|
package/dist/src/sdk.js
CHANGED
|
@@ -13,21 +13,29 @@ exports.BluefinProSdk = void 0;
|
|
|
13
13
|
const api_1 = require("./api");
|
|
14
14
|
const configuration_1 = require("./configuration");
|
|
15
15
|
const ws_1 = require("ws");
|
|
16
|
+
const v3_1 = require("@firefly-exchange/library-sui/dist/src/v3");
|
|
17
|
+
const library_sui_1 = require("@firefly-exchange/library-sui");
|
|
16
18
|
const environmentConfig = {
|
|
17
19
|
mainnet: {
|
|
18
20
|
authHost: "https://auth.api.sui-prod.bluefin.io",
|
|
19
21
|
apiHost: "https://api.sui-prod.bluefin.io",
|
|
20
22
|
tradeHost: "https://trade.api.sui-prod.bluefin.io",
|
|
23
|
+
marketWsHost: "wss://stream.api.sui-prod.bluefin.io/ws/market",
|
|
24
|
+
accountWsHost: "wss://stream.api.sui-prod.bluefin.io/ws/account",
|
|
21
25
|
},
|
|
22
26
|
testnet: {
|
|
23
27
|
authHost: "https://auth.api.sui-staging.bluefin.io",
|
|
24
28
|
apiHost: "https://api.sui-staging.bluefin.io",
|
|
25
29
|
tradeHost: "https://trade.api.sui-staging.bluefin.io",
|
|
30
|
+
marketWsHost: "wss://stream.api.sui-staging.bluefin.io/ws/market",
|
|
31
|
+
accountWsHost: "wss://stream.api.sui-staging.bluefin.io/ws/account",
|
|
26
32
|
},
|
|
27
33
|
devnet: {
|
|
28
34
|
authHost: "https://auth.api.sui-dev.bluefin.io",
|
|
29
35
|
apiHost: "https://api.sui-dev.bluefin.io",
|
|
30
36
|
tradeHost: "https://trade.api.sui-dev.bluefin.io",
|
|
37
|
+
marketWsHost: "wss://stream.api.sui-dev.bluefin.io/ws/market",
|
|
38
|
+
accountWsHost: "wss://stream.api.sui-dev.bluefin.io/ws/account",
|
|
31
39
|
},
|
|
32
40
|
};
|
|
33
41
|
var Services;
|
|
@@ -36,10 +44,14 @@ var Services;
|
|
|
36
44
|
Services[Services["Exchange"] = 1] = "Exchange";
|
|
37
45
|
Services[Services["Trade"] = 2] = "Trade";
|
|
38
46
|
Services[Services["Auth"] = 3] = "Auth";
|
|
47
|
+
Services[Services["MarketWebsocket"] = 4] = "MarketWebsocket";
|
|
48
|
+
Services[Services["AccountWebsocket"] = 5] = "AccountWebsocket";
|
|
39
49
|
})(Services || (Services = {}));
|
|
40
50
|
class BluefinProSdk {
|
|
41
|
-
constructor(bfSigner, environment = "mainnet", currentAccountAddress = null, basePathConfig = null) {
|
|
51
|
+
constructor(bfSigner, environment = "mainnet", suiClient, currentAccountAddress = null, basePathConfig = null) {
|
|
42
52
|
this.bfSigner = bfSigner;
|
|
53
|
+
this.environment = environment;
|
|
54
|
+
this.suiClient = suiClient;
|
|
43
55
|
this.currentAccountAddress = currentAccountAddress;
|
|
44
56
|
this.configs = {};
|
|
45
57
|
this.isConnected = false;
|
|
@@ -50,13 +62,19 @@ class BluefinProSdk {
|
|
|
50
62
|
const basePaths = {
|
|
51
63
|
authHost: basePathConfig && (basePathConfig === null || basePathConfig === void 0 ? void 0 : basePathConfig.authHost)
|
|
52
64
|
? basePathConfig.authHost
|
|
53
|
-
: environmentConfig[environment].authHost,
|
|
65
|
+
: environmentConfig[this.environment].authHost,
|
|
54
66
|
apiHost: basePathConfig && (basePathConfig === null || basePathConfig === void 0 ? void 0 : basePathConfig.apiHost)
|
|
55
67
|
? basePathConfig.apiHost
|
|
56
|
-
: environmentConfig[environment].apiHost,
|
|
68
|
+
: environmentConfig[this.environment].apiHost,
|
|
57
69
|
tradeHost: basePathConfig && (basePathConfig === null || basePathConfig === void 0 ? void 0 : basePathConfig.tradeHost)
|
|
58
70
|
? basePathConfig.tradeHost
|
|
59
|
-
: environmentConfig[environment].tradeHost,
|
|
71
|
+
: environmentConfig[this.environment].tradeHost,
|
|
72
|
+
marketWsHost: basePathConfig && (basePathConfig === null || basePathConfig === void 0 ? void 0 : basePathConfig.marketWsHost)
|
|
73
|
+
? basePathConfig.marketWsHost
|
|
74
|
+
: environmentConfig[this.environment].marketWsHost,
|
|
75
|
+
accountWsHost: basePathConfig && (basePathConfig === null || basePathConfig === void 0 ? void 0 : basePathConfig.accountWsHost)
|
|
76
|
+
? basePathConfig.accountWsHost
|
|
77
|
+
: environmentConfig[this.environment].accountWsHost,
|
|
60
78
|
};
|
|
61
79
|
const authApiConfig = new configuration_1.Configuration({
|
|
62
80
|
basePath: basePaths.authHost,
|
|
@@ -78,13 +96,47 @@ class BluefinProSdk {
|
|
|
78
96
|
});
|
|
79
97
|
this.configs[Services.Trade] = tradeApiConfig;
|
|
80
98
|
this.tradeApi = new api_1.TradeApi(tradeApiConfig);
|
|
99
|
+
const marketWsConfig = new configuration_1.Configuration({
|
|
100
|
+
basePath: basePaths.marketWsHost,
|
|
101
|
+
});
|
|
102
|
+
this.configs[Services.MarketWebsocket] = marketWsConfig;
|
|
103
|
+
const accountWsConfig = new configuration_1.Configuration({
|
|
104
|
+
basePath: basePaths.accountWsHost,
|
|
105
|
+
});
|
|
106
|
+
this.configs[Services.AccountWebsocket] = accountWsConfig;
|
|
81
107
|
}
|
|
82
108
|
generateSalt() {
|
|
83
109
|
return (Date.now() + Math.floor(Math.random() * 1000000)).toString();
|
|
84
110
|
}
|
|
111
|
+
initializeTxBuilder() {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
114
|
+
this.txBuilder = new v3_1.TxBuilder({
|
|
115
|
+
AdminCap: "",
|
|
116
|
+
ExternalDataStore: ((_a = this.contractsConfig) === null || _a === void 0 ? void 0 : _a.edsId) || "",
|
|
117
|
+
InternalDataStore: ((_b = this.contractsConfig) === null || _b === void 0 ? void 0 : _b.idsId) || "",
|
|
118
|
+
Operators: {
|
|
119
|
+
admin: ((_c = this.contractsConfig) === null || _c === void 0 ? void 0 : _c.operators.admin) || "",
|
|
120
|
+
fee: ((_d = this.contractsConfig) === null || _d === void 0 ? void 0 : _d.operators.fee) || "",
|
|
121
|
+
funding: ((_e = this.contractsConfig) === null || _e === void 0 ? void 0 : _e.operators.funding) || "",
|
|
122
|
+
pruning: "",
|
|
123
|
+
sequencer: ((_f = this.contractsConfig) === null || _f === void 0 ? void 0 : _f.operators.sequencer) || "",
|
|
124
|
+
},
|
|
125
|
+
Package: ((_g = this.contractsConfig) === null || _g === void 0 ? void 0 : _g.currentContractAddress) || "",
|
|
126
|
+
Perpetuals: {},
|
|
127
|
+
SupportedAssets: ((_h = this.assets) === null || _h === void 0 ? void 0 : _h.reduce((agg, x) => {
|
|
128
|
+
agg[x.symbol] = Object.assign(Object.assign({}, x), { coinType: x.assetType });
|
|
129
|
+
return agg;
|
|
130
|
+
}, {})) || {},
|
|
131
|
+
TreasuryCap: "",
|
|
132
|
+
UpgradeCap: "",
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
85
136
|
initialize() {
|
|
86
137
|
return __awaiter(this, void 0, void 0, function* () {
|
|
87
138
|
yield this.setContractsConfig();
|
|
139
|
+
yield this.initializeTxBuilder();
|
|
88
140
|
yield this.loginAndUpdateToken();
|
|
89
141
|
this.updateTokenInterval = setInterval(() => this.refreshToken(), 10000);
|
|
90
142
|
this.isConnected = true;
|
|
@@ -94,6 +146,7 @@ class BluefinProSdk {
|
|
|
94
146
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
147
|
const response = yield this.exchangeDataApi.getExchangeInfo();
|
|
96
148
|
this.contractsConfig = response.data.contractsConfig;
|
|
149
|
+
this.assets = response.data.assets;
|
|
97
150
|
});
|
|
98
151
|
}
|
|
99
152
|
loginAndUpdateToken() {
|
|
@@ -162,7 +215,11 @@ class BluefinProSdk {
|
|
|
162
215
|
signedAtUtcMillis: Date.now(),
|
|
163
216
|
};
|
|
164
217
|
const request = yield this.bfSigner.signLeverageUpdateRequest(signedFields);
|
|
165
|
-
return yield this.tradeApi.putLeverageUpdate(
|
|
218
|
+
return yield this.tradeApi.putLeverageUpdate({
|
|
219
|
+
signedFields,
|
|
220
|
+
signature: request,
|
|
221
|
+
requestHash: "",
|
|
222
|
+
});
|
|
166
223
|
});
|
|
167
224
|
}
|
|
168
225
|
createOrder(params) {
|
|
@@ -184,11 +241,11 @@ class BluefinProSdk {
|
|
|
184
241
|
expiresAtUtcMillis: params.expiresAtUtcMillis,
|
|
185
242
|
signedAtUtcMillis: Date.now(),
|
|
186
243
|
};
|
|
187
|
-
const
|
|
244
|
+
const signature = yield this.bfSigner.signOrderRequest(signedFields);
|
|
188
245
|
const createOrderRequest = {
|
|
189
246
|
signedFields,
|
|
190
247
|
signature,
|
|
191
|
-
orderHash,
|
|
248
|
+
orderHash: "",
|
|
192
249
|
clientOrderId: params.clientOrderId,
|
|
193
250
|
type: params.type,
|
|
194
251
|
reduceOnly: (_a = params.reduceOnly) !== null && _a !== void 0 ? _a : false,
|
|
@@ -224,9 +281,37 @@ class BluefinProSdk {
|
|
|
224
281
|
salt: this.generateSalt(),
|
|
225
282
|
signedAtUtcMillis: Date.now(),
|
|
226
283
|
};
|
|
227
|
-
const
|
|
228
|
-
yield this.tradeApi.postWithdraw(
|
|
229
|
-
|
|
284
|
+
const signature = yield this.bfSigner.signWithdrawRequest(signedFields);
|
|
285
|
+
yield this.tradeApi.postWithdraw({
|
|
286
|
+
signedFields,
|
|
287
|
+
signature,
|
|
288
|
+
requestHash: "",
|
|
289
|
+
});
|
|
290
|
+
console.log("Withdraw request sent:", signedFields);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
deposit(amountE9, accountAddress) {
|
|
294
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
295
|
+
var _a, _b, _c;
|
|
296
|
+
const assetSymbol = "USDC";
|
|
297
|
+
const txb = new library_sui_1.TransactionBlock();
|
|
298
|
+
const assetType = (_b = (_a = this.assets) === null || _a === void 0 ? void 0 : _a.find((x) => x.symbol === assetSymbol)) === null || _b === void 0 ? void 0 : _b.assetType;
|
|
299
|
+
if (!assetType) {
|
|
300
|
+
throw new Error("Missing USDC asset type");
|
|
301
|
+
}
|
|
302
|
+
const [splitCoin, mergedCoin] = yield library_sui_1.CoinUtils.createCoinWithBalance(this.suiClient, txb, amountE9, assetType, this.currentAccountAddress || this.bfSigner.getAddress());
|
|
303
|
+
(_c = this.txBuilder) === null || _c === void 0 ? void 0 : _c.depositToAssetBank(assetSymbol, accountAddress ||
|
|
304
|
+
this.currentAccountAddress ||
|
|
305
|
+
this.bfSigner.getAddress(), amountE9, splitCoin, {
|
|
306
|
+
txBlock: txb,
|
|
307
|
+
});
|
|
308
|
+
if (mergedCoin) {
|
|
309
|
+
txb.transferObjects([mergedCoin], this.currentAccountAddress || this.bfSigner.getAddress());
|
|
310
|
+
}
|
|
311
|
+
if (splitCoin) {
|
|
312
|
+
txb.transferObjects([splitCoin], this.currentAccountAddress || this.bfSigner.getAddress());
|
|
313
|
+
}
|
|
314
|
+
return this.bfSigner.executeTx(txb, this.suiClient);
|
|
230
315
|
});
|
|
231
316
|
}
|
|
232
317
|
setAccessToken() {
|
|
@@ -261,7 +346,7 @@ class BluefinProSdk {
|
|
|
261
346
|
if (!this.tokenResponse) {
|
|
262
347
|
throw new Error("Missing tokenResponse");
|
|
263
348
|
}
|
|
264
|
-
const ws = new ws_1.WebSocket(
|
|
349
|
+
const ws = new ws_1.WebSocket(this.configs[Services.AccountWebsocket].basePath, {
|
|
265
350
|
headers: {
|
|
266
351
|
Authorization: `Bearer ${this.tokenResponse.accessToken}`,
|
|
267
352
|
},
|
|
@@ -278,7 +363,7 @@ class BluefinProSdk {
|
|
|
278
363
|
createMarketDataStreamListener(handler) {
|
|
279
364
|
return __awaiter(this, void 0, void 0, function* () {
|
|
280
365
|
return new Promise((resolve, reject) => {
|
|
281
|
-
const ws = new ws_1.WebSocket(
|
|
366
|
+
const ws = new ws_1.WebSocket(this.configs[Services.MarketWebsocket].basePath);
|
|
282
367
|
ws.onmessage = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
283
368
|
yield handler(JSON.parse(event.data));
|
|
284
369
|
});
|