@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.
- package/build/bcRead.d.ts +2 -2
- package/build/bcRead.js +12 -12
- package/build/bcRead.js.map +1 -1
- package/build/bcTransaction.d.ts +6 -1
- package/build/bcTransaction.js +87 -33
- package/build/bcTransaction.js.map +1 -1
- package/build/connection.js +1 -1
- package/build/connection.js.map +1 -1
- package/build/customization.js +2 -4
- package/build/customization.js.map +1 -1
- package/build/ethereum/ethFuncs.js +3 -3
- package/build/ethereum/ethFuncs.js.map +1 -1
- package/build/ethereum/myetherwallet.d.ts +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.js +3 -2
- package/build/index.js.map +1 -1
- package/build/memo.js +6 -3
- package/build/memo.js.map +1 -1
- package/build/rest/ajaxReq.js +1 -1
- package/build/rest/ajaxReq.js.map +1 -1
- package/build/rest/http.js +6 -1
- package/build/rest/http.js.map +1 -1
- package/build/utils.d.ts +15 -0
- package/build/utils.js +270 -0
- package/build/utils.js.map +1 -0
- package/build/wallet.js +11 -6
- package/build/wallet.js.map +1 -1
- package/package.json +2 -2
- package/src/bcRead.ts +19 -12
- package/src/bcTransaction.ts +87 -39
- package/src/ethereum/ethFuncs.ts +3 -3
- package/src/index.ts +2 -1
- package/src/utils.ts +300 -0
- package/tests/environment.ts +27 -0
- package/tests/setup.ts +12 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +2 -0
package/src/bcTransaction.ts
CHANGED
|
@@ -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,
|
|
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 (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
|
package/src/ethereum/ethFuncs.ts
CHANGED
|
@@ -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...
|
|
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...
|
|
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
|
|
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
package/tsconfig.json
CHANGED