ccxt 4.5.48 → 4.5.50

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.
Files changed (60) hide show
  1. package/README.md +7 -5
  2. package/dist/ccxt.browser.min.js +10 -10
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/weex.js +11 -0
  5. package/dist/cjs/src/base/Exchange.js +48 -13
  6. package/dist/cjs/src/bitget.js +1 -0
  7. package/dist/cjs/src/btcbox.js +1 -1
  8. package/dist/cjs/src/bullish.js +2 -1
  9. package/dist/cjs/src/gate.js +0 -1
  10. package/dist/cjs/src/hibachi.js +1 -1
  11. package/dist/cjs/src/kraken.js +1 -0
  12. package/dist/cjs/src/krakenfutures.js +10 -1
  13. package/dist/cjs/src/kucoin.js +5 -1
  14. package/dist/cjs/src/lighter.js +312 -144
  15. package/dist/cjs/src/mexc.js +7 -12
  16. package/dist/cjs/src/okx.js +46 -1
  17. package/dist/cjs/src/paradex.js +5 -2
  18. package/dist/cjs/src/pro/binance.js +1 -1
  19. package/dist/cjs/src/pro/cex.js +1 -1
  20. package/dist/cjs/src/pro/coinbase.js +1 -1
  21. package/dist/cjs/src/pro/hyperliquid.js +361 -1
  22. package/dist/cjs/src/pro/lighter.js +339 -18
  23. package/dist/cjs/src/pro/weex.js +1906 -0
  24. package/dist/cjs/src/weex.js +3823 -0
  25. package/js/ccxt.d.ts +8 -2
  26. package/js/ccxt.js +6 -2
  27. package/js/src/abstract/myokx.d.ts +34 -0
  28. package/js/src/abstract/okx.d.ts +34 -0
  29. package/js/src/abstract/okxus.d.ts +34 -0
  30. package/js/src/abstract/weex.d.ts +83 -0
  31. package/js/src/abstract/weex.js +11 -0
  32. package/js/src/base/Exchange.d.ts +5 -1
  33. package/js/src/base/Exchange.js +48 -13
  34. package/js/src/bitget.js +1 -0
  35. package/js/src/btcbox.js +1 -1
  36. package/js/src/bullish.js +2 -1
  37. package/js/src/gate.js +0 -1
  38. package/js/src/hibachi.js +1 -1
  39. package/js/src/kraken.js +1 -0
  40. package/js/src/krakenfutures.js +10 -1
  41. package/js/src/kucoin.d.ts +4 -0
  42. package/js/src/kucoin.js +5 -1
  43. package/js/src/lighter.d.ts +12 -2
  44. package/js/src/lighter.js +313 -145
  45. package/js/src/mexc.d.ts +2 -0
  46. package/js/src/mexc.js +7 -12
  47. package/js/src/okx.js +46 -1
  48. package/js/src/paradex.js +5 -2
  49. package/js/src/pro/binance.js +1 -1
  50. package/js/src/pro/cex.js +1 -1
  51. package/js/src/pro/coinbase.js +1 -1
  52. package/js/src/pro/hyperliquid.d.ts +48 -1
  53. package/js/src/pro/hyperliquid.js +362 -2
  54. package/js/src/pro/lighter.d.ts +37 -2
  55. package/js/src/pro/lighter.js +339 -18
  56. package/js/src/pro/weex.d.ts +330 -0
  57. package/js/src/pro/weex.js +1905 -0
  58. package/js/src/weex.d.ts +675 -0
  59. package/js/src/weex.js +3822 -0
  60. package/package.json +1 -1
package/js/src/lighter.js CHANGED
@@ -6,9 +6,12 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import Exchange from './abstract/lighter.js';
9
- import { ArgumentsRequired, BadRequest, ExchangeError, InvalidOrder, RateLimitExceeded } from './base/errors.js';
9
+ import { ArgumentsRequired, BadRequest, ExchangeError, InvalidOrder, NotSupported, RateLimitExceeded } from './base/errors.js';
10
10
  import { TICK_SIZE } from './base/functions/number.js';
11
11
  import Precise from './base/Precise.js';
12
+ import { ecdsa } from './base/functions/crypto.js';
13
+ import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js';
14
+ import { secp256k1 } from './static_dependencies/noble-curves/secp256k1.js';
12
15
  // ---------------------------------------------------------------------------
13
16
  /**
14
17
  * @class lighter
@@ -25,6 +28,7 @@ export default class lighter extends Exchange {
25
28
  'certified': false,
26
29
  'pro': true,
27
30
  'dex': true,
31
+ 'quoteJsonNumbers': false,
28
32
  'has': {
29
33
  'CORS': undefined,
30
34
  'spot': false,
@@ -247,6 +251,7 @@ export default class lighter extends Exchange {
247
251
  'httpExceptions': {},
248
252
  'exceptions': {
249
253
  'exact': {
254
+ '21146': ExchangeError,
250
255
  '21500': ExchangeError,
251
256
  '21501': ExchangeError,
252
257
  '21502': ExchangeError,
@@ -340,11 +345,16 @@ export default class lighter extends Exchange {
340
345
  'commonCurrencies': {},
341
346
  'options': {
342
347
  'defaultType': 'swap',
348
+ 'builderFee': true,
343
349
  'chainId': 304,
344
350
  'accountIndex': undefined,
345
351
  'apiKeyIndex': undefined,
352
+ 'lighterPrivateKey': undefined,
346
353
  'wasmExecPath': undefined,
347
354
  'libraryPath': undefined,
355
+ 'integratorAccountIndex': 718718,
356
+ 'integratorMakerFee': 1000,
357
+ 'integratorTakerFee': 1000,
348
358
  'authDeadlineExpiry': 28800,
349
359
  'authDeadlineMinimumRemaining': 60,
350
360
  },
@@ -370,16 +380,66 @@ export default class lighter extends Exchange {
370
380
  });
371
381
  }
372
382
  async loadAccount(chainId, privateKey, apiKeyIndex, accountIndex, params = {}) {
373
- let signer = this.safeDict(this.options, 'signer');
383
+ this.initAuthObject(accountIndex, apiKeyIndex);
384
+ const cachedAuths = this.safeDict(this.options['auths'][accountIndex], apiKeyIndex);
385
+ let signer = this.safeValue(cachedAuths, 'signer');
374
386
  if (signer !== undefined) {
375
387
  return signer;
376
388
  }
377
389
  let libraryPath = undefined;
378
390
  [libraryPath, params] = this.handleOptionAndParams(params, 'loadAccount', 'libraryPath');
379
- signer = await this.loadLighterLibrary(libraryPath, chainId, privateKey, apiKeyIndex, accountIndex);
380
- this.options['signer'] = signer;
391
+ const lighterPrivateKeyIsSet = (privateKey !== undefined) && (privateKey !== '');
392
+ if (lighterPrivateKeyIsSet && (libraryPath !== undefined) && (apiKeyIndex !== undefined) && (accountIndex !== undefined)) {
393
+ // load lighter library, and create lighter client
394
+ signer = await this.loadLighterLibrary(libraryPath, chainId, privateKey, this.parseToInt(apiKeyIndex), this.parseToInt(accountIndex), true);
395
+ this.options['auths'][accountIndex][apiKeyIndex]['signer'] = signer;
396
+ return signer;
397
+ }
398
+ const privateKeyIsSet = (this.privateKey !== undefined) && (this.privateKey !== '');
399
+ if (privateKeyIsSet && (apiKeyIndex !== undefined) && (accountIndex !== undefined)) {
400
+ if (this.privateKey.length > 66) {
401
+ throw new NotSupported(this.id + ' after the latest update (v4.5.50), CCXT now expects the l1 private key to be provided in the credentials. Please check for more details: https://github.com/ccxt/ccxt/wiki/FAQ#how-to-use-the-lighter-exchange-in-ccxt');
402
+ }
403
+ // load lighter library without creating lighter client
404
+ signer = await this.loadLighterLibrary(libraryPath, chainId, '', this.parseToInt(apiKeyIndex), this.parseToInt(accountIndex), false);
405
+ this.options['auths'][accountIndex][apiKeyIndex]['signer'] = signer;
406
+ const res = await this.changeApiKey();
407
+ await this.handleBuilderFeeApproval(this.parseToInt(accountIndex), this.parseToInt(apiKeyIndex));
408
+ return res;
409
+ }
381
410
  return signer;
382
411
  }
412
+ initAuthObject(strAccountIndex, strApiKeyIndex) {
413
+ if (!('auths' in this.options)) {
414
+ this.options['auths'] = {};
415
+ }
416
+ if (!(strAccountIndex in this.options['auths'])) {
417
+ this.options['auths'][strAccountIndex] = {};
418
+ }
419
+ if (!(strApiKeyIndex in this.options['auths'][strAccountIndex])) {
420
+ this.options['auths'][strAccountIndex][strApiKeyIndex] = {
421
+ 'signer': undefined,
422
+ 'lighterPrivateKey': undefined,
423
+ 'deadline': undefined,
424
+ 'token': undefined,
425
+ };
426
+ }
427
+ }
428
+ getLighterPrivateKey(strAccountIndex, strApiKeyIndex) {
429
+ if (!('auths' in this.options)) {
430
+ return undefined;
431
+ }
432
+ if (!(strAccountIndex in this.options['auths'])) {
433
+ return undefined;
434
+ }
435
+ if (!(strApiKeyIndex in this.options['auths'][strAccountIndex])) {
436
+ return undefined;
437
+ }
438
+ if (!('lighterPrivateKey' in this.options['auths'][strAccountIndex][strApiKeyIndex])) {
439
+ return undefined;
440
+ }
441
+ return this.options['auths'][strAccountIndex][strApiKeyIndex]['lighterPrivateKey'];
442
+ }
383
443
  /**
384
444
  * @method
385
445
  * @name lighter#preLoadLighterLibrary
@@ -388,31 +448,47 @@ export default class lighter extends Exchange {
388
448
  * @returns {boolean} true if the signer was loaded, false otherwise
389
449
  */
390
450
  async preLoadLighterLibrary(params = {}) {
391
- let signer = this.safeDict(this.options, 'signer');
451
+ let apiKeyIndex = undefined;
452
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'loadAccount', 'apiKeyIndex', 'api_key_index');
453
+ let accountIndex = undefined;
454
+ [accountIndex, params] = await this.handleAccountIndex(params, 'loadAccount', 'accountIndex', 'account_index');
455
+ if (accountIndex === undefined) {
456
+ throw new ArgumentsRequired(this.id + ' requires accountIndex or account_index');
457
+ }
458
+ const strAccountIndex = this.numberToString(accountIndex);
459
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
460
+ this.initAuthObject(strAccountIndex, strApiKeyIndex);
461
+ let signer = this.safeDict(this.options['auths'][strAccountIndex][strApiKeyIndex], 'signer');
392
462
  if (signer !== undefined) {
393
463
  return true;
394
464
  }
395
- let libraryPath = undefined;
396
- [libraryPath, params] = this.handleOptionAndParams(params, 'loadAccount', 'libraryPath');
465
+ signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex);
466
+ await this.handleBuilderFeeApproval(accountIndex, apiKeyIndex);
467
+ return (signer !== undefined);
468
+ }
469
+ handleApiKeyIndex(params, methodName1, optionName1, optionName2, defaultValue = undefined) {
397
470
  let apiKeyIndex = undefined;
398
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'loadAccount', 'apiKeyIndex', 'api_key_index');
399
- let accountIndex = undefined;
400
- [accountIndex, params] = this.handleOptionAndParams2(params, 'loadAccount', 'accountIndex', 'account_index');
401
- const privateKeyIsSet = (this.privateKey !== undefined) && (this.privateKey !== '');
402
- if (privateKeyIsSet && (libraryPath !== undefined) && (apiKeyIndex !== undefined) && (accountIndex !== undefined)) {
403
- signer = await this.loadLighterLibrary(libraryPath, this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex);
404
- this.options['signer'] = signer;
405
- return true;
471
+ [apiKeyIndex, params] = this.handleOptionAndParams2(params, methodName1, optionName1, optionName2, defaultValue);
472
+ if ((apiKeyIndex === undefined) || (apiKeyIndex < 4) || (apiKeyIndex > 254)) {
473
+ // apiKeyIndex = this.randNumber (2);
474
+ apiKeyIndex = 254;
475
+ this.options['apiKeyIndex'] = apiKeyIndex; // default to a value to avoid overriding other keys
406
476
  }
407
- return false;
477
+ return [this.parseToInt(apiKeyIndex), params];
408
478
  }
409
479
  async handleAccountIndex(params, methodName1, optionName1, optionName2, defaultValue = undefined) {
410
480
  let accountIndex = undefined;
411
481
  [accountIndex, params] = this.handleOptionAndParams2(params, methodName1, optionName1, optionName2, defaultValue);
412
482
  if (accountIndex === undefined) {
413
- const walletAddress = this.walletAddress;
483
+ let walletAddress = this.walletAddress;
484
+ if (this.privateKey !== undefined) {
485
+ if (this.privateKey.length > 66) {
486
+ throw new NotSupported(this.id + ' after the latest update (v4.5.50), CCXT now expects the l1 private key to be provided in the credentials. Please check for more details: https://github.com/ccxt/ccxt/wiki/FAQ#how-to-use-the-lighter-exchange-in-ccxt');
487
+ }
488
+ walletAddress = this.ethGetAddressFromPrivateKey(this.privateKey);
489
+ }
414
490
  if (walletAddress === undefined || walletAddress === '') {
415
- throw new ArgumentsRequired(this.id + ' ' + methodName1 + '() requires an ' + optionName1 + '/' + optionName2 + ' parameter or walletAddress to fetch accountIndex');
491
+ throw new ArgumentsRequired(this.id + ' ' + methodName1 + '() requires an ' + optionName1 + '/' + optionName2 + ' parameter or walletAddress to fetch accountIndex. Alternatively set privateKey in credentials to enable automatic walletAddress detection.');
416
492
  }
417
493
  const res = await this.publicGetAccountsByL1Address({ 'l1_address': walletAddress });
418
494
  //
@@ -452,19 +528,18 @@ export default class lighter extends Exchange {
452
528
  }
453
529
  async createSubAccount(name, params = {}) {
454
530
  let apiKeyIndex = undefined;
455
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'createSubAccount', 'apiKeyIndex', 'api_key_index');
456
- if (apiKeyIndex === undefined) {
457
- throw new ArgumentsRequired(this.id + ' createSubAccount() requires an apiKeyIndex parameter');
458
- }
531
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'createSubAccount', 'apiKeyIndex', 'api_key_index');
459
532
  let accountIndex = undefined;
460
533
  [accountIndex, params] = await this.handleAccountIndex(params, 'createSubAccount', 'accountIndex', 'account_index');
461
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
534
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
462
535
  const signRaw = {
463
536
  'nonce': nonce,
464
537
  'api_key_index': apiKeyIndex,
465
538
  'account_index': accountIndex,
466
539
  };
467
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
540
+ const strAccountIndex = this.numberToString(accountIndex);
541
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
542
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
468
543
  const [txType, txInfo] = this.lighterSignCreateSubAccount(signer, this.extend(signRaw, params));
469
544
  const request = {
470
545
  'tx_type': txType,
@@ -474,15 +549,15 @@ export default class lighter extends Exchange {
474
549
  }
475
550
  createAuth(params = {}) {
476
551
  // don't omit [accountIndex, apiKeyIndex], request may need them
477
- let apiKeyIndex = this.safeInteger2(params, 'apiKeyIndex', 'api_key_index');
552
+ let apiKeyIndex = this.safeString2(params, 'apiKeyIndex', 'api_key_index');
478
553
  if (apiKeyIndex === undefined) {
479
554
  const res = this.handleOptionAndParams2({}, 'createAuth', 'apiKeyIndex', 'api_key_index');
480
- apiKeyIndex = this.safeInteger(res, 0);
555
+ apiKeyIndex = this.safeString(res, 0);
481
556
  }
482
- let accountIndex = this.safeInteger2(params, 'accountIndex', 'account_index');
557
+ let accountIndex = this.safeString2(params, 'accountIndex', 'account_index');
483
558
  if (accountIndex === undefined) {
484
559
  const res = this.handleOptionAndParams2({}, 'createAuth', 'accountIndex', 'account_index');
485
- accountIndex = this.safeInteger(res, 0);
560
+ accountIndex = this.safeString(res, 0);
486
561
  }
487
562
  const auths = this.safeDict(this.options, 'auths');
488
563
  const accountAuths = this.safeDict(auths, accountIndex);
@@ -497,20 +572,12 @@ export default class lighter extends Exchange {
497
572
  const deadline = this.seconds() + this.safeInteger(this.options, 'authDeadlineExpiry');
498
573
  const request = {
499
574
  'deadline': deadline,
500
- 'api_key_index': apiKeyIndex,
501
- 'account_index': accountIndex,
502
- };
503
- const token = this.lighterCreateAuthToken(this.safeValue(this.options, 'signer'), request);
504
- if (!('auths' in this.options)) {
505
- this.options['auths'] = {};
506
- }
507
- if (!(accountIndex in this.options['auths'])) {
508
- this.options['auths'][accountIndex] = {};
509
- }
510
- this.options['auths'][accountIndex][apiKeyIndex] = {
511
- 'deadline': deadline,
512
- 'token': token,
575
+ 'api_key_index': this.parseToInt(apiKeyIndex),
576
+ 'account_index': this.parseToInt(accountIndex),
513
577
  };
578
+ const token = this.lighterCreateAuthToken(this.options['auths'][accountIndex][apiKeyIndex]['signer'], request);
579
+ this.options['auths'][accountIndex][apiKeyIndex]['deadline'] = deadline;
580
+ this.options['auths'][accountIndex][apiKeyIndex]['token'] = token;
514
581
  return token;
515
582
  }
516
583
  pow(n, m) {
@@ -530,6 +597,104 @@ export default class lighter extends Exchange {
530
597
  }
531
598
  return r;
532
599
  }
600
+ hashMessage(message) {
601
+ const binaryMessage = this.encode(message);
602
+ const binaryMessageLength = this.binaryLength(binaryMessage);
603
+ const x19 = this.base16ToBinary('19');
604
+ const newline = this.base16ToBinary('0a');
605
+ const prefix = this.binaryConcat(x19, this.encode('Ethereum Signed Message:'), newline, this.encode(this.numberToString(binaryMessageLength)));
606
+ return '0x' + this.hash(this.binaryConcat(prefix, binaryMessage), keccak, 'hex');
607
+ }
608
+ signHash(hash, privateKey) {
609
+ this.checkRequiredCredentials();
610
+ const signature = ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1, undefined);
611
+ const r = signature['r'];
612
+ const s = signature['s'];
613
+ const v = this.intToBase16(this.sum(27, signature['v']));
614
+ return '0x' + r.padStart(64, '0') + s.padStart(64, '0') + v;
615
+ }
616
+ signL1AndPrepareTxInfo(txInfo, message, privateKey) {
617
+ const hashMessage = this.hashMessage(message);
618
+ const signature = this.signHash(hashMessage, privateKey);
619
+ const decTxInfo = this.parseJson(txInfo);
620
+ decTxInfo['L1Sig'] = signature;
621
+ return this.json(decTxInfo);
622
+ }
623
+ async handleBuilderFeeApproval(accountIndex, apiKeyIndex) {
624
+ const buildFee = this.safeBool(this.options, 'builderFee', true);
625
+ if (!buildFee) {
626
+ return false;
627
+ }
628
+ const approvedBuilderFee = this.safeBool(this.options, 'approvedBuilderFee', false);
629
+ if (approvedBuilderFee) {
630
+ return true;
631
+ }
632
+ try {
633
+ const builder = this.safeInteger(this.options, 'integratorAccountIndex', 718718);
634
+ const takerFeeRate = this.safeInteger(this.options, 'integratorTakerFee', 1000);
635
+ const makerFeeRate = this.safeInteger(this.options, 'integratorMakerFee', 1000);
636
+ await this.approveBuilderFee(builder, takerFeeRate, makerFeeRate, accountIndex, apiKeyIndex);
637
+ this.options['approvedBuilderFee'] = true;
638
+ }
639
+ catch (e) {
640
+ this.options['builderFee'] = false;
641
+ }
642
+ return true;
643
+ }
644
+ async approveBuilderFee(builder, takerFeeRate, makerFeeRate, accountIndex, apiKeyIndex, params = {}) {
645
+ const strAccountIndex = this.numberToString(accountIndex);
646
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
647
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
648
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
649
+ const expiry = this.milliseconds() + 365 * 864000;
650
+ const signRaw = {
651
+ 'integrator_account_index': builder,
652
+ 'integrator_taker_fee': takerFeeRate,
653
+ 'integrator_maker_fee': makerFeeRate,
654
+ 'approval_expiry': expiry,
655
+ 'nonce': nonce,
656
+ 'api_key_index': apiKeyIndex,
657
+ 'account_index': accountIndex,
658
+ };
659
+ const [txType, txInfo, messageToSign] = this.lighterSignApproveIntegrator(signer, this.extend(signRaw, params));
660
+ const newTxInfo = this.signL1AndPrepareTxInfo(txInfo, messageToSign, this.privateKey);
661
+ const request = {
662
+ 'tx_type': txType,
663
+ 'tx_info': newTxInfo,
664
+ };
665
+ const response = await this.publicPostSendTx(request);
666
+ return response;
667
+ }
668
+ async changeApiKey(params = {}) {
669
+ let apiKeyIndex = undefined;
670
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'changeApiKey', 'apiKeyIndex', 'api_key_index');
671
+ let accountIndex = undefined;
672
+ [accountIndex, params] = await this.handleAccountIndex(params, 'changeApiKey', 'accountIndex', 'account_index');
673
+ const strAccountIndex = this.numberToString(accountIndex);
674
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
675
+ const signerNotLoad = this.options['auths'][strAccountIndex][strApiKeyIndex]['signer'];
676
+ const [privateKey, publicKey] = this.lighterGenerateApiKey(signerNotLoad);
677
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
678
+ const signRaw = {
679
+ 'pubkey': this.encode(publicKey),
680
+ 'nonce': nonce,
681
+ 'api_key_index': apiKeyIndex,
682
+ 'account_index': accountIndex,
683
+ };
684
+ // create lighter client
685
+ const signer = this.lighterCreateClient(signerNotLoad, this.options['chainId'], privateKey, apiKeyIndex, accountIndex);
686
+ const [txType, txInfo, messageToSign] = this.lighterSignChangePubkey(signer, this.extend(signRaw, params));
687
+ const newTxInfo = this.signL1AndPrepareTxInfo(txInfo, messageToSign, this.privateKey);
688
+ const request = {
689
+ 'tx_type': txType,
690
+ 'tx_info': newTxInfo,
691
+ };
692
+ await this.publicPostSendTx(request);
693
+ this.options['auths'][strAccountIndex][strApiKeyIndex]['lighterPrivateKey'] = privateKey;
694
+ this.options['auths'][strAccountIndex][strApiKeyIndex]['signer'] = signer; // reassign signer in go
695
+ await this.handleBuilderFeeApproval(accountIndex, apiKeyIndex);
696
+ return signer;
697
+ }
533
698
  setSandboxMode(enable) {
534
699
  super.setSandboxMode(enable);
535
700
  this.options['sandboxMode'] = enable;
@@ -567,14 +732,13 @@ export default class lighter extends Exchange {
567
732
  let apiKeyIndex = undefined;
568
733
  let accountIndex = undefined;
569
734
  let orderExpiry = undefined;
570
- [apiKeyIndex, params] = this.handleOptionAndParams(params, 'createOrder', 'apiKeyIndex', 255);
571
- if (apiKeyIndex === undefined) {
572
- throw new ArgumentsRequired(this.id + ' createOrder() requires an apiKeyIndex parameter');
573
- }
735
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'createOrder', 'apiKeyIndex', 'api_key_index');
574
736
  [accountIndex, params] = this.handleOptionAndParams2(params, 'createOrder', 'accountIndex', 'account_index');
575
737
  [nonce, params] = this.handleOptionAndParams(params, 'createOrder', 'nonce');
576
738
  [orderExpiry, params] = this.handleOptionAndParams(params, 'createOrder', 'orderExpiry', 0);
577
- request['nonce'] = nonce;
739
+ if (nonce !== undefined) {
740
+ request['nonce'] = nonce;
741
+ }
578
742
  request['api_key_index'] = apiKeyIndex;
579
743
  request['account_index'] = this.parseToInt(accountIndex);
580
744
  const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
@@ -660,6 +824,11 @@ export default class lighter extends Exchange {
660
824
  request['base_amount'] = this.parseToInt(Precise.stringMul(amountStr, amountScale));
661
825
  request['avg_execution_price'] = this.parseToInt(Precise.stringMul(priceStr, priceScale));
662
826
  request['trigger_price'] = this.parseToInt(Precise.stringMul(triggerPriceStr, priceScale));
827
+ if (this.safeBool(this.options, 'builderFee', true)) {
828
+ request['integrator_account_index'] = this.options['integratorAccountIndex'];
829
+ request['integrator_taker_fee'] = this.options['integratorTakerFee'];
830
+ request['integrator_maker_fee'] = this.options['integratorMakerFee'];
831
+ }
663
832
  const orders = [];
664
833
  orders.push(this.extend(request, params));
665
834
  if (hasStopLoss || hasTakeProfit) {
@@ -748,17 +917,14 @@ export default class lighter extends Exchange {
748
917
  if (totalOrderRequests > 0) {
749
918
  order = orderRequests[0];
750
919
  apiKeyIndex = order['api_key_index'];
751
- if (order['nonce'] === undefined) {
752
- const nonceInOptions = this.safeInteger(this.options, 'nonce');
753
- if (nonceInOptions !== undefined) {
754
- order['nonce'] = nonceInOptions;
755
- }
756
- else {
757
- order['nonce'] = await this.fetchNonce(accountIndex, apiKeyIndex);
758
- }
759
- }
760
920
  }
761
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
921
+ const strAccountIndex = this.numberToString(accountIndex);
922
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
923
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
924
+ // the nonce could be updated
925
+ if (this.safeInteger(order, 'nonce') === undefined) {
926
+ order['nonce'] = await this.fetchNonce(accountIndex, apiKeyIndex);
927
+ }
762
928
  let txType = undefined;
763
929
  let txInfo = undefined;
764
930
  if (totalOrderRequests < 2) {
@@ -772,6 +938,11 @@ export default class lighter extends Exchange {
772
938
  'api_key_index': apiKeyIndex,
773
939
  'account_index': accountIndex,
774
940
  };
941
+ if (this.safeBool(this.options, 'builderFee', true)) {
942
+ signingPayload['integrator_account_index'] = order['integrator_account_index'];
943
+ signingPayload['integrator_taker_fee'] = order['integrator_taker_fee'];
944
+ signingPayload['integrator_maker_fee'] = order['integrator_maker_fee'];
945
+ }
775
946
  [txType, txInfo] = this.lighterSignCreateGroupedOrders(signer, signingPayload);
776
947
  }
777
948
  const request = {
@@ -805,17 +976,16 @@ export default class lighter extends Exchange {
805
976
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
806
977
  */
807
978
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
808
- let apiKeyIndex = undefined;
809
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'editOrder', 'apiKeyIndex', 'api_key_index');
810
- if (apiKeyIndex === undefined) {
811
- throw new ArgumentsRequired(this.id + ' editOrder() requires an apiKeyIndex parameter');
812
- }
813
979
  await this.loadMarkets();
980
+ let apiKeyIndex = undefined;
981
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'editOrder', 'apiKeyIndex', 'api_key_index');
814
982
  let accountIndex = undefined;
815
983
  [accountIndex, params] = await this.handleAccountIndex(params, 'editOrder', 'accountIndex', 'account_index');
984
+ const strAccountIndex = this.numberToString(accountIndex);
985
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
986
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
816
987
  const market = this.market(symbol);
817
988
  const marketInfo = this.safeDict(market, 'info');
818
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
819
989
  const amountScale = this.pow('10', marketInfo['size_decimals']);
820
990
  const priceScale = this.pow('10', marketInfo['price_decimals']);
821
991
  const triggerPrice = this.safeStringN(params, ['stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
@@ -830,6 +1000,7 @@ export default class lighter extends Exchange {
830
1000
  else {
831
1001
  amountStr = this.amountToPrecision(symbol, amount);
832
1002
  }
1003
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
833
1004
  const signRaw = {
834
1005
  'market_index': this.parseToInt(market['id']),
835
1006
  'index': this.parseToInt(id),
@@ -839,8 +1010,10 @@ export default class lighter extends Exchange {
839
1010
  'nonce': nonce,
840
1011
  'api_key_index': apiKeyIndex,
841
1012
  'account_index': accountIndex,
1013
+ 'integrator_account_index': this.options['integratorAccountIndex'],
1014
+ 'integrator_taker_fee': this.options['integratorTakerFee'],
1015
+ 'integrator_maker_fee': this.options['integratorMakerFee'],
842
1016
  };
843
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
844
1017
  const [txType, txInfo] = this.lighterSignModifyOrder(signer, this.extend(signRaw, params));
845
1018
  const request = {
846
1019
  'tx_type': txType,
@@ -1075,7 +1248,9 @@ export default class lighter extends Exchange {
1075
1248
  */
1076
1249
  async fetchCurrencies(params = {}) {
1077
1250
  const response = await this.publicGetAssetDetails(params);
1078
- await this.preLoadLighterLibrary();
1251
+ if (this.checkRequiredCredentials(false)) {
1252
+ await this.preLoadLighterLibrary();
1253
+ }
1079
1254
  //
1080
1255
  // {
1081
1256
  // "code": 200,
@@ -1554,6 +1729,7 @@ export default class lighter extends Exchange {
1554
1729
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1555
1730
  * @param {string} [params.by] fetch balance by 'index' or 'l1_address', defaults to 'index'
1556
1731
  * @param {string} [params.value] fetch balance value, account index or l1 address
1732
+ * @param {string} [params.type] 'spot', 'swap', default is 'swap'
1557
1733
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
1558
1734
  */
1559
1735
  async fetchBalance(params = {}) {
@@ -1628,9 +1804,11 @@ export default class lighter extends Exchange {
1628
1804
  }
1629
1805
  }
1630
1806
  else {
1631
- const perpUSDC = this.safeString(account, 'collateral');
1632
- const perpBalance = this.safeDict(result, 'USDC(PERP)', this.account());
1633
- perpBalance['total'] = Precise.stringAdd(perpBalance['total'], perpUSDC);
1807
+ const perpBalance = this.safeDict(result, 'USDC', this.account());
1808
+ const perpUSDCTotal = this.safeString(account, 'collateral');
1809
+ const perpUSDCFree = this.safeString(account, 'available_balance');
1810
+ perpBalance['total'] = Precise.stringAdd(perpBalance['total'], perpUSDCTotal);
1811
+ perpBalance['free'] = Precise.stringAdd(perpBalance['free'], perpUSDCFree);
1634
1812
  result['USDC'] = perpBalance;
1635
1813
  }
1636
1814
  }
@@ -1904,11 +2082,10 @@ export default class lighter extends Exchange {
1904
2082
  let accountIndex = undefined;
1905
2083
  [accountIndex, params] = await this.handleAccountIndex(params, 'fetchOpenOrders', 'accountIndex', 'account_index');
1906
2084
  let apiKeyIndex = undefined;
1907
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'fetchOpenOrders', 'apiKeyIndex', 'api_key_index');
1908
- if (apiKeyIndex === undefined) {
1909
- throw new ArgumentsRequired(this.id + ' fetchOpenOrders() requires an apiKeyIndex parameter');
1910
- }
1911
- await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2085
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'fetchOpenOrders', 'apiKeyIndex', 'api_key_index');
2086
+ const strAccountIndex = this.numberToString(accountIndex);
2087
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2088
+ await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
1912
2089
  const market = this.market(symbol);
1913
2090
  const request = {
1914
2091
  'market_id': market['id'],
@@ -1980,11 +2157,10 @@ export default class lighter extends Exchange {
1980
2157
  let accountIndex = undefined;
1981
2158
  [accountIndex, params] = await this.handleAccountIndex(params, 'fetchClosedOrders', 'accountIndex', 'account_index');
1982
2159
  let apiKeyIndex = undefined;
1983
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'fetchClosedOrders', 'apiKeyIndex', 'api_key_index');
1984
- if (apiKeyIndex === undefined) {
1985
- throw new ArgumentsRequired(this.id + ' fetchClosedOrders() requires an apiKeyIndex parameter');
1986
- }
1987
- await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2160
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'fetchClosedOrders', 'apiKeyIndex', 'api_key_index');
2161
+ const strAccountIndex = this.numberToString(accountIndex);
2162
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2163
+ await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
1988
2164
  const market = this.market(symbol);
1989
2165
  const request = {
1990
2166
  'market_id': market['id'],
@@ -2238,16 +2414,16 @@ export default class lighter extends Exchange {
2238
2414
  * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/?id=transfer-structure}
2239
2415
  */
2240
2416
  async transfer(code, amount, fromAccount, toAccount, params = {}) {
2241
- let apiKeyIndex = undefined;
2242
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'transfer', 'apiKeyIndex', 'api_key_index');
2243
- if (apiKeyIndex === undefined) {
2244
- throw new ArgumentsRequired(this.id + ' transfer() requires an apiKeyIndex parameter');
2245
- }
2246
2417
  await this.loadMarkets();
2418
+ let apiKeyIndex = undefined;
2419
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'transfer', 'apiKeyIndex', 'api_key_index');
2247
2420
  let accountIndex = undefined;
2248
2421
  [accountIndex, params] = await this.handleAccountIndex(params, 'transfer', 'accountIndex', 'account_index');
2249
2422
  let toAccountIndex = undefined;
2250
2423
  [toAccountIndex, params] = this.handleOptionAndParams2(params, 'transfer', 'toAccountIndex', 'to_account_index', accountIndex);
2424
+ const strAccountIndex = this.numberToString(accountIndex);
2425
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2426
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2251
2427
  const currency = this.currency(code);
2252
2428
  if (currency['code'] === 'USDC') {
2253
2429
  amount = this.parseToInt(Precise.stringMul(this.pow('10', '6'), this.currencyToPrecision(code, amount)));
@@ -2260,9 +2436,9 @@ export default class lighter extends Exchange {
2260
2436
  }
2261
2437
  const fromRouteType = (fromAccount === 'perp') ? 0 : 1; // 0: perp, 1: spot
2262
2438
  const toRouteType = (toAccount === 'perp') ? 0 : 1;
2263
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
2264
2439
  const memo = this.safeString(params, 'memo', '0x000000000000000000000000000000');
2265
2440
  params = this.omit(params, ['memo']);
2441
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
2266
2442
  const signRaw = {
2267
2443
  'to_account_index': toAccountIndex,
2268
2444
  'asset_index': this.parseToInt(currency['id']),
@@ -2275,7 +2451,6 @@ export default class lighter extends Exchange {
2275
2451
  'api_key_index': apiKeyIndex,
2276
2452
  'account_index': accountIndex,
2277
2453
  };
2278
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2279
2454
  const [txType, txInfo] = this.lighterSignTransfer(signer, this.extend(signRaw, params));
2280
2455
  const request = {
2281
2456
  'tx_type': txType,
@@ -2298,6 +2473,7 @@ export default class lighter extends Exchange {
2298
2473
  * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/?id=transfer-structure}
2299
2474
  */
2300
2475
  async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
2476
+ await this.loadMarkets();
2301
2477
  let paginate = false;
2302
2478
  [paginate, params] = this.handleOptionAndParams(params, 'fetchTransfers', 'paginate');
2303
2479
  if (paginate) {
@@ -2309,11 +2485,10 @@ export default class lighter extends Exchange {
2309
2485
  'account_index': accountIndex,
2310
2486
  };
2311
2487
  let apiKeyIndex = undefined;
2312
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'fetchTransfers', 'apiKeyIndex', 'api_key_index');
2313
- if (apiKeyIndex === undefined) {
2314
- throw new ArgumentsRequired(this.id + ' fetchTransfers() requires an apiKeyIndex parameter');
2315
- }
2316
- await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2488
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'fetchTransfers', 'apiKeyIndex', 'api_key_index');
2489
+ const strAccountIndex = this.numberToString(accountIndex);
2490
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2491
+ await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2317
2492
  let currency = undefined;
2318
2493
  if (code !== undefined) {
2319
2494
  currency = this.currency(code);
@@ -2400,6 +2575,7 @@ export default class lighter extends Exchange {
2400
2575
  * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/?id=transaction-structure}
2401
2576
  */
2402
2577
  async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2578
+ await this.loadMarkets();
2403
2579
  let paginate = false;
2404
2580
  [paginate, params] = this.handleOptionAndParams(params, 'fetchDeposits', 'paginate');
2405
2581
  if (paginate) {
@@ -2410,7 +2586,6 @@ export default class lighter extends Exchange {
2410
2586
  if (address === undefined) {
2411
2587
  throw new ArgumentsRequired(this.id + ' fetchDeposits() requires an address parameter');
2412
2588
  }
2413
- await this.loadMarkets();
2414
2589
  let accountIndex = undefined;
2415
2590
  [accountIndex, params] = await this.handleAccountIndex(params, 'fetchDeposits', 'accountIndex', 'account_index');
2416
2591
  const request = {
@@ -2418,11 +2593,10 @@ export default class lighter extends Exchange {
2418
2593
  'l1_address': address,
2419
2594
  };
2420
2595
  let apiKeyIndex = undefined;
2421
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'fetchDeposits', 'apiKeyIndex', 'api_key_index');
2422
- if (apiKeyIndex === undefined) {
2423
- throw new ArgumentsRequired(this.id + ' fetchDeposits() requires an apiKeyIndex parameter');
2424
- }
2425
- await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2596
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'fetchDeposits', 'apiKeyIndex', 'api_key_index');
2597
+ const strAccountIndex = this.numberToString(accountIndex);
2598
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2599
+ await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2426
2600
  let currency = undefined;
2427
2601
  if (code !== undefined) {
2428
2602
  currency = this.currency(code);
@@ -2479,11 +2653,10 @@ export default class lighter extends Exchange {
2479
2653
  'account_index': accountIndex,
2480
2654
  };
2481
2655
  let apiKeyIndex = undefined;
2482
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'fetchWithdrawals', 'apiKeyIndex', 'api_key_index');
2483
- if (apiKeyIndex === undefined) {
2484
- throw new ArgumentsRequired(this.id + ' fetchWithdrawals() requires an apiKeyIndex parameter');
2485
- }
2486
- await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2656
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'fetchWithdrawals', 'apiKeyIndex', 'api_key_index');
2657
+ const strAccountIndex = this.numberToString(accountIndex);
2658
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2659
+ await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2487
2660
  let currency = undefined;
2488
2661
  if (code !== undefined) {
2489
2662
  currency = this.currency(code);
@@ -2593,14 +2766,14 @@ export default class lighter extends Exchange {
2593
2766
  * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/?id=transaction-structure}
2594
2767
  */
2595
2768
  async withdraw(code, amount, address, tag = undefined, params = {}) {
2596
- let apiKeyIndex = undefined;
2597
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'withdraw', 'apiKeyIndex', 'api_key_index');
2598
- if (apiKeyIndex === undefined) {
2599
- throw new ArgumentsRequired(this.id + ' withdraw() requires an apiKeyIndex parameter');
2600
- }
2601
2769
  await this.loadMarkets();
2770
+ let apiKeyIndex = undefined;
2771
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'withdraw', 'apiKeyIndex', 'api_key_index');
2602
2772
  let accountIndex = undefined;
2603
2773
  [accountIndex, params] = await this.handleAccountIndex(params, 'withdraw', 'accountIndex', 'account_index');
2774
+ const strAccountIndex = this.numberToString(accountIndex);
2775
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2776
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2604
2777
  const currency = this.currency(code);
2605
2778
  if (currency['code'] === 'USDC') {
2606
2779
  amount = this.parseToInt(Precise.stringMul(this.pow('10', '6'), this.currencyToPrecision(code, amount)));
@@ -2613,7 +2786,7 @@ export default class lighter extends Exchange {
2613
2786
  }
2614
2787
  const routeType = this.safeInteger(params, 'routeType', 0); // 0: perp, 1: spot
2615
2788
  params = this.omit(params, 'routeType');
2616
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
2789
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
2617
2790
  const signRaw = {
2618
2791
  'asset_index': this.parseToInt(currency['id']),
2619
2792
  'route_type': routeType,
@@ -2622,7 +2795,6 @@ export default class lighter extends Exchange {
2622
2795
  'api_key_index': apiKeyIndex,
2623
2796
  'account_index': accountIndex,
2624
2797
  };
2625
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2626
2798
  const [txType, txInfo] = this.lighterSignWithdraw(signer, this.extend(signRaw, params));
2627
2799
  const request = {
2628
2800
  'tx_type': txType,
@@ -2655,11 +2827,10 @@ export default class lighter extends Exchange {
2655
2827
  let accountIndex = undefined;
2656
2828
  [accountIndex, params] = await this.handleAccountIndex(params, 'fetchMyTrades', 'accountIndex', 'account_index');
2657
2829
  let apiKeyIndex = undefined;
2658
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'fetchMyTrades', 'apiKeyIndex', 'api_key_index');
2659
- if (apiKeyIndex === undefined) {
2660
- throw new ArgumentsRequired(this.id + ' fetchMyTrades() requires an apiKeyIndex parameter');
2661
- }
2662
- await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2830
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'fetchMyTrades', 'apiKeyIndex', 'api_key_index');
2831
+ const strAccountIndex = this.numberToString(accountIndex);
2832
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
2833
+ await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2663
2834
  const request = {
2664
2835
  'sort_by': 'timestamp',
2665
2836
  'limit': 100,
@@ -2835,22 +3006,22 @@ export default class lighter extends Exchange {
2835
3006
  return await this.modifyLeverageAndMarginMode(leverage, marginMode, symbol, params);
2836
3007
  }
2837
3008
  async modifyLeverageAndMarginMode(leverage, marginMode, symbol = undefined, params = {}) {
3009
+ await this.loadMarkets();
2838
3010
  if ((marginMode !== 'cross') && (marginMode !== 'isolated')) {
2839
3011
  throw new BadRequest(this.id + ' modifyLeverageAndMarginMode() requires a marginMode parameter that must be either cross or isolated');
2840
3012
  }
2841
3013
  let apiKeyIndex = undefined;
2842
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'modifyLeverageAndMarginMode', 'apiKeyIndex', 'api_key_index');
2843
- if (apiKeyIndex === undefined) {
2844
- throw new ArgumentsRequired(this.id + ' modifyLeverageAndMarginMode() requires an apiKeyIndex parameter');
2845
- }
3014
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'modifyLeverageAndMarginMode', 'apiKeyIndex', 'api_key_index');
2846
3015
  if (symbol === undefined) {
2847
3016
  throw new ArgumentsRequired(this.id + ' modifyLeverageAndMarginMode() requires a symbol argument');
2848
3017
  }
2849
- await this.loadMarkets();
2850
3018
  let accountIndex = undefined;
2851
3019
  [accountIndex, params] = await this.handleAccountIndex(params, 'modifyLeverageAndMarginMode', 'accountIndex', 'account_index');
3020
+ const strAccountIndex = this.numberToString(accountIndex);
3021
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
3022
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2852
3023
  const market = this.market(symbol);
2853
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
3024
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
2854
3025
  const signRaw = {
2855
3026
  'market_index': this.parseToInt(market['id']),
2856
3027
  'initial_margin_fraction': this.parseToInt(10000 / leverage),
@@ -2859,7 +3030,6 @@ export default class lighter extends Exchange {
2859
3030
  'api_key_index': apiKeyIndex,
2860
3031
  'account_index': accountIndex,
2861
3032
  };
2862
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2863
3033
  const [txType, txInfo] = this.lighterSignUpdateLeverage(signer, this.extend(signRaw, params));
2864
3034
  const request = {
2865
3035
  'tx_type': txType,
@@ -2879,21 +3049,21 @@ export default class lighter extends Exchange {
2879
3049
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
2880
3050
  */
2881
3051
  async cancelOrder(id, symbol = undefined, params = {}) {
3052
+ await this.loadMarkets();
2882
3053
  let apiKeyIndex = undefined;
2883
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'cancelOrder', 'apiKeyIndex', 'api_key_index');
2884
- if (apiKeyIndex === undefined) {
2885
- throw new ArgumentsRequired(this.id + ' cancelOrder() requires an apiKeyIndex parameter');
2886
- }
3054
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'cancelOrder', 'apiKeyIndex', 'api_key_index');
2887
3055
  if (symbol === undefined) {
2888
3056
  throw new ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
2889
3057
  }
3058
+ const market = this.market(symbol);
2890
3059
  const clientOrderId = this.safeString2(params, 'client_order_index', 'clientOrderId');
2891
3060
  params = this.omit(params, ['client_order_index', 'clientOrderId']);
2892
- await this.loadMarkets();
2893
3061
  let accountIndex = undefined;
2894
3062
  [accountIndex, params] = await this.handleAccountIndex(params, 'cancelOrder', 'accountIndex', 'account_index');
2895
- const market = this.market(symbol);
2896
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
3063
+ const strAccountIndex = this.numberToString(accountIndex);
3064
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
3065
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
3066
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
2897
3067
  const signRaw = {
2898
3068
  'market_index': this.parseToInt(market['id']),
2899
3069
  'nonce': nonce,
@@ -2909,7 +3079,6 @@ export default class lighter extends Exchange {
2909
3079
  else {
2910
3080
  throw new ArgumentsRequired(this.id + ' cancelOrder requires order id or client order id');
2911
3081
  }
2912
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2913
3082
  const [txType, txInfo] = this.lighterSignCancelOrder(signer, this.extend(signRaw, params));
2914
3083
  const request = {
2915
3084
  'tx_type': txType,
@@ -2929,13 +3098,14 @@ export default class lighter extends Exchange {
2929
3098
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
2930
3099
  */
2931
3100
  async cancelAllOrders(symbol = undefined, params = {}) {
3101
+ await this.loadMarkets();
2932
3102
  let apiKeyIndex = undefined;
2933
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'cancelAllOrders', 'apiKeyIndex', 'api_key_index');
2934
- if (apiKeyIndex === undefined) {
2935
- throw new ArgumentsRequired(this.id + ' cancelAllOrders() requires an apiKeyIndex parameter');
2936
- }
3103
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'cancelAllOrders', 'apiKeyIndex', 'api_key_index');
2937
3104
  let accountIndex = undefined;
2938
3105
  [accountIndex, params] = await this.handleAccountIndex(params, 'cancelAllOrders', 'accountIndex', 'account_index');
3106
+ const strAccountIndex = this.numberToString(accountIndex);
3107
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
3108
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
2939
3109
  const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
2940
3110
  const signRaw = {
2941
3111
  'time_in_force': 0,
@@ -2944,7 +3114,6 @@ export default class lighter extends Exchange {
2944
3114
  'api_key_index': apiKeyIndex,
2945
3115
  'account_index': accountIndex,
2946
3116
  };
2947
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2948
3117
  const [txType, txInfo] = this.lighterSignCancelAllOrders(signer, this.extend(signRaw, params));
2949
3118
  const request = {
2950
3119
  'tx_type': txType,
@@ -2962,17 +3131,18 @@ export default class lighter extends Exchange {
2962
3131
  * @returns {object} the api result
2963
3132
  */
2964
3133
  async cancelAllOrdersAfter(timeout, params = {}) {
3134
+ await this.loadMarkets();
2965
3135
  if ((timeout < 300000) || (timeout > 1296000000)) {
2966
3136
  throw new BadRequest(this.id + ' timeout should be between 5 minutes and 15 days.');
2967
3137
  }
2968
3138
  let apiKeyIndex = undefined;
2969
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'cancelOrder', 'apiKeyIndex', 'api_key_index');
2970
- if (apiKeyIndex === undefined) {
2971
- throw new ArgumentsRequired(this.id + ' cancelAllOrdersAfter() requires an apiKeyIndex parameter');
2972
- }
3139
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'cancelOrder', 'apiKeyIndex', 'api_key_index');
2973
3140
  let accountIndex = undefined;
2974
3141
  [accountIndex, params] = await this.handleAccountIndex(params, 'cancelAllOrdersAfter', 'accountIndex', 'account_index');
2975
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
3142
+ const strAccountIndex = this.numberToString(accountIndex);
3143
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
3144
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
3145
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
2976
3146
  const signRaw = {
2977
3147
  'time_in_force': 1,
2978
3148
  'time': this.milliseconds() + timeout,
@@ -2980,7 +3150,6 @@ export default class lighter extends Exchange {
2980
3150
  'api_key_index': apiKeyIndex,
2981
3151
  'account_index': accountIndex,
2982
3152
  };
2983
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
2984
3153
  const [txType, txInfo] = this.lighterSignCancelAllOrders(signer, this.extend(signRaw, params));
2985
3154
  const request = {
2986
3155
  'tx_type': txType,
@@ -3031,11 +3200,9 @@ export default class lighter extends Exchange {
3031
3200
  * @returns {object} A [margin structure]{@link https://docs.ccxt.com/?id=add-margin-structure}
3032
3201
  */
3033
3202
  async setMargin(symbol, amount, params = {}) {
3203
+ await this.loadMarkets();
3034
3204
  let apiKeyIndex = undefined;
3035
- [apiKeyIndex, params] = this.handleOptionAndParams2(params, 'setMargin', 'apiKeyIndex', 'api_key_index');
3036
- if (apiKeyIndex === undefined) {
3037
- throw new ArgumentsRequired(this.id + ' setMargin() requires an apiKeyIndex parameter');
3038
- }
3205
+ [apiKeyIndex, params] = this.handleApiKeyIndex(params, 'setMargin', 'apiKeyIndex', 'api_key_index');
3039
3206
  const direction = this.safeInteger(params, 'direction'); // 1 increase margin 0 decrease margin
3040
3207
  if (direction === undefined) {
3041
3208
  throw new ArgumentsRequired(this.id + ' setMargin() requires a direction parameter either 1 (increase margin) or 0 (decrease margin)');
@@ -3046,11 +3213,13 @@ export default class lighter extends Exchange {
3046
3213
  if (symbol === undefined) {
3047
3214
  throw new ArgumentsRequired(this.id + ' setMargin() requires a symbol argument');
3048
3215
  }
3049
- await this.loadMarkets();
3050
3216
  let accountIndex = undefined;
3051
3217
  [accountIndex, params] = await this.handleAccountIndex(params, 'setMargin', 'accountIndex', 'account_index');
3218
+ const strAccountIndex = this.numberToString(accountIndex);
3219
+ const strApiKeyIndex = this.numberToString(apiKeyIndex);
3220
+ const signer = await this.loadAccount(this.options['chainId'], this.getLighterPrivateKey(strAccountIndex, strApiKeyIndex), strApiKeyIndex, strAccountIndex, params);
3052
3221
  const market = this.market(symbol);
3053
- const nonce = await this.fetchNonce(accountIndex, apiKeyIndex);
3222
+ const nonce = await this.fetchNonce(accountIndex, apiKeyIndex, params);
3054
3223
  const signRaw = {
3055
3224
  'market_index': this.parseToInt(market['id']),
3056
3225
  'usdc_amount': this.parseToInt(Precise.stringMul(this.pow('10', '6'), this.currencyToPrecision('USDC', amount))),
@@ -3059,7 +3228,6 @@ export default class lighter extends Exchange {
3059
3228
  'api_key_index': apiKeyIndex,
3060
3229
  'account_index': accountIndex,
3061
3230
  };
3062
- const signer = await this.loadAccount(this.options['chainId'], this.privateKey, apiKeyIndex, accountIndex, params);
3063
3231
  const [txType, txInfo] = this.lighterSignUpdateMargin(signer, this.extend(signRaw, params));
3064
3232
  const request = {
3065
3233
  'tx_type': txType,