@nightlylabs/dex-sdk 0.0.24 → 0.0.25
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/index.cjs +233 -16
- package/dist/index.d.cts +93 -4
- package/dist/index.d.ts +93 -4
- package/dist/index.js +234 -16
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -50,12 +50,15 @@ __export(index_exports, {
|
|
|
50
50
|
getRandomId: () => getRandomId,
|
|
51
51
|
getTopicFromCommand: () => getTopicFromCommand,
|
|
52
52
|
getTopicFromMessage: () => getTopicFromMessage,
|
|
53
|
+
nowInMiliseconds: () => nowInMiliseconds,
|
|
54
|
+
parseEntryFunctionAbi: () => parseEntryFunctionAbi,
|
|
53
55
|
sleep: () => sleep,
|
|
54
56
|
toSystemValue: () => toSystemValue
|
|
55
57
|
});
|
|
56
58
|
module.exports = __toCommonJS(index_exports);
|
|
57
59
|
|
|
58
60
|
// src/client.ts
|
|
61
|
+
var import_ts_sdk2 = require("@aptos-labs/ts-sdk");
|
|
59
62
|
var import_surf = require("@thalalabs/surf");
|
|
60
63
|
var import_isomorphic_ws = __toESM(require("isomorphic-ws"), 1);
|
|
61
64
|
var import_uuid = require("uuid");
|
|
@@ -513,6 +516,7 @@ var GLOBAL_DENOMINATOR = 1e8;
|
|
|
513
516
|
// src/utils.ts
|
|
514
517
|
var import_decimal = require("decimal.js");
|
|
515
518
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
519
|
+
var nowInMiliseconds = () => Date.now();
|
|
516
520
|
var toSystemValue = (value) => {
|
|
517
521
|
return new import_decimal.Decimal(value).mul(new import_decimal.Decimal(GLOBAL_DENOMINATOR)).toString();
|
|
518
522
|
};
|
|
@@ -580,6 +584,184 @@ var getTopicFromMessage = (data) => {
|
|
|
580
584
|
}
|
|
581
585
|
};
|
|
582
586
|
|
|
587
|
+
// src/sequenceNumberManager.ts
|
|
588
|
+
var AccountSequenceNumber = class {
|
|
589
|
+
/**
|
|
590
|
+
* Creates an instance of AccountSequenceNumber.
|
|
591
|
+
*
|
|
592
|
+
* @param aptos - The Aptos client instance
|
|
593
|
+
* @param account - The account associated with transactions
|
|
594
|
+
* @param options - Configuration options
|
|
595
|
+
*/
|
|
596
|
+
constructor(aptos, account, options = {}) {
|
|
597
|
+
// Sequence number on chain
|
|
598
|
+
this.lastCommittedNumber = null;
|
|
599
|
+
// Local sequence number (next to be used)
|
|
600
|
+
this.currentNumber = null;
|
|
601
|
+
// Use a proper mutex implementation instead of a boolean flag
|
|
602
|
+
this.isLocked = false;
|
|
603
|
+
this.lockQueue = [];
|
|
604
|
+
this._aptos = aptos;
|
|
605
|
+
this.account = account;
|
|
606
|
+
this.maxWaitTime = options.maxWaitTime ?? 1e4;
|
|
607
|
+
this.maximumInFlight = options.maximumInFlight ?? 100;
|
|
608
|
+
this.sleepTime = options.sleepTime ?? 10;
|
|
609
|
+
this.warningTime = options.warningTime ?? 3e4;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Acquires the lock for synchronized access.
|
|
613
|
+
*/
|
|
614
|
+
async acquireLock() {
|
|
615
|
+
if (!this.isLocked) {
|
|
616
|
+
this.isLocked = true;
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
return new Promise((resolve) => {
|
|
620
|
+
this.lockQueue.push(resolve);
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Releases the lock and processes the next queued operation if any.
|
|
625
|
+
*/
|
|
626
|
+
releaseLock() {
|
|
627
|
+
if (this.lockQueue.length > 0) {
|
|
628
|
+
const nextResolve = this.lockQueue.shift();
|
|
629
|
+
if (nextResolve) {
|
|
630
|
+
nextResolve();
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
this.isLocked = false;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Returns the next available sequence number for this account.
|
|
638
|
+
*
|
|
639
|
+
* @returns The next available sequence number or null if an error occurs
|
|
640
|
+
*/
|
|
641
|
+
async nextSequenceNumber() {
|
|
642
|
+
await this.acquireLock();
|
|
643
|
+
try {
|
|
644
|
+
if (this.lastCommittedNumber === null || this.currentNumber === null) {
|
|
645
|
+
await this.initialize();
|
|
646
|
+
}
|
|
647
|
+
if (this.currentNumber - this.lastCommittedNumber >= this.maximumInFlight) {
|
|
648
|
+
await this.waitForCommit();
|
|
649
|
+
}
|
|
650
|
+
const nextNumber = this.currentNumber;
|
|
651
|
+
this.currentNumber = this.currentNumber + BigInt(1);
|
|
652
|
+
return nextNumber;
|
|
653
|
+
} catch (e) {
|
|
654
|
+
console.error("Error getting next sequence number:", e);
|
|
655
|
+
return null;
|
|
656
|
+
} finally {
|
|
657
|
+
this.releaseLock();
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Waits for pending transactions to be committed.
|
|
662
|
+
*/
|
|
663
|
+
async waitForCommit() {
|
|
664
|
+
await this.update();
|
|
665
|
+
const startTime = nowInMiliseconds();
|
|
666
|
+
while (this.currentNumber - this.lastCommittedNumber >= this.maximumInFlight) {
|
|
667
|
+
const elapsed = nowInMiliseconds() - startTime;
|
|
668
|
+
if (elapsed > this.maxWaitTime) {
|
|
669
|
+
console.warn(
|
|
670
|
+
`Waited over ${this.maxWaitTime / 1e3} seconds for a transaction to commit, re-syncing ${this.account.accountAddress.toString()}`
|
|
671
|
+
);
|
|
672
|
+
await this.initialize();
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
if (elapsed > this.warningTime && elapsed % 5e3 < this.sleepTime) {
|
|
676
|
+
console.warn(
|
|
677
|
+
`Still waiting for transactions to commit after ${elapsed / 1e3} seconds for account ${this.account.accountAddress.toString()}`
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
await sleep(this.sleepTime);
|
|
681
|
+
await this.update();
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Initializes this account with the sequence number on chain.
|
|
686
|
+
*/
|
|
687
|
+
async initialize() {
|
|
688
|
+
const sequenceNumber = await this.getSequenceNumber();
|
|
689
|
+
this.currentNumber = sequenceNumber;
|
|
690
|
+
this.lastCommittedNumber = sequenceNumber;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Updates this account's sequence number with the one on-chain.
|
|
694
|
+
*
|
|
695
|
+
* @returns The on-chain sequence number for this account.
|
|
696
|
+
*/
|
|
697
|
+
async update() {
|
|
698
|
+
const sequenceNumber = await this.getSequenceNumber();
|
|
699
|
+
this.lastCommittedNumber = sequenceNumber;
|
|
700
|
+
return this.lastCommittedNumber;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Synchronizes the local sequence number with the sequence number on-chain.
|
|
704
|
+
* This method waits until all submitted transactions have been committed.
|
|
705
|
+
*/
|
|
706
|
+
async synchronize() {
|
|
707
|
+
if (this.lastCommittedNumber === this.currentNumber) return;
|
|
708
|
+
await this.acquireLock();
|
|
709
|
+
try {
|
|
710
|
+
await this.update();
|
|
711
|
+
const startTime = nowInMiliseconds();
|
|
712
|
+
while (this.lastCommittedNumber !== this.currentNumber) {
|
|
713
|
+
const elapsed = nowInMiliseconds() - startTime;
|
|
714
|
+
if (elapsed > this.maxWaitTime) {
|
|
715
|
+
console.warn(
|
|
716
|
+
`Waited over ${this.maxWaitTime / 1e3} seconds for all transactions to commit, re-syncing ${this.account.accountAddress.toString()}`
|
|
717
|
+
);
|
|
718
|
+
await this.initialize();
|
|
719
|
+
break;
|
|
720
|
+
}
|
|
721
|
+
await sleep(this.sleepTime);
|
|
722
|
+
await this.update();
|
|
723
|
+
}
|
|
724
|
+
} catch (e) {
|
|
725
|
+
console.error("Error synchronizing account sequence number:", e);
|
|
726
|
+
} finally {
|
|
727
|
+
this.releaseLock();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Gets the current sequence number from the blockchain.
|
|
732
|
+
*
|
|
733
|
+
* @returns The current sequence number
|
|
734
|
+
* @throws If unable to retrieve the account information
|
|
735
|
+
*/
|
|
736
|
+
async getSequenceNumber() {
|
|
737
|
+
try {
|
|
738
|
+
const accInfo = await this._aptos.getAccountInfo({
|
|
739
|
+
accountAddress: this.account.accountAddress
|
|
740
|
+
});
|
|
741
|
+
return BigInt(accInfo.sequence_number);
|
|
742
|
+
} catch (error) {
|
|
743
|
+
console.error(
|
|
744
|
+
`Failed to get sequence number for ${this.account.accountAddress.toString()}:`,
|
|
745
|
+
error
|
|
746
|
+
);
|
|
747
|
+
throw error;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Returns information about the current state.
|
|
752
|
+
* Useful for debugging and monitoring.
|
|
753
|
+
*/
|
|
754
|
+
getStatus() {
|
|
755
|
+
return {
|
|
756
|
+
pendingTransactions: this.currentNumber !== null && this.lastCommittedNumber !== null ? this.currentNumber - this.lastCommittedNumber : BigInt(0),
|
|
757
|
+
currentNumber: this.currentNumber,
|
|
758
|
+
lastCommittedNumber: this.lastCommittedNumber,
|
|
759
|
+
isLocked: this.isLocked,
|
|
760
|
+
queuedOperations: this.lockQueue.length
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
|
|
583
765
|
// src/client.ts
|
|
584
766
|
var getRandomId = () => (0, import_uuid.v4)();
|
|
585
767
|
var Client = class _Client {
|
|
@@ -753,6 +935,7 @@ var Client = class _Client {
|
|
|
753
935
|
this._apiKey = apiKey || generateApiKey();
|
|
754
936
|
this._subscriptions = /* @__PURE__ */ new Map();
|
|
755
937
|
this._serverUrl = url;
|
|
938
|
+
this._sequenceNumberManager = new AccountSequenceNumber(this._aptos, this._apiKey);
|
|
756
939
|
this._ws = ws;
|
|
757
940
|
if (this._ws) {
|
|
758
941
|
this._ws.onmessage = async (msg) => {
|
|
@@ -823,12 +1006,11 @@ var Client = class _Client {
|
|
|
823
1006
|
async setApiKey(apiKey) {
|
|
824
1007
|
this._apiKey = apiKey;
|
|
825
1008
|
this._apiKeySequenceNumber = await this.fetchApiKeySequenceNumber();
|
|
1009
|
+
this._sequenceNumberManager = new AccountSequenceNumber(this._aptos, this._apiKey);
|
|
1010
|
+
await this._sequenceNumberManager.initialize();
|
|
826
1011
|
}
|
|
827
1012
|
getApiKeySequenceNumber() {
|
|
828
|
-
return this.
|
|
829
|
-
}
|
|
830
|
-
incrementSequenceNumber() {
|
|
831
|
-
this._apiKeySequenceNumber++;
|
|
1013
|
+
return this._sequenceNumberManager.getSequenceNumber();
|
|
832
1014
|
}
|
|
833
1015
|
async fetchApiKeySequenceNumber() {
|
|
834
1016
|
const accInfo = await this._aptos.getAccountInfo({
|
|
@@ -960,7 +1142,7 @@ var Client = class _Client {
|
|
|
960
1142
|
return await this.submitSponsoredTransaction(tx, signature);
|
|
961
1143
|
}
|
|
962
1144
|
async placePerpLimitOrder(params) {
|
|
963
|
-
console.log("start"
|
|
1145
|
+
console.log("start");
|
|
964
1146
|
const payload = (0, import_surf.createEntryPayload)(placePerpLimitOrder_default, {
|
|
965
1147
|
function: "place_perp_limit_order",
|
|
966
1148
|
functionArguments: [
|
|
@@ -973,22 +1155,35 @@ var Client = class _Client {
|
|
|
973
1155
|
],
|
|
974
1156
|
typeArguments: []
|
|
975
1157
|
});
|
|
976
|
-
console.log("
|
|
1158
|
+
console.log("get sequence number");
|
|
1159
|
+
const sequenceNumber = await this.getApiKeySequenceNumber();
|
|
1160
|
+
console.log("sequence number", sequenceNumber);
|
|
977
1161
|
const tx = await this._aptos.transaction.build.simple({
|
|
978
1162
|
sender: this._apiKey.accountAddress,
|
|
979
|
-
data:
|
|
1163
|
+
data: {
|
|
1164
|
+
...payload,
|
|
1165
|
+
abi: parseEntryFunctionAbi({
|
|
1166
|
+
moduleAbi: placePerpLimitOrder_default,
|
|
1167
|
+
functionName: "place_perp_limit_order",
|
|
1168
|
+
moduleAddress: "0x88dd5fbd381db9ad1566c8bbaec39a3d98906b3983a74bcafba70a09ae8f58f6",
|
|
1169
|
+
moduleName: "place_perp_limit_order"
|
|
1170
|
+
})
|
|
1171
|
+
},
|
|
980
1172
|
withFeePayer: true,
|
|
981
1173
|
options: {
|
|
982
|
-
accountSequenceNumber:
|
|
1174
|
+
accountSequenceNumber: sequenceNumber,
|
|
1175
|
+
// Now + 10 sec
|
|
1176
|
+
expireTimestamp: Date.now() + 10 * 1e3,
|
|
1177
|
+
gasUnitPrice: 100,
|
|
1178
|
+
maxGasAmount: 1e4
|
|
983
1179
|
}
|
|
984
1180
|
});
|
|
985
|
-
|
|
986
|
-
console.log("tx", (/* @__PURE__ */ new Date()).getMilliseconds());
|
|
1181
|
+
console.log("after build");
|
|
987
1182
|
const signature = this._aptos.sign({
|
|
988
1183
|
signer: this._apiKey,
|
|
989
1184
|
transaction: tx
|
|
990
1185
|
});
|
|
991
|
-
console.log("
|
|
1186
|
+
console.log("after sign");
|
|
992
1187
|
return await this.submitSponsoredTransaction(tx, signature);
|
|
993
1188
|
}
|
|
994
1189
|
async placePerpMarketOrder(params) {
|
|
@@ -1006,12 +1201,8 @@ var Client = class _Client {
|
|
|
1006
1201
|
const tx = await this._aptos.transaction.build.simple({
|
|
1007
1202
|
sender: this._apiKey.accountAddress,
|
|
1008
1203
|
data: payload,
|
|
1009
|
-
withFeePayer: true
|
|
1010
|
-
options: {
|
|
1011
|
-
accountSequenceNumber: this.getApiKeySequenceNumber()
|
|
1012
|
-
}
|
|
1204
|
+
withFeePayer: true
|
|
1013
1205
|
});
|
|
1014
|
-
this.incrementSequenceNumber();
|
|
1015
1206
|
const signature = this._aptos.sign({
|
|
1016
1207
|
signer: this._apiKey,
|
|
1017
1208
|
transaction: tx
|
|
@@ -1161,6 +1352,30 @@ var Client = class _Client {
|
|
|
1161
1352
|
}
|
|
1162
1353
|
};
|
|
1163
1354
|
var client_default = Client;
|
|
1355
|
+
function parseEntryFunctionAbi(args) {
|
|
1356
|
+
const { moduleAbi, moduleAddress, moduleName, functionName } = args;
|
|
1357
|
+
const functionAbi = moduleAbi.exposed_functions.find((func) => func.name === functionName);
|
|
1358
|
+
if (!functionAbi) {
|
|
1359
|
+
throw new Error(
|
|
1360
|
+
`Could not find entry function ABI for '${moduleAddress}::${moduleName}::${functionName}'`
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
if (!functionAbi.is_entry) {
|
|
1364
|
+
throw new Error(
|
|
1365
|
+
`'${moduleAddress}::${moduleName}::${functionName}' is not an entry function`
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
const numSigners = (0, import_ts_sdk2.findFirstNonSignerArg)(functionAbi);
|
|
1369
|
+
const params = [];
|
|
1370
|
+
for (let i = numSigners; i < functionAbi.params.length; i += 1) {
|
|
1371
|
+
params.push((0, import_ts_sdk2.parseTypeTag)(functionAbi.params[i], { allowGenerics: true }));
|
|
1372
|
+
}
|
|
1373
|
+
return {
|
|
1374
|
+
signers: numSigners,
|
|
1375
|
+
typeParameters: functionAbi.generic_type_params,
|
|
1376
|
+
parameters: params
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1164
1379
|
|
|
1165
1380
|
// src/testFaucet.ts
|
|
1166
1381
|
var import_surf2 = require("@thalalabs/surf");
|
|
@@ -1519,6 +1734,8 @@ var TestFaucet = class _TestFaucet extends client_default {
|
|
|
1519
1734
|
getRandomId,
|
|
1520
1735
|
getTopicFromCommand,
|
|
1521
1736
|
getTopicFromMessage,
|
|
1737
|
+
nowInMiliseconds,
|
|
1738
|
+
parseEntryFunctionAbi,
|
|
1522
1739
|
sleep,
|
|
1523
1740
|
toSystemValue
|
|
1524
1741
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _aptos_labs_ts_sdk from '@aptos-labs/ts-sdk';
|
|
2
|
-
import {
|
|
2
|
+
import { Account, Aptos, AccountAuthenticator, SimpleTransaction, MoveModule, EntryFunctionABI } from '@aptos-labs/ts-sdk';
|
|
3
3
|
import * as _thalalabs_surf_build_types_core from '@thalalabs/surf/build/types/core';
|
|
4
4
|
import * as _thalalabs_surf from '@thalalabs/surf';
|
|
5
5
|
import WebSocket from 'isomorphic-ws';
|
|
@@ -589,6 +589,87 @@ declare enum Network {
|
|
|
589
589
|
Devnet = "Devnet"
|
|
590
590
|
}
|
|
591
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Manages sequence numbers for Aptos blockchain transactions.
|
|
594
|
+
* Ensures proper transaction ordering and handles synchronization with the blockchain.
|
|
595
|
+
*/
|
|
596
|
+
declare class AccountSequenceNumber {
|
|
597
|
+
private _aptos;
|
|
598
|
+
readonly account: Account;
|
|
599
|
+
private lastCommittedNumber;
|
|
600
|
+
private currentNumber;
|
|
601
|
+
private isLocked;
|
|
602
|
+
private lockQueue;
|
|
603
|
+
private readonly maxWaitTime;
|
|
604
|
+
private readonly maximumInFlight;
|
|
605
|
+
private readonly sleepTime;
|
|
606
|
+
private readonly warningTime;
|
|
607
|
+
/**
|
|
608
|
+
* Creates an instance of AccountSequenceNumber.
|
|
609
|
+
*
|
|
610
|
+
* @param aptos - The Aptos client instance
|
|
611
|
+
* @param account - The account associated with transactions
|
|
612
|
+
* @param options - Configuration options
|
|
613
|
+
*/
|
|
614
|
+
constructor(aptos: Aptos, account: Account, options?: {
|
|
615
|
+
maxWaitTime?: number;
|
|
616
|
+
maximumInFlight?: number;
|
|
617
|
+
sleepTime?: number;
|
|
618
|
+
warningTime?: number;
|
|
619
|
+
});
|
|
620
|
+
/**
|
|
621
|
+
* Acquires the lock for synchronized access.
|
|
622
|
+
*/
|
|
623
|
+
private acquireLock;
|
|
624
|
+
/**
|
|
625
|
+
* Releases the lock and processes the next queued operation if any.
|
|
626
|
+
*/
|
|
627
|
+
private releaseLock;
|
|
628
|
+
/**
|
|
629
|
+
* Returns the next available sequence number for this account.
|
|
630
|
+
*
|
|
631
|
+
* @returns The next available sequence number or null if an error occurs
|
|
632
|
+
*/
|
|
633
|
+
nextSequenceNumber(): Promise<bigint | null>;
|
|
634
|
+
/**
|
|
635
|
+
* Waits for pending transactions to be committed.
|
|
636
|
+
*/
|
|
637
|
+
private waitForCommit;
|
|
638
|
+
/**
|
|
639
|
+
* Initializes this account with the sequence number on chain.
|
|
640
|
+
*/
|
|
641
|
+
initialize(): Promise<void>;
|
|
642
|
+
/**
|
|
643
|
+
* Updates this account's sequence number with the one on-chain.
|
|
644
|
+
*
|
|
645
|
+
* @returns The on-chain sequence number for this account.
|
|
646
|
+
*/
|
|
647
|
+
update(): Promise<bigint>;
|
|
648
|
+
/**
|
|
649
|
+
* Synchronizes the local sequence number with the sequence number on-chain.
|
|
650
|
+
* This method waits until all submitted transactions have been committed.
|
|
651
|
+
*/
|
|
652
|
+
synchronize(): Promise<void>;
|
|
653
|
+
/**
|
|
654
|
+
* Gets the current sequence number from the blockchain.
|
|
655
|
+
*
|
|
656
|
+
* @returns The current sequence number
|
|
657
|
+
* @throws If unable to retrieve the account information
|
|
658
|
+
*/
|
|
659
|
+
getSequenceNumber(): Promise<bigint>;
|
|
660
|
+
/**
|
|
661
|
+
* Returns information about the current state.
|
|
662
|
+
* Useful for debugging and monitoring.
|
|
663
|
+
*/
|
|
664
|
+
getStatus(): {
|
|
665
|
+
pendingTransactions: bigint;
|
|
666
|
+
currentNumber: bigint | null;
|
|
667
|
+
lastCommittedNumber: bigint | null;
|
|
668
|
+
isLocked: boolean;
|
|
669
|
+
queuedOperations: number;
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
592
673
|
declare const getRandomId: () => string;
|
|
593
674
|
declare class Client {
|
|
594
675
|
_aptos: Aptos;
|
|
@@ -598,6 +679,7 @@ declare class Client {
|
|
|
598
679
|
_ws: WebSocket | undefined;
|
|
599
680
|
_serverUrl: string;
|
|
600
681
|
_subscriptions: Map<string, (data: WsMessage) => void>;
|
|
682
|
+
_sequenceNumberManager: AccountSequenceNumber;
|
|
601
683
|
timeout: number;
|
|
602
684
|
static init(connection: Aptos, apiKey?: Account, url?: string, enableWs?: boolean): Promise<Client>;
|
|
603
685
|
constructor(connection: Aptos, url: string, ws?: WebSocket, apiKey?: Account);
|
|
@@ -605,8 +687,7 @@ declare class Client {
|
|
|
605
687
|
sendWsMessage(message: WsCommand): Promise<WsMessage>;
|
|
606
688
|
static create(connection: Aptos, apiKey?: Account, url?: string, enableWs?: boolean): Promise<Client>;
|
|
607
689
|
setApiKey(apiKey: Account): Promise<void>;
|
|
608
|
-
getApiKeySequenceNumber():
|
|
609
|
-
incrementSequenceNumber(): void;
|
|
690
|
+
getApiKeySequenceNumber(): Promise<bigint>;
|
|
610
691
|
fetchApiKeySequenceNumber(): Promise<number>;
|
|
611
692
|
createUser(params: CreateUserParams): Promise<{
|
|
612
693
|
tx: _aptos_labs_ts_sdk.MultiAgentTransaction;
|
|
@@ -742,6 +823,13 @@ type WsPerpMarketUpdates = Extract<WsMessage, {
|
|
|
742
823
|
type: 'OrderbookUpdate' | 'TradesUpdate';
|
|
743
824
|
}>;
|
|
744
825
|
|
|
826
|
+
declare function parseEntryFunctionAbi(args: {
|
|
827
|
+
moduleAbi: MoveModule;
|
|
828
|
+
moduleAddress: string;
|
|
829
|
+
moduleName: string;
|
|
830
|
+
functionName: string;
|
|
831
|
+
}): EntryFunctionABI;
|
|
832
|
+
|
|
745
833
|
declare const ExchangeProxies: {
|
|
746
834
|
[key in Network]: string[];
|
|
747
835
|
};
|
|
@@ -758,9 +846,10 @@ declare class TestFaucet extends Client {
|
|
|
758
846
|
}
|
|
759
847
|
|
|
760
848
|
declare const sleep: (ms: number) => Promise<unknown>;
|
|
849
|
+
declare const nowInMiliseconds: () => number;
|
|
761
850
|
declare const toSystemValue: (value: string | number) => string;
|
|
762
851
|
declare const generateApiKey: () => _aptos_labs_ts_sdk.Ed25519Account;
|
|
763
852
|
declare const getTopicFromCommand: (data: WsCommand) => string;
|
|
764
853
|
declare const getTopicFromMessage: (data: WsMessage) => string;
|
|
765
854
|
|
|
766
|
-
export { type AddApiKey, type AddApiKeyParams, type Address, AdminEndpoints, type BalanceChange, BaseEndpoints, type Borrow, type BorrowLending, type CancelAllPerpOrdersParams, type CancelPerpOrdersParams, type CanceledPerpOrders, type ChartCandle, ChartInterval, Client, type Content, type CreateUserParams, type Deposit, type DepositToVaultParams, type DepositTokenParams, EndpointsV1, type ErrorResponse, type ExchangeConfig, ExchangeProxies, type Fees, type FundingCheckpoint, type FundingRate, GLOBAL_DENOMINATOR, type GetBorrowLendingDataResponse, type GetChartCandlesInRangeRequest, type GetChartCandlesInRangeResponse, type GetPerpMarketsDataRequest, type GetPerpMarketsDataResponse, type GetPerpOrderBookDataRequest, type GetPerpOrderBookDataResponse, type GetPerpRecentTradesRequest, type GetPerpRecentTradesResponse, type GetPerpUserFillsRequest, type GetPerpUserFillsResponse, type GetPerpUserOrdersRequest, type GetPerpUserOrdersResponse, type GetPerpetualMarketsConfigResponse, type GetPriceIndexesResponse, type GetTokensConfigResponse, type GetUserDataRequest, type GetUserDataResponse, type GetUsersByAddressRequest, type GetUsersByAddressResponse, type IGetChartCandlesInRange, type Lend, type LendTokenParams, type MarginStep, Network, type OracleUpdate, type OracleUpdates, type Order, type OrderFills, OrderSide, OrderStatus, OrderType, type OrderbookUpdate, type PaginationCursor, type PerpFill, type PerpMarketData, type PerpOrder, type PerpOrderBookData, type PerpPosition, type PerpTrade, type PerpetualMarketConfigEntry, PerpetualMarketStatus, type PlacePerpLimitOrder, type PlacePerpLimitOrderParams, type PlacePerpMarketOrder, type PlacePerpMarketOrderParams, type PriceIndex, type RedeemTokenParams, type Referral, type RemoveApiKey, type RemoveApiKeyParams, type RepayBorrow, type SetAlias, type SetAliasNameParams, type SetAutolend, type SetAutolendParams, Status, type StatusResponse, type SubmitSponsoredTransactionRequest, type SubmitSponsoredTransactionResponse, TestFaucet, type TimeResponse, type TokenConfigEntry, type Topic, type Trade, TradeRole, type TradesUpdate, type User, UserStatus, type UtilizationCurve, type VaultInvestment, type Withdraw, type WithdrawFromVaultParams, type WithdrawLend, type WsCommand, type WsFill, type WsMessage, type WsOracleUpdates, type WsPerpMarketUpdates, type WsUserUpdates, generateApiKey, getRandomId, getTopicFromCommand, getTopicFromMessage, sleep, toSystemValue };
|
|
855
|
+
export { type AddApiKey, type AddApiKeyParams, type Address, AdminEndpoints, type BalanceChange, BaseEndpoints, type Borrow, type BorrowLending, type CancelAllPerpOrdersParams, type CancelPerpOrdersParams, type CanceledPerpOrders, type ChartCandle, ChartInterval, Client, type Content, type CreateUserParams, type Deposit, type DepositToVaultParams, type DepositTokenParams, EndpointsV1, type ErrorResponse, type ExchangeConfig, ExchangeProxies, type Fees, type FundingCheckpoint, type FundingRate, GLOBAL_DENOMINATOR, type GetBorrowLendingDataResponse, type GetChartCandlesInRangeRequest, type GetChartCandlesInRangeResponse, type GetPerpMarketsDataRequest, type GetPerpMarketsDataResponse, type GetPerpOrderBookDataRequest, type GetPerpOrderBookDataResponse, type GetPerpRecentTradesRequest, type GetPerpRecentTradesResponse, type GetPerpUserFillsRequest, type GetPerpUserFillsResponse, type GetPerpUserOrdersRequest, type GetPerpUserOrdersResponse, type GetPerpetualMarketsConfigResponse, type GetPriceIndexesResponse, type GetTokensConfigResponse, type GetUserDataRequest, type GetUserDataResponse, type GetUsersByAddressRequest, type GetUsersByAddressResponse, type IGetChartCandlesInRange, type Lend, type LendTokenParams, type MarginStep, Network, type OracleUpdate, type OracleUpdates, type Order, type OrderFills, OrderSide, OrderStatus, OrderType, type OrderbookUpdate, type PaginationCursor, type PerpFill, type PerpMarketData, type PerpOrder, type PerpOrderBookData, type PerpPosition, type PerpTrade, type PerpetualMarketConfigEntry, PerpetualMarketStatus, type PlacePerpLimitOrder, type PlacePerpLimitOrderParams, type PlacePerpMarketOrder, type PlacePerpMarketOrderParams, type PriceIndex, type RedeemTokenParams, type Referral, type RemoveApiKey, type RemoveApiKeyParams, type RepayBorrow, type SetAlias, type SetAliasNameParams, type SetAutolend, type SetAutolendParams, Status, type StatusResponse, type SubmitSponsoredTransactionRequest, type SubmitSponsoredTransactionResponse, TestFaucet, type TimeResponse, type TokenConfigEntry, type Topic, type Trade, TradeRole, type TradesUpdate, type User, UserStatus, type UtilizationCurve, type VaultInvestment, type Withdraw, type WithdrawFromVaultParams, type WithdrawLend, type WsCommand, type WsFill, type WsMessage, type WsOracleUpdates, type WsPerpMarketUpdates, type WsUserUpdates, generateApiKey, getRandomId, getTopicFromCommand, getTopicFromMessage, nowInMiliseconds, parseEntryFunctionAbi, sleep, toSystemValue };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _aptos_labs_ts_sdk from '@aptos-labs/ts-sdk';
|
|
2
|
-
import {
|
|
2
|
+
import { Account, Aptos, AccountAuthenticator, SimpleTransaction, MoveModule, EntryFunctionABI } from '@aptos-labs/ts-sdk';
|
|
3
3
|
import * as _thalalabs_surf_build_types_core from '@thalalabs/surf/build/types/core';
|
|
4
4
|
import * as _thalalabs_surf from '@thalalabs/surf';
|
|
5
5
|
import WebSocket from 'isomorphic-ws';
|
|
@@ -589,6 +589,87 @@ declare enum Network {
|
|
|
589
589
|
Devnet = "Devnet"
|
|
590
590
|
}
|
|
591
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Manages sequence numbers for Aptos blockchain transactions.
|
|
594
|
+
* Ensures proper transaction ordering and handles synchronization with the blockchain.
|
|
595
|
+
*/
|
|
596
|
+
declare class AccountSequenceNumber {
|
|
597
|
+
private _aptos;
|
|
598
|
+
readonly account: Account;
|
|
599
|
+
private lastCommittedNumber;
|
|
600
|
+
private currentNumber;
|
|
601
|
+
private isLocked;
|
|
602
|
+
private lockQueue;
|
|
603
|
+
private readonly maxWaitTime;
|
|
604
|
+
private readonly maximumInFlight;
|
|
605
|
+
private readonly sleepTime;
|
|
606
|
+
private readonly warningTime;
|
|
607
|
+
/**
|
|
608
|
+
* Creates an instance of AccountSequenceNumber.
|
|
609
|
+
*
|
|
610
|
+
* @param aptos - The Aptos client instance
|
|
611
|
+
* @param account - The account associated with transactions
|
|
612
|
+
* @param options - Configuration options
|
|
613
|
+
*/
|
|
614
|
+
constructor(aptos: Aptos, account: Account, options?: {
|
|
615
|
+
maxWaitTime?: number;
|
|
616
|
+
maximumInFlight?: number;
|
|
617
|
+
sleepTime?: number;
|
|
618
|
+
warningTime?: number;
|
|
619
|
+
});
|
|
620
|
+
/**
|
|
621
|
+
* Acquires the lock for synchronized access.
|
|
622
|
+
*/
|
|
623
|
+
private acquireLock;
|
|
624
|
+
/**
|
|
625
|
+
* Releases the lock and processes the next queued operation if any.
|
|
626
|
+
*/
|
|
627
|
+
private releaseLock;
|
|
628
|
+
/**
|
|
629
|
+
* Returns the next available sequence number for this account.
|
|
630
|
+
*
|
|
631
|
+
* @returns The next available sequence number or null if an error occurs
|
|
632
|
+
*/
|
|
633
|
+
nextSequenceNumber(): Promise<bigint | null>;
|
|
634
|
+
/**
|
|
635
|
+
* Waits for pending transactions to be committed.
|
|
636
|
+
*/
|
|
637
|
+
private waitForCommit;
|
|
638
|
+
/**
|
|
639
|
+
* Initializes this account with the sequence number on chain.
|
|
640
|
+
*/
|
|
641
|
+
initialize(): Promise<void>;
|
|
642
|
+
/**
|
|
643
|
+
* Updates this account's sequence number with the one on-chain.
|
|
644
|
+
*
|
|
645
|
+
* @returns The on-chain sequence number for this account.
|
|
646
|
+
*/
|
|
647
|
+
update(): Promise<bigint>;
|
|
648
|
+
/**
|
|
649
|
+
* Synchronizes the local sequence number with the sequence number on-chain.
|
|
650
|
+
* This method waits until all submitted transactions have been committed.
|
|
651
|
+
*/
|
|
652
|
+
synchronize(): Promise<void>;
|
|
653
|
+
/**
|
|
654
|
+
* Gets the current sequence number from the blockchain.
|
|
655
|
+
*
|
|
656
|
+
* @returns The current sequence number
|
|
657
|
+
* @throws If unable to retrieve the account information
|
|
658
|
+
*/
|
|
659
|
+
getSequenceNumber(): Promise<bigint>;
|
|
660
|
+
/**
|
|
661
|
+
* Returns information about the current state.
|
|
662
|
+
* Useful for debugging and monitoring.
|
|
663
|
+
*/
|
|
664
|
+
getStatus(): {
|
|
665
|
+
pendingTransactions: bigint;
|
|
666
|
+
currentNumber: bigint | null;
|
|
667
|
+
lastCommittedNumber: bigint | null;
|
|
668
|
+
isLocked: boolean;
|
|
669
|
+
queuedOperations: number;
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
592
673
|
declare const getRandomId: () => string;
|
|
593
674
|
declare class Client {
|
|
594
675
|
_aptos: Aptos;
|
|
@@ -598,6 +679,7 @@ declare class Client {
|
|
|
598
679
|
_ws: WebSocket | undefined;
|
|
599
680
|
_serverUrl: string;
|
|
600
681
|
_subscriptions: Map<string, (data: WsMessage) => void>;
|
|
682
|
+
_sequenceNumberManager: AccountSequenceNumber;
|
|
601
683
|
timeout: number;
|
|
602
684
|
static init(connection: Aptos, apiKey?: Account, url?: string, enableWs?: boolean): Promise<Client>;
|
|
603
685
|
constructor(connection: Aptos, url: string, ws?: WebSocket, apiKey?: Account);
|
|
@@ -605,8 +687,7 @@ declare class Client {
|
|
|
605
687
|
sendWsMessage(message: WsCommand): Promise<WsMessage>;
|
|
606
688
|
static create(connection: Aptos, apiKey?: Account, url?: string, enableWs?: boolean): Promise<Client>;
|
|
607
689
|
setApiKey(apiKey: Account): Promise<void>;
|
|
608
|
-
getApiKeySequenceNumber():
|
|
609
|
-
incrementSequenceNumber(): void;
|
|
690
|
+
getApiKeySequenceNumber(): Promise<bigint>;
|
|
610
691
|
fetchApiKeySequenceNumber(): Promise<number>;
|
|
611
692
|
createUser(params: CreateUserParams): Promise<{
|
|
612
693
|
tx: _aptos_labs_ts_sdk.MultiAgentTransaction;
|
|
@@ -742,6 +823,13 @@ type WsPerpMarketUpdates = Extract<WsMessage, {
|
|
|
742
823
|
type: 'OrderbookUpdate' | 'TradesUpdate';
|
|
743
824
|
}>;
|
|
744
825
|
|
|
826
|
+
declare function parseEntryFunctionAbi(args: {
|
|
827
|
+
moduleAbi: MoveModule;
|
|
828
|
+
moduleAddress: string;
|
|
829
|
+
moduleName: string;
|
|
830
|
+
functionName: string;
|
|
831
|
+
}): EntryFunctionABI;
|
|
832
|
+
|
|
745
833
|
declare const ExchangeProxies: {
|
|
746
834
|
[key in Network]: string[];
|
|
747
835
|
};
|
|
@@ -758,9 +846,10 @@ declare class TestFaucet extends Client {
|
|
|
758
846
|
}
|
|
759
847
|
|
|
760
848
|
declare const sleep: (ms: number) => Promise<unknown>;
|
|
849
|
+
declare const nowInMiliseconds: () => number;
|
|
761
850
|
declare const toSystemValue: (value: string | number) => string;
|
|
762
851
|
declare const generateApiKey: () => _aptos_labs_ts_sdk.Ed25519Account;
|
|
763
852
|
declare const getTopicFromCommand: (data: WsCommand) => string;
|
|
764
853
|
declare const getTopicFromMessage: (data: WsMessage) => string;
|
|
765
854
|
|
|
766
|
-
export { type AddApiKey, type AddApiKeyParams, type Address, AdminEndpoints, type BalanceChange, BaseEndpoints, type Borrow, type BorrowLending, type CancelAllPerpOrdersParams, type CancelPerpOrdersParams, type CanceledPerpOrders, type ChartCandle, ChartInterval, Client, type Content, type CreateUserParams, type Deposit, type DepositToVaultParams, type DepositTokenParams, EndpointsV1, type ErrorResponse, type ExchangeConfig, ExchangeProxies, type Fees, type FundingCheckpoint, type FundingRate, GLOBAL_DENOMINATOR, type GetBorrowLendingDataResponse, type GetChartCandlesInRangeRequest, type GetChartCandlesInRangeResponse, type GetPerpMarketsDataRequest, type GetPerpMarketsDataResponse, type GetPerpOrderBookDataRequest, type GetPerpOrderBookDataResponse, type GetPerpRecentTradesRequest, type GetPerpRecentTradesResponse, type GetPerpUserFillsRequest, type GetPerpUserFillsResponse, type GetPerpUserOrdersRequest, type GetPerpUserOrdersResponse, type GetPerpetualMarketsConfigResponse, type GetPriceIndexesResponse, type GetTokensConfigResponse, type GetUserDataRequest, type GetUserDataResponse, type GetUsersByAddressRequest, type GetUsersByAddressResponse, type IGetChartCandlesInRange, type Lend, type LendTokenParams, type MarginStep, Network, type OracleUpdate, type OracleUpdates, type Order, type OrderFills, OrderSide, OrderStatus, OrderType, type OrderbookUpdate, type PaginationCursor, type PerpFill, type PerpMarketData, type PerpOrder, type PerpOrderBookData, type PerpPosition, type PerpTrade, type PerpetualMarketConfigEntry, PerpetualMarketStatus, type PlacePerpLimitOrder, type PlacePerpLimitOrderParams, type PlacePerpMarketOrder, type PlacePerpMarketOrderParams, type PriceIndex, type RedeemTokenParams, type Referral, type RemoveApiKey, type RemoveApiKeyParams, type RepayBorrow, type SetAlias, type SetAliasNameParams, type SetAutolend, type SetAutolendParams, Status, type StatusResponse, type SubmitSponsoredTransactionRequest, type SubmitSponsoredTransactionResponse, TestFaucet, type TimeResponse, type TokenConfigEntry, type Topic, type Trade, TradeRole, type TradesUpdate, type User, UserStatus, type UtilizationCurve, type VaultInvestment, type Withdraw, type WithdrawFromVaultParams, type WithdrawLend, type WsCommand, type WsFill, type WsMessage, type WsOracleUpdates, type WsPerpMarketUpdates, type WsUserUpdates, generateApiKey, getRandomId, getTopicFromCommand, getTopicFromMessage, sleep, toSystemValue };
|
|
855
|
+
export { type AddApiKey, type AddApiKeyParams, type Address, AdminEndpoints, type BalanceChange, BaseEndpoints, type Borrow, type BorrowLending, type CancelAllPerpOrdersParams, type CancelPerpOrdersParams, type CanceledPerpOrders, type ChartCandle, ChartInterval, Client, type Content, type CreateUserParams, type Deposit, type DepositToVaultParams, type DepositTokenParams, EndpointsV1, type ErrorResponse, type ExchangeConfig, ExchangeProxies, type Fees, type FundingCheckpoint, type FundingRate, GLOBAL_DENOMINATOR, type GetBorrowLendingDataResponse, type GetChartCandlesInRangeRequest, type GetChartCandlesInRangeResponse, type GetPerpMarketsDataRequest, type GetPerpMarketsDataResponse, type GetPerpOrderBookDataRequest, type GetPerpOrderBookDataResponse, type GetPerpRecentTradesRequest, type GetPerpRecentTradesResponse, type GetPerpUserFillsRequest, type GetPerpUserFillsResponse, type GetPerpUserOrdersRequest, type GetPerpUserOrdersResponse, type GetPerpetualMarketsConfigResponse, type GetPriceIndexesResponse, type GetTokensConfigResponse, type GetUserDataRequest, type GetUserDataResponse, type GetUsersByAddressRequest, type GetUsersByAddressResponse, type IGetChartCandlesInRange, type Lend, type LendTokenParams, type MarginStep, Network, type OracleUpdate, type OracleUpdates, type Order, type OrderFills, OrderSide, OrderStatus, OrderType, type OrderbookUpdate, type PaginationCursor, type PerpFill, type PerpMarketData, type PerpOrder, type PerpOrderBookData, type PerpPosition, type PerpTrade, type PerpetualMarketConfigEntry, PerpetualMarketStatus, type PlacePerpLimitOrder, type PlacePerpLimitOrderParams, type PlacePerpMarketOrder, type PlacePerpMarketOrderParams, type PriceIndex, type RedeemTokenParams, type Referral, type RemoveApiKey, type RemoveApiKeyParams, type RepayBorrow, type SetAlias, type SetAliasNameParams, type SetAutolend, type SetAutolendParams, Status, type StatusResponse, type SubmitSponsoredTransactionRequest, type SubmitSponsoredTransactionResponse, TestFaucet, type TimeResponse, type TokenConfigEntry, type Topic, type Trade, TradeRole, type TradesUpdate, type User, UserStatus, type UtilizationCurve, type VaultInvestment, type Withdraw, type WithdrawFromVaultParams, type WithdrawLend, type WsCommand, type WsFill, type WsMessage, type WsOracleUpdates, type WsPerpMarketUpdates, type WsUserUpdates, generateApiKey, getRandomId, getTopicFromCommand, getTopicFromMessage, nowInMiliseconds, parseEntryFunctionAbi, sleep, toSystemValue };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
|
+
import {
|
|
3
|
+
findFirstNonSignerArg,
|
|
4
|
+
parseTypeTag
|
|
5
|
+
} from "@aptos-labs/ts-sdk";
|
|
2
6
|
import { createEntryPayload, createSurfClient } from "@thalalabs/surf";
|
|
3
7
|
import WebSocket from "isomorphic-ws";
|
|
4
8
|
import { v4 as uuidv4 } from "uuid";
|
|
@@ -456,6 +460,7 @@ var GLOBAL_DENOMINATOR = 1e8;
|
|
|
456
460
|
// src/utils.ts
|
|
457
461
|
import { Decimal } from "decimal.js";
|
|
458
462
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
463
|
+
var nowInMiliseconds = () => Date.now();
|
|
459
464
|
var toSystemValue = (value) => {
|
|
460
465
|
return new Decimal(value).mul(new Decimal(GLOBAL_DENOMINATOR)).toString();
|
|
461
466
|
};
|
|
@@ -523,6 +528,184 @@ var getTopicFromMessage = (data) => {
|
|
|
523
528
|
}
|
|
524
529
|
};
|
|
525
530
|
|
|
531
|
+
// src/sequenceNumberManager.ts
|
|
532
|
+
var AccountSequenceNumber = class {
|
|
533
|
+
/**
|
|
534
|
+
* Creates an instance of AccountSequenceNumber.
|
|
535
|
+
*
|
|
536
|
+
* @param aptos - The Aptos client instance
|
|
537
|
+
* @param account - The account associated with transactions
|
|
538
|
+
* @param options - Configuration options
|
|
539
|
+
*/
|
|
540
|
+
constructor(aptos, account, options = {}) {
|
|
541
|
+
// Sequence number on chain
|
|
542
|
+
this.lastCommittedNumber = null;
|
|
543
|
+
// Local sequence number (next to be used)
|
|
544
|
+
this.currentNumber = null;
|
|
545
|
+
// Use a proper mutex implementation instead of a boolean flag
|
|
546
|
+
this.isLocked = false;
|
|
547
|
+
this.lockQueue = [];
|
|
548
|
+
this._aptos = aptos;
|
|
549
|
+
this.account = account;
|
|
550
|
+
this.maxWaitTime = options.maxWaitTime ?? 1e4;
|
|
551
|
+
this.maximumInFlight = options.maximumInFlight ?? 100;
|
|
552
|
+
this.sleepTime = options.sleepTime ?? 10;
|
|
553
|
+
this.warningTime = options.warningTime ?? 3e4;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Acquires the lock for synchronized access.
|
|
557
|
+
*/
|
|
558
|
+
async acquireLock() {
|
|
559
|
+
if (!this.isLocked) {
|
|
560
|
+
this.isLocked = true;
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
return new Promise((resolve) => {
|
|
564
|
+
this.lockQueue.push(resolve);
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Releases the lock and processes the next queued operation if any.
|
|
569
|
+
*/
|
|
570
|
+
releaseLock() {
|
|
571
|
+
if (this.lockQueue.length > 0) {
|
|
572
|
+
const nextResolve = this.lockQueue.shift();
|
|
573
|
+
if (nextResolve) {
|
|
574
|
+
nextResolve();
|
|
575
|
+
}
|
|
576
|
+
} else {
|
|
577
|
+
this.isLocked = false;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Returns the next available sequence number for this account.
|
|
582
|
+
*
|
|
583
|
+
* @returns The next available sequence number or null if an error occurs
|
|
584
|
+
*/
|
|
585
|
+
async nextSequenceNumber() {
|
|
586
|
+
await this.acquireLock();
|
|
587
|
+
try {
|
|
588
|
+
if (this.lastCommittedNumber === null || this.currentNumber === null) {
|
|
589
|
+
await this.initialize();
|
|
590
|
+
}
|
|
591
|
+
if (this.currentNumber - this.lastCommittedNumber >= this.maximumInFlight) {
|
|
592
|
+
await this.waitForCommit();
|
|
593
|
+
}
|
|
594
|
+
const nextNumber = this.currentNumber;
|
|
595
|
+
this.currentNumber = this.currentNumber + BigInt(1);
|
|
596
|
+
return nextNumber;
|
|
597
|
+
} catch (e) {
|
|
598
|
+
console.error("Error getting next sequence number:", e);
|
|
599
|
+
return null;
|
|
600
|
+
} finally {
|
|
601
|
+
this.releaseLock();
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Waits for pending transactions to be committed.
|
|
606
|
+
*/
|
|
607
|
+
async waitForCommit() {
|
|
608
|
+
await this.update();
|
|
609
|
+
const startTime = nowInMiliseconds();
|
|
610
|
+
while (this.currentNumber - this.lastCommittedNumber >= this.maximumInFlight) {
|
|
611
|
+
const elapsed = nowInMiliseconds() - startTime;
|
|
612
|
+
if (elapsed > this.maxWaitTime) {
|
|
613
|
+
console.warn(
|
|
614
|
+
`Waited over ${this.maxWaitTime / 1e3} seconds for a transaction to commit, re-syncing ${this.account.accountAddress.toString()}`
|
|
615
|
+
);
|
|
616
|
+
await this.initialize();
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
if (elapsed > this.warningTime && elapsed % 5e3 < this.sleepTime) {
|
|
620
|
+
console.warn(
|
|
621
|
+
`Still waiting for transactions to commit after ${elapsed / 1e3} seconds for account ${this.account.accountAddress.toString()}`
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
await sleep(this.sleepTime);
|
|
625
|
+
await this.update();
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Initializes this account with the sequence number on chain.
|
|
630
|
+
*/
|
|
631
|
+
async initialize() {
|
|
632
|
+
const sequenceNumber = await this.getSequenceNumber();
|
|
633
|
+
this.currentNumber = sequenceNumber;
|
|
634
|
+
this.lastCommittedNumber = sequenceNumber;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Updates this account's sequence number with the one on-chain.
|
|
638
|
+
*
|
|
639
|
+
* @returns The on-chain sequence number for this account.
|
|
640
|
+
*/
|
|
641
|
+
async update() {
|
|
642
|
+
const sequenceNumber = await this.getSequenceNumber();
|
|
643
|
+
this.lastCommittedNumber = sequenceNumber;
|
|
644
|
+
return this.lastCommittedNumber;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Synchronizes the local sequence number with the sequence number on-chain.
|
|
648
|
+
* This method waits until all submitted transactions have been committed.
|
|
649
|
+
*/
|
|
650
|
+
async synchronize() {
|
|
651
|
+
if (this.lastCommittedNumber === this.currentNumber) return;
|
|
652
|
+
await this.acquireLock();
|
|
653
|
+
try {
|
|
654
|
+
await this.update();
|
|
655
|
+
const startTime = nowInMiliseconds();
|
|
656
|
+
while (this.lastCommittedNumber !== this.currentNumber) {
|
|
657
|
+
const elapsed = nowInMiliseconds() - startTime;
|
|
658
|
+
if (elapsed > this.maxWaitTime) {
|
|
659
|
+
console.warn(
|
|
660
|
+
`Waited over ${this.maxWaitTime / 1e3} seconds for all transactions to commit, re-syncing ${this.account.accountAddress.toString()}`
|
|
661
|
+
);
|
|
662
|
+
await this.initialize();
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
await sleep(this.sleepTime);
|
|
666
|
+
await this.update();
|
|
667
|
+
}
|
|
668
|
+
} catch (e) {
|
|
669
|
+
console.error("Error synchronizing account sequence number:", e);
|
|
670
|
+
} finally {
|
|
671
|
+
this.releaseLock();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Gets the current sequence number from the blockchain.
|
|
676
|
+
*
|
|
677
|
+
* @returns The current sequence number
|
|
678
|
+
* @throws If unable to retrieve the account information
|
|
679
|
+
*/
|
|
680
|
+
async getSequenceNumber() {
|
|
681
|
+
try {
|
|
682
|
+
const accInfo = await this._aptos.getAccountInfo({
|
|
683
|
+
accountAddress: this.account.accountAddress
|
|
684
|
+
});
|
|
685
|
+
return BigInt(accInfo.sequence_number);
|
|
686
|
+
} catch (error) {
|
|
687
|
+
console.error(
|
|
688
|
+
`Failed to get sequence number for ${this.account.accountAddress.toString()}:`,
|
|
689
|
+
error
|
|
690
|
+
);
|
|
691
|
+
throw error;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Returns information about the current state.
|
|
696
|
+
* Useful for debugging and monitoring.
|
|
697
|
+
*/
|
|
698
|
+
getStatus() {
|
|
699
|
+
return {
|
|
700
|
+
pendingTransactions: this.currentNumber !== null && this.lastCommittedNumber !== null ? this.currentNumber - this.lastCommittedNumber : BigInt(0),
|
|
701
|
+
currentNumber: this.currentNumber,
|
|
702
|
+
lastCommittedNumber: this.lastCommittedNumber,
|
|
703
|
+
isLocked: this.isLocked,
|
|
704
|
+
queuedOperations: this.lockQueue.length
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
526
709
|
// src/client.ts
|
|
527
710
|
var getRandomId = () => uuidv4();
|
|
528
711
|
var Client = class _Client {
|
|
@@ -696,6 +879,7 @@ var Client = class _Client {
|
|
|
696
879
|
this._apiKey = apiKey || generateApiKey();
|
|
697
880
|
this._subscriptions = /* @__PURE__ */ new Map();
|
|
698
881
|
this._serverUrl = url;
|
|
882
|
+
this._sequenceNumberManager = new AccountSequenceNumber(this._aptos, this._apiKey);
|
|
699
883
|
this._ws = ws;
|
|
700
884
|
if (this._ws) {
|
|
701
885
|
this._ws.onmessage = async (msg) => {
|
|
@@ -766,12 +950,11 @@ var Client = class _Client {
|
|
|
766
950
|
async setApiKey(apiKey) {
|
|
767
951
|
this._apiKey = apiKey;
|
|
768
952
|
this._apiKeySequenceNumber = await this.fetchApiKeySequenceNumber();
|
|
953
|
+
this._sequenceNumberManager = new AccountSequenceNumber(this._aptos, this._apiKey);
|
|
954
|
+
await this._sequenceNumberManager.initialize();
|
|
769
955
|
}
|
|
770
956
|
getApiKeySequenceNumber() {
|
|
771
|
-
return this.
|
|
772
|
-
}
|
|
773
|
-
incrementSequenceNumber() {
|
|
774
|
-
this._apiKeySequenceNumber++;
|
|
957
|
+
return this._sequenceNumberManager.getSequenceNumber();
|
|
775
958
|
}
|
|
776
959
|
async fetchApiKeySequenceNumber() {
|
|
777
960
|
const accInfo = await this._aptos.getAccountInfo({
|
|
@@ -903,7 +1086,7 @@ var Client = class _Client {
|
|
|
903
1086
|
return await this.submitSponsoredTransaction(tx, signature);
|
|
904
1087
|
}
|
|
905
1088
|
async placePerpLimitOrder(params) {
|
|
906
|
-
console.log("start"
|
|
1089
|
+
console.log("start");
|
|
907
1090
|
const payload = createEntryPayload(placePerpLimitOrder_default, {
|
|
908
1091
|
function: "place_perp_limit_order",
|
|
909
1092
|
functionArguments: [
|
|
@@ -916,22 +1099,35 @@ var Client = class _Client {
|
|
|
916
1099
|
],
|
|
917
1100
|
typeArguments: []
|
|
918
1101
|
});
|
|
919
|
-
console.log("
|
|
1102
|
+
console.log("get sequence number");
|
|
1103
|
+
const sequenceNumber = await this.getApiKeySequenceNumber();
|
|
1104
|
+
console.log("sequence number", sequenceNumber);
|
|
920
1105
|
const tx = await this._aptos.transaction.build.simple({
|
|
921
1106
|
sender: this._apiKey.accountAddress,
|
|
922
|
-
data:
|
|
1107
|
+
data: {
|
|
1108
|
+
...payload,
|
|
1109
|
+
abi: parseEntryFunctionAbi({
|
|
1110
|
+
moduleAbi: placePerpLimitOrder_default,
|
|
1111
|
+
functionName: "place_perp_limit_order",
|
|
1112
|
+
moduleAddress: "0x88dd5fbd381db9ad1566c8bbaec39a3d98906b3983a74bcafba70a09ae8f58f6",
|
|
1113
|
+
moduleName: "place_perp_limit_order"
|
|
1114
|
+
})
|
|
1115
|
+
},
|
|
923
1116
|
withFeePayer: true,
|
|
924
1117
|
options: {
|
|
925
|
-
accountSequenceNumber:
|
|
1118
|
+
accountSequenceNumber: sequenceNumber,
|
|
1119
|
+
// Now + 10 sec
|
|
1120
|
+
expireTimestamp: Date.now() + 10 * 1e3,
|
|
1121
|
+
gasUnitPrice: 100,
|
|
1122
|
+
maxGasAmount: 1e4
|
|
926
1123
|
}
|
|
927
1124
|
});
|
|
928
|
-
|
|
929
|
-
console.log("tx", (/* @__PURE__ */ new Date()).getMilliseconds());
|
|
1125
|
+
console.log("after build");
|
|
930
1126
|
const signature = this._aptos.sign({
|
|
931
1127
|
signer: this._apiKey,
|
|
932
1128
|
transaction: tx
|
|
933
1129
|
});
|
|
934
|
-
console.log("
|
|
1130
|
+
console.log("after sign");
|
|
935
1131
|
return await this.submitSponsoredTransaction(tx, signature);
|
|
936
1132
|
}
|
|
937
1133
|
async placePerpMarketOrder(params) {
|
|
@@ -949,12 +1145,8 @@ var Client = class _Client {
|
|
|
949
1145
|
const tx = await this._aptos.transaction.build.simple({
|
|
950
1146
|
sender: this._apiKey.accountAddress,
|
|
951
1147
|
data: payload,
|
|
952
|
-
withFeePayer: true
|
|
953
|
-
options: {
|
|
954
|
-
accountSequenceNumber: this.getApiKeySequenceNumber()
|
|
955
|
-
}
|
|
1148
|
+
withFeePayer: true
|
|
956
1149
|
});
|
|
957
|
-
this.incrementSequenceNumber();
|
|
958
1150
|
const signature = this._aptos.sign({
|
|
959
1151
|
signer: this._apiKey,
|
|
960
1152
|
transaction: tx
|
|
@@ -1104,6 +1296,30 @@ var Client = class _Client {
|
|
|
1104
1296
|
}
|
|
1105
1297
|
};
|
|
1106
1298
|
var client_default = Client;
|
|
1299
|
+
function parseEntryFunctionAbi(args) {
|
|
1300
|
+
const { moduleAbi, moduleAddress, moduleName, functionName } = args;
|
|
1301
|
+
const functionAbi = moduleAbi.exposed_functions.find((func) => func.name === functionName);
|
|
1302
|
+
if (!functionAbi) {
|
|
1303
|
+
throw new Error(
|
|
1304
|
+
`Could not find entry function ABI for '${moduleAddress}::${moduleName}::${functionName}'`
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
if (!functionAbi.is_entry) {
|
|
1308
|
+
throw new Error(
|
|
1309
|
+
`'${moduleAddress}::${moduleName}::${functionName}' is not an entry function`
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
const numSigners = findFirstNonSignerArg(functionAbi);
|
|
1313
|
+
const params = [];
|
|
1314
|
+
for (let i = numSigners; i < functionAbi.params.length; i += 1) {
|
|
1315
|
+
params.push(parseTypeTag(functionAbi.params[i], { allowGenerics: true }));
|
|
1316
|
+
}
|
|
1317
|
+
return {
|
|
1318
|
+
signers: numSigners,
|
|
1319
|
+
typeParameters: functionAbi.generic_type_params,
|
|
1320
|
+
parameters: params
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1107
1323
|
|
|
1108
1324
|
// src/testFaucet.ts
|
|
1109
1325
|
import { createEntryPayload as createEntryPayload2 } from "@thalalabs/surf";
|
|
@@ -1461,6 +1677,8 @@ export {
|
|
|
1461
1677
|
getRandomId,
|
|
1462
1678
|
getTopicFromCommand,
|
|
1463
1679
|
getTopicFromMessage,
|
|
1680
|
+
nowInMiliseconds,
|
|
1681
|
+
parseEntryFunctionAbi,
|
|
1464
1682
|
sleep,
|
|
1465
1683
|
toSystemValue
|
|
1466
1684
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nightlylabs/dex-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"license": "ISC",
|
|
39
39
|
"packageManager": "pnpm@9.3.0+sha512.ee7b93e0c2bd11409c6424f92b866f31d3ea1bef5fbe47d3c7500cdc3c9668833d2e55681ad66df5b640c61fa9dc25d546efa54d76d7f8bf54b13614ac293631",
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@aptos-labs/ts-sdk": "^1.
|
|
41
|
+
"@aptos-labs/ts-sdk": "^1.35.0",
|
|
42
42
|
"@thalalabs/surf": "^1.8.1",
|
|
43
43
|
"decimal.js": "^10.5.0",
|
|
44
44
|
"isomorphic-ws": "^5.0.0",
|