@com-chain/jsc3l 2.0.1-rc.19 → 2.0.1-rc.20

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.
@@ -2,7 +2,7 @@
2
2
  import { getNakedAddress, padLeft, encodeNumber } from './ethereum/ethFuncs'
3
3
  import { generateTx } from './ethereum/uiFuncs'
4
4
  import AjaxReq from './rest/ajaxReq'
5
-
5
+ import * as utils from './utils'
6
6
 
7
7
  function roundCent (strAmount:string) {
8
8
  return Math.round(100 * parseFloat(strAmount))
@@ -14,7 +14,7 @@ function typeConv (label: string): (x:any) => (string | number) {
14
14
  return (a) => padLeft(getNakedAddress(a), 64)
15
15
  }
16
16
  if (label === 'int') {
17
- return (nb) => encodeNumber(parseInt(nb, 19))
17
+ return (nb) => encodeNumber(parseInt(nb, 10))
18
18
  }
19
19
  if (label.startsWith('limit') || label === 'amount') {
20
20
  return (nb) => encodeNumber(roundCent(nb))
@@ -40,48 +40,96 @@ export abstract class BcTransactionAbstract {
40
40
  // //////////////////////////////////////////////////////////////////////////
41
41
  // CM VS Nant Handling
42
42
 
43
- getSplitting (nantVal, cmVal, cmMinusLim, amount) {
44
- cmVal = parseFloat(cmVal)
45
- nantVal = parseFloat(nantVal)
46
- let nant = 0
47
- let cm = 0
48
-
49
- let res = parseFloat(amount)
50
- if (cmVal > 0) {
51
- if (cmVal >= res) {
52
- cm = res
53
- res = 0
54
- } else {
55
- cm = cmVal
56
- res = res - cmVal
57
- cmVal = 0
58
- }
59
- }
60
-
61
- if (nantVal > 0) {
62
- if (nantVal >= res) {
63
- nant = res
64
- res = 0
65
- } else {
66
- nant = nantVal
67
- res = res - nantVal
68
- // nantVal=0;
69
- }
43
+ static getSplitting (nantBal, cmBal, cmSrcMin, amount) {
44
+ console.warn("Obsolete usage of `BcTransactionAbstract.getSplitting()'," +
45
+ " prefer `jsc3l.utils.getSplitting()'")
46
+ cmBal = parseFloat(cmBal)
47
+ nantBal = parseFloat(nantBal)
48
+ amount = parseFloat(amount)
49
+ cmSrcMin = parseFloat(cmSrcMin)
50
+
51
+ try {
52
+ let {nant, cm} = utils.getSplitting(amount, { cm: cmBal, nant: nantBal}, cmSrcMin)
53
+ return { possible: true, nant, cm}
54
+ } catch(e: any) {
55
+ return { possible: false}
70
56
  }
71
-
72
- if (res > 0 && cmVal - parseFloat(cmMinusLim) >= res) {
73
- cm = cm + res
74
- res = 0
75
- }
76
-
77
- const possible = res === 0
78
- return { possible: possible, nant: nant, cm: cm }
79
57
  }
80
-
81
- // //////////////////////////////////////////////////////////////////////////
58
+ getSplitting = BcTransactionAbstract.getSplitting
82
59
 
83
60
  }
84
61
 
62
+ /* @skip-prod-transpilation */
63
+ if (import.meta.vitest) {
64
+ const { it, expect, describe } = import.meta.vitest
65
+ describe('split', () => {
66
+ it('should split 0 to cm: 0, nant: 0', () => {
67
+ expect(BcTransactionAbstract.getSplitting(0, 0, 0, 0))
68
+ .toStrictEqual({ possible: true, nant: 0, cm: 0})
69
+ });
70
+ it('should NOT split 1 with no funds', () => {
71
+ expect(BcTransactionAbstract.getSplitting(0, 0, 0, 1).possible)
72
+ .toBe(false)
73
+ });
74
+ // Only Cm
75
+ it('should split 1 to cm: 1, nant: 0 with bal cm: 2, nant: 0', () => {
76
+ expect(BcTransactionAbstract.getSplitting(0, 2, 0, 1))
77
+ .toStrictEqual({ possible: true, nant: 0, cm: 1})
78
+ });
79
+ it('should split 2 to cm: 2, nant: 0 with bal cm: 2, nant: 0', () => {
80
+ expect(BcTransactionAbstract.getSplitting(0, 2, 0, 2))
81
+ .toStrictEqual({ possible: true, nant: 0, cm: 2})
82
+ });
83
+ it('should NOT split 3 with bal cm: 2, nant: 0', () => {
84
+ expect(BcTransactionAbstract.getSplitting(0, 2, 0, 3).possible)
85
+ .toBe(false)
86
+ });
87
+ // Only Nant
88
+ it('should split 1 to cm: 0, nant: 1 with bal cm: 0, nant: 2', () => {
89
+ expect(BcTransactionAbstract.getSplitting(2, 0, 0, 1))
90
+ .toStrictEqual({ possible: true, nant: 1, cm: 0})
91
+ });
92
+ it('should split 2 to cm: 0, nant: 2 with bal cm: 0, nant: 2', () => {
93
+ expect(BcTransactionAbstract.getSplitting(2, 0, 0, 2))
94
+ .toStrictEqual({ possible: true, nant: 2, cm: 0})
95
+ });
96
+ it('should NOT split 3 with bal cm: 0, nant: 2', () => {
97
+ expect(BcTransactionAbstract.getSplitting(2, 0, 0, 3).possible)
98
+ .toBe(false)
99
+ });
100
+ // Both Nant and Cm
101
+ it('should split 2 to cm: 1, nant: 1 with bal cm: 1, nant: 1', () => {
102
+ expect(BcTransactionAbstract.getSplitting(1, 1, 0, 2))
103
+ .toStrictEqual({ possible: true, nant: 1, cm: 1})
104
+ });
105
+ it('should split 2 to cm: 0, nant: 2 with bal cm: 0, nant: 2 (limSrcCm: -2)', () => {
106
+ expect(BcTransactionAbstract.getSplitting(2, 0, -2, 2))
107
+ .toStrictEqual({ possible: true, nant: 2, cm: 0})
108
+ });
109
+ it('should split 2 to cm: 1, nant: 1 with bal cm: 0, nant: 1 (limSrcCm: -1)', () => {
110
+ expect(BcTransactionAbstract.getSplitting(1, 0, -1, 2))
111
+ .toStrictEqual({ possible: true, nant: 1, cm: 1})
112
+ });
113
+ it('should NOT split 3 with bal cm: 0, nant: 1 (limSrcCm: -1)', () => {
114
+ expect(BcTransactionAbstract.getSplitting(1, 0, -1, 3).possible)
115
+ .toBe(false)
116
+ });
117
+ it('should split 3 to cm: 2, nant: 1 with bal cm: 1, nant: 1 (limSrcCm: -1)', () => {
118
+ expect(BcTransactionAbstract.getSplitting(1, 1, -1, 3))
119
+ .toStrictEqual({ possible: true, nant: 1, cm: 2})
120
+ });
121
+ // Negative cm bal and limSrcCm
122
+ it('should split 1 to cm: -1, nant: 0 with bal cm: -1, nant: 0 (limSrcCm: -2)', () => {
123
+ expect(BcTransactionAbstract.getSplitting(0, -1, -2, 1))
124
+ .toStrictEqual({ possible: true, nant: 0, cm: 1})
125
+ });
126
+ it('should NOT split 2 with bal cm: -1, nant: 0 (limSrcCm: -2)', () => {
127
+ expect(BcTransactionAbstract.getSplitting(0, -1, -2, 2).possible)
128
+ .toBe(false)
129
+ });
130
+
131
+ });
132
+ }
85
133
 
86
134
  export function transactionFactory(transactionDefs: any[], bcTransactionClass: any) {
87
135
 
@@ -86,7 +86,7 @@ if (import.meta.vitest) {
86
86
  it('should encode 16 to "00...0010"', () => {
87
87
  expect(encodeNumber(16)).toBe('0000000000000000000000000000000000000000000000000000000000000010')
88
88
  })
89
- it('should encode 0x1f_ffff_ffff_ffff to "00...ffff_ffff_ffff"', () => {
89
+ it('should encode 0x1f_ffff_ffff_ffff to "00...001f_ffff_ffff_ffff"', () => {
90
90
  expect(encodeNumber(0x1f_ffff_ffff_ffff)).toBe('000000000000000000000000000000000000000000000000001fffffffffffff')
91
91
  })
92
92
 
@@ -99,11 +99,11 @@ if (import.meta.vitest) {
99
99
  it('should encode -0x10 to "ff...fff0"', () => {
100
100
  expect(encodeNumber(-0x10)).toBe('fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0')
101
101
  })
102
- it('should encode -0x1f_ffff_ffff_fffff to "ff...e0000000000001"', () => {
102
+ it('should encode -0x1f_ffff_ffff_fffff to "ff...ffe0_0000_0000_0001"', () => {
103
103
  expect(encodeNumber(-0x1f_ffff_ffff_ffff)).toBe('ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000001')
104
104
  })
105
105
 
106
- it('should refuse to encode 0x1ff_ffff_ffff_ffff', () => {
106
+ it('should refuse to encode 0x20_0000_0000_0000', () => {
107
107
  expect(() => encodeNumber(0x20_0000_0000_0000)).toThrowError('number type')
108
108
  })
109
109
  it('should refuse to encode -0x20_0000_0000_0000', () => {
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import * as qr from './qr'
5
5
  // Only required for blockie helper
6
6
  import blockies from './blockies'
7
7
  import Wallet from './ethereum/myetherwallet'
8
+ import * as utils from './utils'
8
9
 
9
10
  import * as t from './type'
10
11
 
@@ -47,7 +48,7 @@ abstract class AbstractJsc3l {
47
48
  _Endpoint: new (baseUrl: any) => EndpointAbstract
48
49
  _connection: null | ConnectionMgrAbstract
49
50
  _http: null | HttpAbstract
50
-
51
+ utils = utils
51
52
 
52
53
  constructor (localDefaultConf?, defaultTransactionDefs?) {
53
54
  this.localDefaultConf = localDefaultConf || {}
package/src/utils.ts ADDED
@@ -0,0 +1,300 @@
1
+ export class SplitError extends Error {
2
+ constructor (message) {
3
+ super(message)
4
+ this.name = 'SplitError'
5
+ }
6
+ }
7
+
8
+
9
+ export class InsufficientBalanceError extends SplitError {
10
+ missingAmount: number
11
+ constructor (message, missingAmount) {
12
+ super(message)
13
+ this.name = 'InsufficientBalanceError'
14
+ this.missingAmount = missingAmount
15
+ }
16
+ }
17
+
18
+ export class CmSpendLimitError extends SplitError {
19
+ missingAmount: number
20
+ constructor (message, missingAmount) {
21
+ super(message)
22
+ this.name = 'CmSpendLimitError'
23
+ this.missingAmount = missingAmount
24
+ }
25
+ }
26
+
27
+
28
+ function min(a, b) {
29
+ return a < b ? a : b
30
+ }
31
+
32
+
33
+ export let getSplitting = function (amount, bals, cmSrcMin, cmSpendMax = null) {
34
+
35
+ const zero = amount - amount // Required for agnosticity
36
+
37
+ const split = { nant: zero, cm: zero }
38
+ const cmPosSpendMax = cmSpendMax !== null ? min(bals.cm, cmSpendMax) : bals.cm
39
+
40
+ if (cmPosSpendMax >= 0) {
41
+ if (cmPosSpendMax >= amount) {
42
+ split.cm += amount
43
+ return split
44
+ }
45
+ split.cm += cmPosSpendMax
46
+ amount -= cmPosSpendMax
47
+ bals.cm -= cmPosSpendMax
48
+ if (cmSpendMax !== null) {
49
+ cmSpendMax -= cmPosSpendMax
50
+ }
51
+ }
52
+
53
+ if (bals.nant >= amount) {
54
+ split.nant += amount
55
+ return split
56
+ }
57
+
58
+ split.nant = bals.nant
59
+ amount -= bals.nant
60
+
61
+ let cmNegAvailable = bals.cm - cmSrcMin
62
+ const cmNegSpendMax = cmSpendMax !== null ? min(cmNegAvailable, cmSpendMax) : cmNegAvailable
63
+ if (cmNegSpendMax >= amount) {
64
+ split.cm += amount
65
+ return split
66
+ }
67
+
68
+ amount -= cmNegSpendMax
69
+ bals.cm -= cmNegSpendMax
70
+ if (cmSpendMax !== null) {
71
+ cmSpendMax -= cmNegSpendMax
72
+ }
73
+
74
+ cmNegAvailable = (bals.cm - cmSrcMin)
75
+ if (cmNegAvailable >= amount && cmSpendMax == 0) {
76
+ throw new CmSpendLimitError(
77
+ `Cm spend limit preventing to complete amount (remaining: ${amount}).`,
78
+ amount
79
+ )
80
+ }
81
+
82
+ throw new InsufficientBalanceError(
83
+ `Missing ${amount - cmNegAvailable} to complete amount`,
84
+ amount - cmNegAvailable
85
+ )
86
+ }
87
+
88
+
89
+ /* @skip-prod-transpilation */
90
+ if (import.meta.vitest) {
91
+ const { it, expect, describe, beforeAll, afterAll } = import.meta.vitest
92
+
93
+ function testSuite (numberFactory: any = null, label: any = null) {
94
+ let msg
95
+ if (numberFactory) {
96
+ msg = `check with ${label}`
97
+ } else {
98
+ msg = "check with standard number"
99
+ }
100
+ describe(msg, () => {
101
+
102
+ let getSplittingOrig = getSplitting
103
+ let toStrictEqual
104
+
105
+ beforeAll(() => {
106
+
107
+ if (numberFactory) {
108
+ getSplitting = function (amount, bals, cmSrcMin, cmSpendMax = null) {
109
+ amount = numberFactory(amount)
110
+ bals.cm = numberFactory(bals.cm)
111
+ bals.nant = numberFactory(bals.nant)
112
+ cmSrcMin = numberFactory(cmSrcMin)
113
+ if (cmSpendMax !== null) {
114
+ cmSpendMax = numberFactory(cmSpendMax)
115
+ }
116
+ return getSplittingOrig(amount, bals, cmSrcMin, cmSpendMax)
117
+ }
118
+ toStrictEqual = function (actual, expected) {
119
+ let { cm, nant } = expected
120
+ expect(actual).toStrictEqual({ cm: numberFactory(cm), nant: numberFactory(nant) })
121
+ }
122
+ } else {
123
+ toStrictEqual = function (actual, expected) {
124
+ expect(actual).toStrictEqual(expected)
125
+ }
126
+ }
127
+ })
128
+
129
+ afterAll(() => {
130
+ getSplitting = getSplittingOrig
131
+ })
132
+
133
+
134
+ describe('split without cmSpendMax', () => {
135
+ it('should split 0 to cm: 0, nant: 0', () => {
136
+ toStrictEqual(getSplitting(0, { cm: 0, nant: 0 }, 0), { nant: 0, cm: 0 })
137
+ });
138
+ it('should NOT split 1 with no funds', () => {
139
+ expect(() => getSplitting(1, { cm: 0, nant: 0 }, 0))
140
+ .toThrow("Missing 1 to complete amount")
141
+ });
142
+ // Only Cm
143
+ it('should split 1 to cm: 1, nant: 0 with bal cm: 2, nant: 0', () => {
144
+ toStrictEqual(getSplitting(1, {cm: 2, nant: 0}, 0), { nant: 0, cm: 1 })
145
+ });
146
+ it('should split 2 to cm: 2, nant: 0 with bal cm: 2, nant: 0', () => {
147
+ toStrictEqual(getSplitting(2, { cm: 2, nant: 0 }, 0), { nant: 0, cm: 2 })
148
+ });
149
+ it('should NOT split 3 with bal cm: 2, nant: 0', () => {
150
+ expect(() => getSplitting(3, { cm: 2, nant: 0 }, 0))
151
+ .toThrow("Missing 1 to complete amount")
152
+ });
153
+ // Only Nant
154
+ it('should split 1 to cm: 0, nant: 1 with bal cm: 0, nant: 2', () => {
155
+ toStrictEqual(getSplitting(1, { cm: 0, nant: 2 }, 0), { nant: 1, cm: 0 })
156
+ });
157
+ it('should split 2 to cm: 0, nant: 2 with bal cm: 0, nant: 2', () => {
158
+ toStrictEqual(getSplitting(2, { cm: 0, nant: 2 }, 0), { nant: 2, cm: 0 })
159
+ });
160
+ it('should NOT split 3 with bal cm: 0, nant: 2', () => {
161
+ expect(() => getSplitting(3, { cm: 0, nant: 2 }, 0))
162
+ .toThrow("Missing 1 to complete amount")
163
+ });
164
+ // Both Nant and Cm
165
+ it('should split 2 to cm: 1, nant: 1 with bal cm: 1, nant: 1', () => {
166
+ toStrictEqual(getSplitting(2, { cm: 1, nant: 1 }, 0), { nant: 1, cm: 1 })
167
+ });
168
+ it('should split 2 to cm: 0, nant: 2 with bal cm: 0, nant: 2 (limSrcCm: -2)', () => {
169
+ toStrictEqual(getSplitting(2, { cm: 0, nant: 2 }, -2), { nant: 2, cm: 0 })
170
+ });
171
+ it('should split 2 to cm: 1, nant: 1 with bal cm: 0, nant: 1 (limSrcCm: -1)', () => {
172
+ toStrictEqual(getSplitting(2, { cm: 0, nant: 1 }, -1), { nant: 1, cm: 1 })
173
+ });
174
+ it('should NOT split 3 with bal cm: 0, nant: 1 (limSrcCm: -1)', () => {
175
+ expect(() => getSplitting(3, { cm: 0, nant: 1 }, -1))
176
+ .toThrow("Missing 1 to complete amount")
177
+ });
178
+ it('should split 3 to cm: 2, nant: 1 with bal cm: 1, nant: 1 (limSrcCm: -1)', () => {
179
+ toStrictEqual(getSplitting(3, { cm: 1, nant: 1 }, -1), { nant: 1, cm: 2 })
180
+ });
181
+ // Negative cm bal and limSrcCm
182
+ it('should split 1 to cm: -1, nant: 0 with bal cm: -1, nant: 0 (limSrcCm: -2)', () => {
183
+ toStrictEqual(getSplitting(1, { cm: -1, nant: 0 }, -2), { nant: 0, cm: 1 })
184
+ });
185
+ it('should NOT split 2 with bal cm: -1, nant: 0 (limSrcCm: -2)', () => {
186
+ expect(() => getSplitting(2, { cm: -1, nant: 0 }, -2))
187
+ .toThrow("Missing 1 to complete amount")
188
+ });
189
+ });
190
+ describe('split with cmSpendMax', () => {
191
+ it('should split 0 to cm: 0, nant: 0 (cmSpendMax: 0)', () => {
192
+ toStrictEqual(getSplitting(0, { cm: 0, nant: 0 }, 0, 0), { nant: 0, cm: 0})
193
+ });
194
+ it('should split 0 to cm: 0, nant: 0 (cmSpendMax: 1)', () => {
195
+ toStrictEqual(getSplitting(0, { cm: 0, nant: 0 }, 0, 0), { nant: 0, cm: 0})
196
+ });
197
+ it('should NOT split 1 with no funds (cmSpendMax: 1)', () => {
198
+ expect(() => getSplitting(1, { cm: 0, nant: 0 }, 0, 1))
199
+ .toThrow("Missing 1 to complete amount")
200
+ });
201
+ it('should NOT split 1 with no funds (cmSpendMax: 0)', () => {
202
+ expect(() => getSplitting(1, { cm: 0, nant: 0 }, 0, 0))
203
+ .toThrow("Missing 1 to complete amount")
204
+ });
205
+ // Only Cm
206
+ it('should split 1 to cm: 1, nant: 0 with bal cm: 2, nant: 0 (cmSpendMax: 1)', () => {
207
+ toStrictEqual(getSplitting(1, {cm: 2, nant: 0}, 0, 1), { nant: 0, cm: 1 })
208
+ });
209
+ it('should split 2 to cm: 2, nant: 0 with bal cm: 2, nant: 0 (cmSpendMax: 2)', () => {
210
+ toStrictEqual(getSplitting(2, { cm: 2, nant: 0 }, 0, 2), { nant: 0, cm: 2 })
211
+ });
212
+ it('should NOT split 2 to cm: 2, nant: 0 with bal cm: 2, nant: 0 (cmSpendMax: 1)', () => {
213
+ expect(() => getSplitting(2, { cm: 2, nant: 0 }, 0, 1))
214
+ .toThrow("Cm spend limit preventing to complete amount (remaining: 1)")
215
+ });
216
+ it('should NOT split 3 with bal cm: 2, nant: 0 (cmSpendMax: 5)', () => {
217
+ expect(() => getSplitting(3, { cm: 2, nant: 0 }, 0, 5))
218
+ .toThrow("Missing 1 to complete amount")
219
+ });
220
+ it('should NOT split 3 with bal cm: 2, nant: 0 (cmSpendMax: 2)', () => {
221
+ expect(() => getSplitting(3, { cm: 2, nant: 0 }, 0, 2))
222
+ .toThrow("Missing 1 to complete amount")
223
+ });
224
+ it('should NOT split 3 with bal cm: 2, nant: 0 (cmSpendMax: 1)', () => {
225
+ expect(() => getSplitting(3, { cm: 2, nant: 0 }, 0, 1))
226
+ .toThrow("Missing 1 to complete amount")
227
+ });
228
+ // Only Nant
229
+ it('should split 1 to cm: 0, nant: 1 with bal cm: 0, nant: 2 (cmSpendMax: 0)', () => {
230
+ toStrictEqual(getSplitting(1, { cm: 0, nant: 2 }, 0, 0), { nant: 1, cm: 0 })
231
+ });
232
+ it('should split 2 to cm: 0, nant: 2 with bal cm: 0, nant: 2 (cmSpendMax: 1)', () => {
233
+ toStrictEqual(getSplitting(2, { cm: 0, nant: 2 }, 0, 1), { nant: 2, cm: 0 })
234
+ });
235
+ it('should NOT split 3 with bal cm: 0, nant: 2 (cmSpendMax: 0)', () => {
236
+ expect(() => getSplitting(3, { cm: 0, nant: 2 }, 0, 0))
237
+ .toThrow("Missing 1 to complete amount")
238
+ });
239
+ // Both Nant and Cm
240
+ it('should split 2 to cm: 1, nant: 1 with bal cm: 1, nant: 1 (cmSpendMax: 1)', () => {
241
+ toStrictEqual(getSplitting(2, { cm: 1, nant: 1 }, 0, 1), { nant: 1, cm: 1})
242
+ });
243
+ it('should NOT split 2 to cm: 1, nant: 1 with bal cm: 1, nant: 1 (cmSpendMax: 0)', () => {
244
+ expect(() => getSplitting(2, { cm: 1, nant: 1 }, 0, 0))
245
+ .toThrow("Cm spend limit preventing to complete amount (remaining: 1)")
246
+ });
247
+ it('should split 2 to cm: 1, nant: 1 with bal cm: 0, nant: 1 (limSrcCm: -1, cmSpendMax: 1)', () => {
248
+ toStrictEqual(getSplitting(2, { cm: 0, nant: 1 }, -1, 1), { nant: 1, cm: 1})
249
+ });
250
+ it('should NOT split 2 to cm: 1, nant: 1 with bal cm: 0, nant: 1 (limSrcCm: -1, cmSpendMax: 0)', () => {
251
+ expect(() => getSplitting(2, { cm: 0, nant: 1 }, -1, 0))
252
+ .toThrow("Cm spend limit preventing to complete amount (remaining: 1)")
253
+ });
254
+ it('should NOT split 3 with bal cm: 0, nant: 1 (limSrcCm: -1, cmSpendMax: 5)', () => {
255
+ expect(() => getSplitting(3, { cm: 0, nant: 1 }, -1, 5))
256
+ .toThrow("Missing 1 to complete amount")
257
+ });
258
+ it('should NOT split 3 with bal cm: 0, nant: 1 (limSrcCm: -1, cmSpendMax: 0)', () => {
259
+ expect(() => getSplitting(3, { cm: 0, nant: 1 }, -1, 0))
260
+ .toThrow("Missing 1 to complete amount")
261
+ });
262
+ it('should split 3 to cm: 2, nant: 1 with bal cm: 1, nant: 1 (limSrcCm: -1, cmSpendMax: 2)', () => {
263
+ toStrictEqual(getSplitting(3, { cm: 1, nant: 1 }, -1, 2), { nant: 1, cm: 2 })
264
+ });
265
+ it('should NOT split 3 to cm: 2, nant: 1 with bal cm: 1, nant: 1 (limSrcCm: -1, cmSpendMax: 1)', () => {
266
+ expect(() => getSplitting(3, { cm: 1, nant: 1 }, -1, 1))
267
+ .toThrow("Cm spend limit preventing to complete amount (remaining: 1)")
268
+ });
269
+ // If the recipient can't receive cm, then pay with nant if possible.
270
+ it('should split 2 to cm: 0, nant: 2 with bal cm: 2, nant: 2 (limSrcCm: 0, cmSpendMax: 0)', () => {
271
+ toStrictEqual(getSplitting(2, { cm: 2, nant: 2 }, 0, 0), { nant: 2, cm: 0 })
272
+ });
273
+ it('should split 3 to cm: 1, nant: 2 with bal cm: 2, nant: 2 (limSrcCm: 0, cmSpendMax: 1)', () => {
274
+ toStrictEqual(getSplitting(3, { cm: 2, nant: 2 }, 0, 1), { nant: 2, cm: 1 })
275
+ });
276
+ it('should split 3 to cm: 2, nant: 2 with bal cm: 2, nant: 2 (limSrcCm: 0, cmSpendMax: 2)', () => {
277
+ toStrictEqual(getSplitting(3, { cm: 2, nant: 2 }, 0, 2), { nant: 1, cm: 2 })
278
+ });
279
+ // Negative cm bal and limSrcCm
280
+ it('should split 1 to cm: -1, nant: 0 with bal cm: -1, nant: 0 (limSrcCm: -2, cmSpendMax: 1)', () => {
281
+ toStrictEqual(getSplitting(1, { cm: -1, nant: 0 }, -2, 1), { nant: 0, cm: 1 })
282
+ });
283
+ it('should NOT split 2 with bal cm: -1, nant: 0 (limSrcCm: -2, cmSpendMax: 2)', () => {
284
+ expect(() => getSplitting(2, { cm: -1, nant: 0 }, -2, 2))
285
+ .toThrow("Missing 1 to complete amount")
286
+ });
287
+ it('should NOT split 2 with bal cm: -1, nant: 0 (limSrcCm: -2, cmSpendMax: 0)', () => {
288
+ expect(() => getSplitting(2, { cm: -1, nant: 0 }, -2, 2))
289
+ .toThrow("Missing 1 to complete amount")
290
+ });
291
+ it('should NOT split 2 with bal cm: -1, nant: 0 (limSrcCm: -3, cmSpendMax: 1)', () => {
292
+ expect(() => getSplitting(2, { cm: -1, nant: 0 }, -3, 1))
293
+ .toThrow("Cm spend limit preventing to complete amount (remaining: 1)")
294
+ });
295
+ })
296
+ })
297
+ }
298
+ testSuite()
299
+ testSuite(BigInt, "BigInt")
300
+ }
@@ -0,0 +1,27 @@
1
+ import type { Environment } from 'vitest'
2
+
3
+ export default <Environment>{
4
+ name: 'custom',
5
+ transformMode: 'ssr',
6
+ // optional - only if you support "experimental-vm" pool
7
+ async setupVM() {
8
+ const vm = await import('node:vm')
9
+ const context = vm.createContext()
10
+ return {
11
+ getVmContext() {
12
+ return context
13
+ },
14
+ teardown() {
15
+ // called after all tests with this env have been run
16
+ }
17
+ }
18
+ },
19
+ setup() {
20
+ // custom setup
21
+ return {
22
+ teardown() {
23
+ // called after all tests with this env have been run
24
+ }
25
+ }
26
+ }
27
+ }
package/tests/setup.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { Buffer } from 'buffer'
2
+ import { afterAll, beforeAll } from 'vitest';
3
+
4
+ beforeAll(() => {
5
+ global.Buffer = Buffer
6
+ });
7
+
8
+ afterAll(() => {
9
+ delete global.Buffer
10
+ });
11
+
12
+
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "es2017",
3
+ "target": "es2020",
4
4
  "module": "esnext",
5
5
  "moduleResolution": "node",
6
6
  "declaration": true,
package/vitest.config.ts CHANGED
@@ -6,6 +6,8 @@ const cfg = defineConfig({
6
6
  include: ['src/**/*.{js,ts}'],
7
7
  setupFiles: ['./tests/setup.ts'],
8
8
  environment: 'jsdom',
9
+ passWithNoTests: true,
10
+ bail: 1,
9
11
  },
10
12
  })
11
13