@psf/bch-js 5.4.0 → 6.2.0

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/src/utxo.js CHANGED
@@ -20,276 +20,6 @@ class UTXO {
20
20
  this.BigNumber = BigNumber
21
21
  }
22
22
 
23
- /**
24
- * @api Utxo.getOld() getOld()
25
- * @apiName getOld
26
- * @apiGroup UTXO
27
- * @apiDescription Get UTXOs for an address (from SLPDB)
28
- *
29
- * Given an address, this function will return an object with thre following
30
- * properties:
31
- * - address: "" - the address these UTXOs are associated with
32
- * - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
33
- * - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
34
- * not spent, to be safe.
35
- * - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
36
- * - type1: {}
37
- * - tokens: [] - SLP token Type 1 tokens.
38
- * - mintBatons: [] - SLP token Type 1 mint batons.
39
- * - nft: {}
40
- * - tokens: [] - NFT tokens
41
- * - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
42
- * - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
43
- *
44
- * Note: You can pass in an optional second Boolean argument. The default
45
- * `false` will use the normal waterfall validation method. Set to `true`,
46
- * SLP UTXOs will be validated with the whitelist filtered SLPDB. This will
47
- * result is many more UTXOs in the `nullUtxos` array.
48
- *
49
- * @apiExample Example usage:
50
- * (async () => {
51
- * try {
52
- * let utxos = await bchjs.Utxo.getOld('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
53
- * console.log(utxos);
54
- * } catch(error) {
55
- * console.error(error)
56
- * }
57
- * })()
58
- *
59
- * // returns
60
- * [
61
- * {
62
- * "address": "bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv",
63
- * "bchUtxos": [
64
- * {
65
- * "height": 674513,
66
- * "tx_hash": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
67
- * "tx_pos": 3,
68
- * "value": 38134,
69
- * "txid": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
70
- * "vout": 3,
71
- * "isValid": false
72
- * }
73
- * ],
74
- * "nullUtxos": [],
75
- * "slpUtxos": {
76
- * "type1": {
77
- * "mintBatons": [
78
- * {
79
- * "height": 674512,
80
- * "tx_hash": "acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230",
81
- * "tx_pos": 2,
82
- * "value": 546,
83
- * "txid": "acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230",
84
- * "vout": 2,
85
- * "utxoType": "minting-baton",
86
- * "tokenId": "acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230",
87
- * "tokenTicker": "SLPTEST",
88
- * "tokenName": "SLP Test Token",
89
- * "tokenDocumentUrl": "https://FullStack.cash",
90
- * "tokenDocumentHash": "",
91
- * "decimals": 8,
92
- * "tokenType": 1,
93
- * "isValid": true
94
- * }
95
- * ],
96
- * "tokens": [
97
- * {
98
- * "height": 674512,
99
- * "tx_hash": "acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230",
100
- * "tx_pos": 1,
101
- * "value": 546,
102
- * "txid": "acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230",
103
- * "vout": 1,
104
- * "utxoType": "token",
105
- * "tokenQty": "100",
106
- * "tokenId": "acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230",
107
- * "tokenTicker": "SLPTEST",
108
- * "tokenName": "SLP Test Token",
109
- * "tokenDocumentUrl": "https://FullStack.cash",
110
- * "tokenDocumentHash": "",
111
- * "decimals": 8,
112
- * "tokenType": 1,
113
- * "isValid": true
114
- * }
115
- * ]
116
- * },
117
- * "nft": {
118
- * "groupMintBatons": [
119
- * {
120
- * "height": 674513,
121
- * "tx_hash": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
122
- * "tx_pos": 2,
123
- * "value": 546,
124
- * "txid": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
125
- * "vout": 2,
126
- * "utxoType": "minting-baton",
127
- * "transactionType": "mint",
128
- * "tokenId": "a9a2458a0f9f0761d5b8725c256f2e7fa35b9de4dec6f47b46e9f20d92d0e395",
129
- * "tokenType": 129,
130
- * "tokenTicker": "NFTGT",
131
- * "tokenName": "NFT Test Group Token",
132
- * "tokenDocumentUrl": "https://FullStack.cash",
133
- * "tokenDocumentHash": "",
134
- * "decimals": 0,
135
- * "mintBatonVout": 2,
136
- * "isValid": true
137
- * }
138
- * ],
139
- * "groupTokens": [
140
- * {
141
- * "height": 674513,
142
- * "tx_hash": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
143
- * "tx_pos": 1,
144
- * "value": 546,
145
- * "txid": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
146
- * "vout": 1,
147
- * "utxoType": "token",
148
- * "tokenQty": "10",
149
- * "transactionType": "mint",
150
- * "tokenId": "a9a2458a0f9f0761d5b8725c256f2e7fa35b9de4dec6f47b46e9f20d92d0e395",
151
- * "tokenType": 129,
152
- * "tokenTicker": "NFTGT",
153
- * "tokenName": "NFT Test Group Token",
154
- * "tokenDocumentUrl": "https://FullStack.cash",
155
- * "tokenDocumentHash": "",
156
- * "decimals": 0,
157
- * "mintBatonVout": 2,
158
- * "isValid": true
159
- * }
160
- * ],
161
- * "tokens": [
162
- * {
163
- * "height": 674512,
164
- * "tx_hash": "eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b",
165
- * "tx_pos": 1,
166
- * "value": 546,
167
- * "txid": "eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b",
168
- * "vout": 1,
169
- * "utxoType": "token",
170
- * "tokenQty": "1",
171
- * "tokenId": "eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b",
172
- * "tokenTicker": "NFT004",
173
- * "tokenName": "NFT Child",
174
- * "tokenDocumentUrl": "https://FullStack.cash",
175
- * "tokenDocumentHash": "",
176
- * "decimals": 0,
177
- * "tokenType": 65,
178
- * "isValid": true
179
- * }
180
- * ]
181
- * }
182
- * }
183
- * }
184
- * ]
185
- *
186
- *
187
- */
188
- async getOld (address, useWhitelist = false) {
189
- try {
190
- if (!address) {
191
- throw new Error('Address must be an array or a string')
192
- }
193
-
194
- // Convert address to an array if it is a string.
195
- if (typeof address === 'string') address = [address]
196
-
197
- // Throw an error if there are more than 20 addresses passed in at a time.
198
- if (address.length > 20) throw new Error('Too many elements, 20 max.')
199
-
200
- // Covert each address to a BCH address.
201
- const addr = address.map(elem => this.slp.Address.toCashAddress(elem))
202
-
203
- // Get the UTXOs associated with the address.
204
- const utxoData = await this.electrumx.utxo(addr)
205
- // console.log(`utxoData: ${JSON.stringify(utxoData, null, 2)}`)
206
-
207
- // Hydate the utxos with token information.
208
- let hydratedUtxos
209
- if (useWhitelist) {
210
- hydratedUtxos = await this.slp.Utils.hydrateUtxosWL(utxoData.utxos)
211
- } else {
212
- hydratedUtxos = await this.slp.Utils.hydrateUtxos(utxoData.utxos)
213
- }
214
- // console.log(`hydratedUtxos: ${JSON.stringify(hydratedUtxos, null, 2)}`)
215
-
216
- const retAry = [] // Return array
217
-
218
- // Loop through each address.
219
- for (let i = 0; i < hydratedUtxos.slpUtxos.length; i++) {
220
- const thisAddr = hydratedUtxos.slpUtxos[i]
221
-
222
- const addrObj = {
223
- address: thisAddr.address
224
- }
225
-
226
- // Filter out the different types of UTXOs.
227
- addrObj.bchUtxos = thisAddr.utxos.filter(elem => elem.isValid === false)
228
- addrObj.nullUtxos = thisAddr.utxos.filter(elem => elem.isValid === null)
229
-
230
- // Break down the SLP UTXOs.
231
- addrObj.slpUtxos = {
232
- type1: {},
233
- nft: {}
234
- }
235
-
236
- // Token Type 1 Minting Batons.
237
- addrObj.slpUtxos.type1.mintBatons = thisAddr.utxos.filter(elem => {
238
- const isValid = elem.isValid === true
239
- const tokenTypeIs1 = elem.tokenType === 1
240
- const isMintingBaton = elem.utxoType === 'minting-baton'
241
-
242
- return isValid && tokenTypeIs1 && isMintingBaton
243
- })
244
-
245
- // Token Type 1 tokens.
246
- addrObj.slpUtxos.type1.tokens = thisAddr.utxos.filter(elem => {
247
- const isValid = elem.isValid === true
248
- const tokenTypeIs1 = elem.tokenType === 1
249
- const isToken = elem.utxoType === 'token'
250
-
251
- return isValid && tokenTypeIs1 && isToken
252
- })
253
-
254
- // NFT Group Minting Batons
255
- addrObj.slpUtxos.nft.groupMintBatons = thisAddr.utxos.filter(elem => {
256
- const isValid = elem.isValid === true
257
- const tokenTypeIs129 = elem.tokenType === 129
258
- const isMintingBaton = elem.utxoType === 'minting-baton'
259
-
260
- return isValid && tokenTypeIs129 && isMintingBaton
261
- })
262
-
263
- // NFT Group tokens
264
- addrObj.slpUtxos.nft.groupTokens = thisAddr.utxos.filter(elem => {
265
- const isValid = elem.isValid === true
266
- const tokenTypeIs129 = elem.tokenType === 129
267
- const isToken = elem.utxoType === 'token'
268
-
269
- return isValid && tokenTypeIs129 && isToken
270
- })
271
-
272
- // NFT (Child) tokens
273
- addrObj.slpUtxos.nft.tokens = thisAddr.utxos.filter(elem => {
274
- const isValid = elem.isValid === true
275
- const tokenTypeIs65 = elem.tokenType === 65
276
- const isToken = elem.utxoType === 'token'
277
-
278
- return isValid && tokenTypeIs65 && isToken
279
- })
280
-
281
- retAry.push(addrObj)
282
- }
283
-
284
- return retAry
285
- } catch (err) {
286
- console.error('Error in bchjs.utxo.get()')
287
-
288
- if (err.error) throw new Error(err.error)
289
- throw err
290
- }
291
- }
292
-
293
23
  /**
294
24
  * @api Utxo.get() get()
295
25
  * @apiName get
@@ -15,113 +15,6 @@ describe('#UTXO', () => {
15
15
  if (process.env.IS_USING_FREE_TIER) await sleep(3000)
16
16
  })
17
17
 
18
- if (process.env.TESTSLP) {
19
- describe('#getOld', () => {
20
- it('should get hydrated and filtered UTXOs for an address', async () => {
21
- // const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
22
- const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
23
-
24
- const result = await bchjs.Utxo.getOld(addr)
25
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
26
-
27
- assert.isArray(result)
28
- assert.property(result[0], 'address')
29
- assert.property(result[0], 'bchUtxos')
30
- assert.property(result[0], 'nullUtxos')
31
- assert.property(result[0], 'slpUtxos')
32
- assert.isArray(result[0].bchUtxos)
33
- assert.isArray(result[0].nullUtxos)
34
- })
35
-
36
- it('should handle an array of addresses', async () => {
37
- const addr = [
38
- 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9',
39
- 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
40
- ]
41
-
42
- const result = await bchjs.Utxo.getOld(addr)
43
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
44
-
45
- assert.isArray(result)
46
- assert.property(result[0], 'address')
47
- assert.property(result[0], 'bchUtxos')
48
- assert.property(result[0], 'nullUtxos')
49
- assert.property(result[0], 'slpUtxos')
50
- assert.isArray(result[0].bchUtxos)
51
- assert.isArray(result[0].nullUtxos)
52
- })
53
-
54
- it('should handle NFTs and minting batons', async () => {
55
- const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
56
-
57
- const result = await bchjs.Utxo.getOld(addr)
58
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
59
-
60
- assert.isArray(result)
61
- assert.property(result[0], 'address')
62
- assert.property(result[0], 'bchUtxos')
63
- assert.property(result[0], 'nullUtxos')
64
- assert.property(result[0], 'slpUtxos')
65
- assert.isArray(result[0].bchUtxos)
66
- assert.isArray(result[0].nullUtxos)
67
-
68
- assert.isArray(result[0].slpUtxos.type1.mintBatons)
69
- assert.isArray(result[0].slpUtxos.type1.tokens)
70
- assert.isArray(result[0].slpUtxos.nft.groupMintBatons)
71
- assert.isArray(result[0].slpUtxos.nft.groupTokens)
72
- assert.isArray(result[0].slpUtxos.nft.tokens)
73
- })
74
-
75
- it('should use the whitelist when flag is set', async () => {
76
- const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
77
- const useWhitelist = true
78
-
79
- const result = await bchjs.Utxo.getOld(addr, useWhitelist)
80
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
81
-
82
- assert.isArray(result)
83
- assert.property(result[0], 'address')
84
- assert.property(result[0], 'bchUtxos')
85
- assert.property(result[0], 'nullUtxos')
86
- assert.property(result[0], 'slpUtxos')
87
- assert.isArray(result[0].bchUtxos)
88
- assert.isArray(result[0].nullUtxos)
89
-
90
- // Most token UTXOs should end up in the nullUtxos array.
91
- assert.isAbove(result[0].bchUtxos.length, 0)
92
- assert.isAbove(result[0].nullUtxos.length, 1)
93
- })
94
- })
95
-
96
- describe('#findBiggestUtxo', () => {
97
- it('should sort UTXOs from Electrumx', async () => {
98
- const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
99
-
100
- const electrumxUtxos = await bchjs.Electrumx.utxo(addr)
101
- // console.log(`Electrumx utxos: ${JSON.stringify(electrumxUtxos, null, 2)}`)
102
-
103
- const result = bchjs.Utxo.findBiggestUtxo(electrumxUtxos.utxos)
104
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
105
-
106
- assert.property(result, 'satoshis')
107
- assert.equal(result.satoshis, 800)
108
- })
109
-
110
- it('should sort UTXOs from Utxos.get()', async () => {
111
- const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
112
-
113
- const utxos = await bchjs.Utxo.getOld(addr)
114
- // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
115
-
116
- const result = bchjs.Utxo.findBiggestUtxo(utxos[0].bchUtxos)
117
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
118
-
119
- assert.property(result, 'satoshis')
120
- assert.equal(result.satoshis, 800)
121
- })
122
- })
123
- }
124
-
125
18
  describe('#hydrateTokenData', () => {
126
19
  it('should hydrate token UTXOs', async () => {
127
20
  const utxos = [