edge-currency-monero 1.4.2 → 1.5.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 1.5.1 (2025-07-03)
6
+
7
+ - fixed: Fix `getFreshAddress` to return a non-empty `publicAddress` when calling immediately after creating a wallet.
8
+ - fixed: Handle insufficient funds errors from native library into `InsufficientFundsError`.
9
+
10
+ ## 1.5.0 (2025-04-21)
11
+
12
+ - added: Support for multiple spend targets.
13
+
5
14
  ## 1.4.2 (2025-04-01)
6
15
 
7
16
  - fixed: Small internal implementation cleanup on how transactions are saved.
@@ -85,13 +85,14 @@ const PRIMARY_CURRENCY_TOKEN_ID = null
85
85
 
86
86
 
87
87
 
88
+ __init() {this.loginPromise = null}
88
89
 
89
90
  constructor(
90
91
  env,
91
92
  tools,
92
93
  walletInfo,
93
94
  opts
94
- ) {
95
+ ) {;MoneroEngine.prototype.__init.call(this);
95
96
  const { callbacks, userSettings = {}, walletLocalDisklet } = opts
96
97
  const initOptions = _moneroTypes.asMoneroInitOptions.call(void 0, _nullishCoalesce(env.initOptions, () => ( {})))
97
98
  const { networkInfo } = tools
@@ -174,6 +175,20 @@ const PRIMARY_CURRENCY_TOKEN_ID = null
174
175
  // Login to mymonero.com server
175
176
  // **********************************************
176
177
  async loginIfNewAddress(privateKeys) {
178
+ if (this.loginPromise != null) {
179
+ return await this.loginPromise
180
+ }
181
+ this.loginPromise = this.performLogin(privateKeys)
182
+
183
+ try {
184
+ await this.loginPromise
185
+ } finally {
186
+ // Clear the promise once completed (success OR failure)
187
+ this.loginPromise = null
188
+ }
189
+ }
190
+
191
+ async performLogin(privateKeys) {
177
192
  try {
178
193
  const result = await this.myMoneroApi.login({
179
194
  address: this.walletInfo.keys.moneroAddress,
@@ -578,8 +593,18 @@ const PRIMARY_CURRENCY_TOKEN_ID = null
578
593
  async getFreshAddress(
579
594
  options
580
595
  ) {
596
+ // Wait for login to complete if it's in progress
597
+ if (this.loginPromise != null) {
598
+ await this.loginPromise
599
+ }
600
+
581
601
  // Do not show the address before logging into my monero...
582
- if (!this.walletLocalData.hasLoggedIn) return { publicAddress: '' }
602
+ if (!this.walletLocalData.hasLoggedIn) {
603
+ this.log.warn(
604
+ 'Attempted to retrieve `publicAddress` before successfully logging in'
605
+ )
606
+ return { publicAddress: '' }
607
+ }
583
608
  return { publicAddress: this.walletInfo.keys.moneroAddress }
584
609
  }
585
610
 
@@ -601,10 +626,14 @@ const PRIMARY_CURRENCY_TOKEN_ID = null
601
626
  }
602
627
 
603
628
  const options = {
604
- amount: '0',
605
629
  isSweepTx: true,
606
630
  priority: translateFee(edgeSpendInfo.networkFeeOption),
607
- targetAddress: publicAddress
631
+ targets: [
632
+ {
633
+ amount: '0',
634
+ targetAddress: publicAddress
635
+ }
636
+ ]
608
637
  }
609
638
 
610
639
  const result = await this.createMyMoneroTransaction(options, privateKeys)
@@ -625,12 +654,20 @@ const PRIMARY_CURRENCY_TOKEN_ID = null
625
654
  },
626
655
  options
627
656
  )
628
- } catch (e) {
657
+ } catch (error) {
658
+ if (!(error instanceof Error)) {
659
+ throw new Error(String(error))
660
+ }
661
+ if (error.message === 'Not enough spendables') {
662
+ throw new (0, _types.InsufficientFundsError)({
663
+ tokenId: PRIMARY_CURRENCY_TOKEN_ID
664
+ })
665
+ }
629
666
  // This error is specific to mymonero-core-js: github.com/mymonero/mymonero-core-cpp/blob/a53e57f2a376b05bb0f4d851713321c749e5d8d9/src/monero_transfer_utils.hpp#L112-L162
630
- this.log.error(e.message)
667
+ this.log.error(error.message)
631
668
  const regex = / Have (\d*\.?\d+) XMR; need (\d*\.?\d+) XMR./gm
632
669
  const subst = `\nHave: $1 XMR.\nNeed: $2 XMR.`
633
- const msgFormatted = e.message.replace(regex, subst)
670
+ const msgFormatted = error.message.replace(regex, subst)
634
671
  throw new Error(msgFormatted)
635
672
  }
636
673
  }
@@ -642,39 +679,45 @@ const PRIMARY_CURRENCY_TOKEN_ID = null
642
679
  const { memos = [] } = edgeSpendInfo
643
680
  const privateKeys = _moneroTypes.asPrivateKeys.call(void 0, _optionalChain([opts, 'optionalAccess', _7 => _7.privateKeys]))
644
681
 
645
- // Monero can only have one output
646
- // TODO: The new SDK fixes this!
647
- if (edgeSpendInfo.spendTargets.length !== 1) {
648
- throw new Error('Error: only one output allowed')
649
- }
682
+ const { spendTargets } = edgeSpendInfo
650
683
 
651
- const [spendTarget] = edgeSpendInfo.spendTargets
652
- const { publicAddress, nativeAmount } = spendTarget
653
- if (publicAddress == null) {
654
- throw new TypeError('Missing destination address')
655
- }
656
- if (nativeAmount == null || _biggystring.eq.call(void 0, nativeAmount, '0')) {
657
- throw new (0, _types.NoAmountSpecifiedError)()
658
- }
684
+ let totalAmount = '0'
685
+ const targets = []
659
686
 
660
- if (
661
- _biggystring.gte.call(void 0,
662
- nativeAmount,
663
- _nullishCoalesce(this.walletLocalData.totalBalances.get(PRIMARY_CURRENCY_TOKEN_ID), () => ( '0'))
664
- )
665
- ) {
666
- if (_biggystring.gte.call(void 0, this.walletLocalData.lockedXmrBalance, nativeAmount)) {
667
- throw new (0, _types.PendingFundsError)()
668
- } else {
669
- throw new (0, _types.InsufficientFundsError)({ tokenId: PRIMARY_CURRENCY_TOKEN_ID })
687
+ for (const spendTarget of spendTargets) {
688
+ const { publicAddress, nativeAmount } = spendTarget
689
+ if (publicAddress == null) {
690
+ throw new TypeError('Missing destination address')
691
+ }
692
+ if (nativeAmount == null || _biggystring.eq.call(void 0, nativeAmount, '0')) {
693
+ throw new (0, _types.NoAmountSpecifiedError)()
694
+ }
695
+ totalAmount = _biggystring.add.call(void 0, totalAmount, nativeAmount)
696
+ if (
697
+ _biggystring.gte.call(void 0,
698
+ totalAmount,
699
+ _nullishCoalesce(this.walletLocalData.totalBalances.get(PRIMARY_CURRENCY_TOKEN_ID), () => (
700
+ '0'))
701
+ )
702
+ ) {
703
+ if (_biggystring.gte.call(void 0, this.walletLocalData.lockedXmrBalance, totalAmount)) {
704
+ throw new (0, _types.PendingFundsError)()
705
+ } else {
706
+ throw new (0, _types.InsufficientFundsError)({
707
+ tokenId: PRIMARY_CURRENCY_TOKEN_ID
708
+ })
709
+ }
670
710
  }
711
+ targets.push({
712
+ amount: _biggystring.div.call(void 0, nativeAmount, '1000000000000', 12),
713
+ targetAddress: publicAddress
714
+ })
671
715
  }
672
716
 
673
717
  const options = {
674
- amount: _biggystring.div.call(void 0, nativeAmount, '1000000000000', 12),
675
718
  isSweepTx: false,
676
719
  priority: translateFee(edgeSpendInfo.networkFeeOption),
677
- targetAddress: publicAddress
720
+ targets
678
721
  }
679
722
  this.log(`Creating transaction: ${JSON.stringify(options, null, 1)}`)
680
723
 
@@ -48,6 +48,8 @@ var _ResponseParser = require('./mymonero-utils/ResponseParser'); var _ResponseP
48
48
 
49
49
 
50
50
 
51
+
52
+
51
53
 
52
54
 
53
55
 
@@ -238,13 +240,7 @@ const asGetAddressTxsResponse = _cleaners.asObject.call(void 0, {
238
240
  opts
239
241
  ) {
240
242
  const { address, privateSpendKey, privateViewKey, publicSpendKey } = keys
241
- const {
242
- amount,
243
- isSweepTx = false,
244
- paymentId,
245
- priority = 1,
246
- targetAddress
247
- } = opts
243
+ const { isSweepTx = false, paymentId, priority = 1, targets } = opts
248
244
 
249
245
  // Grab the UTXO set:
250
246
  const unspentOuts = await this.fetchPostMyMonero('get_unspent_outs', {
@@ -268,14 +264,14 @@ const asGetAddressTxsResponse = _cleaners.asObject.call(void 0, {
268
264
  })
269
265
  }
270
266
 
267
+ const destinations = targets.map(t => ({
268
+ send_amount: t.amount,
269
+ to_address: t.targetAddress
270
+ }))
271
+
271
272
  // Make the transaction:
272
273
  return await this.cppBridge.createTransaction({
273
- destinations: [
274
- {
275
- send_amount: amount,
276
- to_address: targetAddress
277
- }
278
- ],
274
+ destinations,
279
275
  priority,
280
276
  address,
281
277
  paymentId,