@com-chain/jsc3l 2.0.1-rc.2 → 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.
Files changed (71) hide show
  1. package/README.md +12 -2
  2. package/build/bcRead.d.ts +8 -10
  3. package/build/bcRead.js +162 -49
  4. package/build/bcRead.js.map +1 -1
  5. package/build/bcTransaction.d.ts +8 -2
  6. package/build/bcTransaction.js +141 -108
  7. package/build/bcTransaction.js.map +1 -1
  8. package/build/blockies.js.map +1 -1
  9. package/build/config/transactions.d.ts +44 -0
  10. package/build/config/transactions.js +29 -0
  11. package/build/config/transactions.js.map +1 -0
  12. package/build/connection.d.ts +1 -1
  13. package/build/connection.js +44 -13
  14. package/build/connection.js.map +1 -1
  15. package/build/customization.js +13 -6
  16. package/build/customization.js.map +1 -1
  17. package/build/ethereum/cipher.js +3 -3
  18. package/build/ethereum/cipher.js.map +1 -1
  19. package/build/ethereum/ethFuncs.js +37 -1
  20. package/build/ethereum/ethFuncs.js.map +1 -1
  21. package/build/ethereum/etherUnits.js +5 -5
  22. package/build/ethereum/etherUnits.js.map +1 -1
  23. package/build/ethereum/myetherwallet.d.ts +1 -2
  24. package/build/ethereum/myetherwallet.js.map +1 -1
  25. package/build/ethereum/uiFuncs.d.ts +1 -3
  26. package/build/ethereum/uiFuncs.js +13 -23
  27. package/build/ethereum/uiFuncs.js.map +1 -1
  28. package/build/exception.d.ts +8 -0
  29. package/build/exception.js +14 -0
  30. package/build/exception.js.map +1 -0
  31. package/build/index.d.ts +8 -5
  32. package/build/index.js +38 -19
  33. package/build/index.js.map +1 -1
  34. package/build/memo.js +6 -3
  35. package/build/memo.js.map +1 -1
  36. package/build/qr.d.ts +31 -6
  37. package/build/qr.js +32 -12
  38. package/build/qr.js.map +1 -1
  39. package/build/rest/ajaxReq.d.ts +3 -10
  40. package/build/rest/ajaxReq.js +16 -33
  41. package/build/rest/ajaxReq.js.map +1 -1
  42. package/build/rest/http.js +6 -1
  43. package/build/rest/http.js.map +1 -1
  44. package/build/rest/serializer.js.map +1 -1
  45. package/build/type.d.ts +4 -4
  46. package/build/utils.d.ts +15 -0
  47. package/build/utils.js +270 -0
  48. package/build/utils.js.map +1 -0
  49. package/build/wallet.d.ts +6 -8
  50. package/build/wallet.js +35 -39
  51. package/build/wallet.js.map +1 -1
  52. package/package.json +10 -5
  53. package/skip-prod-transpilation.ts +48 -0
  54. package/src/bcRead.ts +184 -63
  55. package/src/bcTransaction.ts +143 -114
  56. package/src/config/transactions.ts +30 -0
  57. package/src/connection.ts +42 -9
  58. package/src/customization.ts +17 -2
  59. package/src/ethereum/ethFuncs.ts +42 -1
  60. package/src/ethereum/etherUnits.ts +5 -5
  61. package/src/ethereum/uiFuncs.ts +16 -25
  62. package/src/exception.ts +16 -0
  63. package/src/index.ts +53 -27
  64. package/src/qr.ts +86 -12
  65. package/src/rest/ajaxReq.ts +18 -40
  66. package/src/utils.ts +300 -0
  67. package/src/wallet.ts +37 -48
  68. package/tests/environment.ts +27 -0
  69. package/tests/setup.ts +12 -0
  70. package/tsconfig.json +8 -2
  71. package/vitest.config.ts +14 -0
@@ -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))
@@ -13,20 +13,26 @@ function typeConv (label: string): (x:any) => (string | number) {
13
13
  if (label.endsWith('Address')) {
14
14
  return (a) => padLeft(getNakedAddress(a), 64)
15
15
  }
16
+ if (label === 'int') {
17
+ return (nb) => encodeNumber(parseInt(nb, 10))
18
+ }
16
19
  if (label.startsWith('limit') || label === 'amount') {
17
20
  return (nb) => encodeNumber(roundCent(nb))
18
21
  }
19
- if (label.endsWith('Status') || label.endsWith('Type')) {
22
+ if (label.endsWith('Status') || label.endsWith('Type') || label.endsWith('Int')) {
20
23
  return (nb) => encodeNumber(nb)
21
24
  }
25
+ if (label.endsWith('Hex')) {
26
+ return (s) => s.padEnd(128, '0')
27
+ }
22
28
  if (label === 'status') {
23
- return (nb) => (parseInt(nb, 10) === 0 ? 0 : 1)
29
+ return (nb) => encodeNumber(parseInt(nb, 10) === 0 ? 0 : 1)
24
30
  }
25
31
  throw new Error(`Unexpected label '${label}' in FnDefs.`)
26
32
  }
27
33
 
28
34
 
29
- export default abstract class BcTransactionAbstract {
35
+ export abstract class BcTransactionAbstract {
30
36
 
31
37
  abstract ajaxReq: AjaxReq
32
38
  abstract contracts: string[]
@@ -34,124 +40,147 @@ export default abstract class BcTransactionAbstract {
34
40
  // //////////////////////////////////////////////////////////////////////////
35
41
  // CM VS Nant Handling
36
42
 
37
- getSplitting (nantVal, cmVal, cmMinusLim, amount) {
38
- cmVal = parseFloat(cmVal)
39
- nantVal = parseFloat(nantVal)
40
- let nant = 0
41
- let cm = 0
42
-
43
- let res = parseFloat(amount)
44
- if (cmVal > 0) {
45
- if (cmVal >= res) {
46
- cm = res
47
- res = 0
48
- } else {
49
- cm = cmVal
50
- res = res - cmVal
51
- cmVal = 0
52
- }
53
- }
54
-
55
- if (nantVal > 0) {
56
- if (nantVal >= res) {
57
- nant = res
58
- res = 0
59
- } else {
60
- nant = nantVal
61
- res = res - nantVal
62
- // nantVal=0;
63
- }
64
- }
65
-
66
- if (res > 0 && cmVal - parseFloat(cmMinusLim) >= res) {
67
- cm = cm + res
68
- res = 0
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}
69
56
  }
70
-
71
- const possible = res === 0
72
- return { possible: possible, nant: nant, cm: cm }
73
57
  }
58
+ getSplitting = BcTransactionAbstract.getSplitting
74
59
 
75
- // //////////////////////////////////////////////////////////////////////////
60
+ }
76
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
+ });
77
132
  }
78
133
 
134
+ export function transactionFactory(transactionDefs: any[], bcTransactionClass: any) {
79
135
 
80
- [
81
- // First Contract
82
- {
83
- setAccountParam: '848b2592:accAddress accStatus accType limitPlus limitMinus',
84
- pledgeAccount: '6c343eef:accAddress amount *',
85
- setAllowance: 'd4e12f2e:spenderAddress amount',
86
- setDelegation: '75741c79:spenderAddress limit',
87
- setTaxAmount: 'f6f1897d:amount',
88
- setTaxLegAmount: 'fafaf4c0:amount',
89
- setTaxAccount: 'd0385b5e:accAddress',
90
- setOwnerAccount: 'f2fde38b:accAddress',
91
- setContractStatus: '0x88b8084f:status',
92
- },
93
- // Second Contract
94
- {
95
- transferNant: 'a5f7c148:toAddress amount *',
96
- transferCM: '60ca9c4c:toAddress amount *',
97
- transferOnBehalfNant: '1b6b1ee5:fromAddress toAddress amount D',
98
- transferOnBehalfCM: '74c421fe:fromAddress toAddress amount D',
99
- askTransferFrom: '58258353:fromAddress amount',
100
- askTransferCMFrom: '2ef9ade2:fromAddress amount',
101
- payRequestNant: '132019f4:toAddress amount *',
102
- payRequestCM: '1415707c:toAddress amount *',
103
- rejectRequest: 'af98f757:toAddress',
104
- dismissAcceptedInfo: 'ccf93c7a:accAddress',
105
- dismissRejectedInfo: '88759215:accAddress',
106
- }
107
- ].forEach((contractFnDefs, contractNb) => {
108
-
109
- for (const fnName in contractFnDefs) {
110
-
111
- const [fnHash, argStringList] = contractFnDefs[fnName].split(':')
112
- const argList = argStringList.split(' ')
113
- let hasAdditionalPostData = false
114
- let hasDelegate = false
115
- if (argList.slice(-1)[0] === '*') {
116
- hasAdditionalPostData = true
117
- argList.pop()
118
- } else if (argList.slice(-1)[0] === 'D') {
119
- hasAdditionalPostData = true
120
- hasDelegate = true
121
- argList.pop()
122
- }
136
+ transactionDefs.forEach((contractFnDefs, contractNb) => {
123
137
 
124
- // Build argument array function
125
- const argFnList = argList.map((arg) => typeConv(arg))
126
- const concatArgs = (args) =>
127
- args.map((arg, idx) => argFnList[idx](arg)).join('')
128
-
129
- BcTransactionAbstract.prototype[fnName] = async function (wallet, ...args) {
130
- const addr = wallet.getAddressString()
131
- const data = await this.ajaxReq.getTransactionData(addr)
132
- // TODO: must test this
133
- if (data.error) {
134
- console.log(`Failed getTransactionData(${addr})`)
135
- throw new Error(data.msg)
138
+ for (const fnName in contractFnDefs) {
139
+
140
+ const [fnHash, argStringList] = contractFnDefs[fnName].split(':')
141
+ const argList = argStringList.split(' ')
142
+ let hasAdditionalPostData = false
143
+ let hasDelegate = false
144
+ if (argList.slice(-1)[0] === '*') {
145
+ hasAdditionalPostData = true
146
+ argList.pop()
147
+ } else if (argList.slice(-1)[0] === 'D') {
148
+ hasAdditionalPostData = true
149
+ hasDelegate = true
150
+ argList.pop()
136
151
  }
137
- const additionalPostData = hasAdditionalPostData ? args.pop() : {}
138
- if (hasDelegate) {
139
- additionalPostData.delegate = wallet.getAddressString()
152
+
153
+ // Build argument array function
154
+ const argFnList = argList.map((arg) => typeConv(arg))
155
+ const concatArgs = (args) =>
156
+ args.map((arg, idx) => argFnList[idx](arg)).join('')
157
+
158
+ bcTransactionClass.prototype[fnName] = async function (wallet, ...args) {
159
+ const addr = wallet.getAddressString()
160
+ const data = await this.ajaxReq.getTransactionData(addr)
161
+ // TODO: must test this
162
+ if (data.error) {
163
+ console.log(`Failed getTransactionData(${addr})`)
164
+ throw new Error(data.msg)
165
+ }
166
+ const additionalPostData = hasAdditionalPostData ? args.pop() : {}
167
+ if (hasDelegate) {
168
+ additionalPostData.delegate = wallet.getAddressString()
169
+ }
170
+ const rawSignedTx = generateTx({
171
+ gasLimit: 500000,
172
+ data: fnHash + concatArgs(args),
173
+ to: this.contracts[contractNb],
174
+ unit: 'ether',
175
+ value: 0,
176
+ nonce: 1,
177
+ gasPrice: null,
178
+ donate: false,
179
+ from: addr,
180
+ key: wallet.getPrivateKeyString()
181
+ }, data)
182
+ return this.ajaxReq.sendTx(rawSignedTx, additionalPostData)
140
183
  }
141
- const rawTx = generateTx({
142
- gasLimit: 500000,
143
- data: fnHash + concatArgs(args),
144
- to: this.contracts[contractNb],
145
- unit: 'ether',
146
- value: 0,
147
- nonce: 1,
148
- gasPrice: null,
149
- donate: false,
150
- from: addr,
151
- key: wallet.getPrivateKeyString()
152
- }, data)
153
- if (rawTx.isError) return rawTx
154
- return this.ajaxReq.sendTx(rawTx.signedTx, additionalPostData)
155
184
  }
156
- }
157
- })
185
+ })
186
+ }
@@ -0,0 +1,30 @@
1
+
2
+
3
+ export default [
4
+ // First Contract
5
+ {
6
+ setAccountParam: '848b2592:accAddress accStatus accType limitPlus limitMinus',
7
+ pledgeAccount: '6c343eef:accAddress amount *',
8
+ setAllowance: 'd4e12f2e:spenderAddress amount',
9
+ setDelegation: '75741c79:spenderAddress limit',
10
+ setTaxAmount: 'f6f1897d:int',
11
+ setTaxLegAmount: 'fafaf4c0:int',
12
+ setTaxAccount: 'd0385b5e:accAddress',
13
+ setOwnerAccount: 'f2fde38b:accAddress',
14
+ setContractStatus: '88b8084f:status',
15
+ },
16
+ // Second Contract
17
+ {
18
+ transferNant: 'a5f7c148:toAddress amount *',
19
+ transferCM: '60ca9c4c:toAddress amount *',
20
+ transferOnBehalfNant: '1b6b1ee5:fromAddress toAddress amount D',
21
+ transferOnBehalfCM: '74c421fe:fromAddress toAddress amount D',
22
+ askTransferFrom: '58258353:fromAddress amount',
23
+ askTransferCMFrom: '2ef9ade2:fromAddress amount',
24
+ payRequestNant: '132019f4:toAddress amount *',
25
+ payRequestCM: '1415707c:toAddress amount *',
26
+ rejectRequest: 'af98f757:toAddress',
27
+ dismissAcceptedInfo: 'ccf93c7a:accAddress',
28
+ dismissRejectedInfo: '88759215:accAddress',
29
+ },
30
+ ]
package/src/connection.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import * as config from './config'
2
2
  import HttpAbstract from './rest/http'
3
3
  import * as t from './type'
4
+ import * as e from './exception'
4
5
 
6
+ const wait = async (ms: number): Promise<void> => {
7
+ return new Promise(resolve => setTimeout(resolve, ms))
8
+ }
5
9
 
6
10
  abstract class ConnectionAbstract {
7
11
 
@@ -36,15 +40,42 @@ abstract class ConnectionAbstract {
36
40
  public async acquireEndPoint (repo: string) {
37
41
  const apiNodes = await this.getCCEndPointList(repo)
38
42
  if (!apiNodes) return false
39
- const endpoint = await this.selectEndPoint(apiNodes)
43
+ let endpoint: boolean | string = false
44
+ let retry = 30
45
+ let count = 0
46
+ console.log(`Pick first endpoint that pass checkdb test`)
47
+ while (!endpoint) {
48
+ if (count >= 1) {
49
+ await wait(200)
50
+ console.log(`No endpoints passed the checkdb test... retry (${count}/${retry})`)
51
+ }
52
+ endpoint = await this.selectEndPoint([...apiNodes])
53
+ count++
54
+ if (count >= retry) {
55
+ break
56
+ }
57
+ }
58
+ if (typeof endpoint === 'string') {
59
+ console.log(` endpoint ${endpoint} %cpassed%c the checkdb test`,
60
+ 'color: #0b0;', 'color: none')
61
+ } else {
62
+ console.log(`Failed to find a functional endpoint passing checkdb.`)
63
+ }
40
64
  return { apiNodes, endpoint }
41
65
  }
42
66
 
43
67
  ///
44
68
  // [Lower level] Get the list of ComChain end-points from given repo
45
69
  ///
46
- getCCEndPointList (repo: string) {
47
- return this.http.get(repo + config.nodesRepo, { _: new Date().getTime() })
70
+ async getCCEndPointList (repo: string) {
71
+ try {
72
+ return await this.http.get(
73
+ repo + config.nodesRepo,
74
+ { _: new Date().getTime() })
75
+ } catch (e) {
76
+ console.error(`Failed to get endpoint list on ${repo}`, e)
77
+ return false
78
+ }
48
79
  }
49
80
 
50
81
  ///
@@ -59,6 +90,7 @@ abstract class ConnectionAbstract {
59
90
  // check the node is up and running
60
91
  const success = await this.testNode(node)
61
92
  if (success) return node
93
+ console.log(` endpoint ${node} %cfailed%c the checkdb test`, 'color: #b00;', 'color:none')
62
94
  nodes.splice(id, 1)
63
95
  }
64
96
  return false
@@ -187,7 +219,7 @@ export default abstract class ConnectionMgrAbstract extends ConnectionAbstract {
187
219
  }
188
220
  const { apiNodes, endpoint } = apiNodesEndpoint
189
221
  if (typeof endpoint !== 'string') {
190
- throw new Error('No endpoint in list seems available.')
222
+ throw new e.NoEndpointAvailable('No endpoint in list seems available.')
191
223
  }
192
224
 
193
225
  this.persistentStore.set('ApiNodes', JSON.stringify(apiNodes))
@@ -232,11 +264,12 @@ export default abstract class ConnectionMgrAbstract extends ConnectionAbstract {
232
264
  public getLocalConfJSON () {
233
265
  if (this.conf) return this.conf
234
266
  const cfgJson = this.persistentStore.get('ServerConf')
235
- if (!cfgJson) return null
236
- const cfg = JSON.parse(cfgJson)
237
- // Completing with other informations
238
- cfg.repo = this.repo
239
- cfg.custoRepo = this.repo + config.custoRepo
267
+ const cfg = cfgJson ? JSON.parse(cfgJson) : {}
268
+ // Completing with other informations if available
269
+ if (this.repo) {
270
+ cfg.repo = this.repo
271
+ cfg.custoRepo = this.repo + config.custoRepo
272
+ }
240
273
  return cfg
241
274
  }
242
275
 
@@ -131,14 +131,25 @@ export default abstract class CustomizationAbstract {
131
131
  if (!currencyName) {
132
132
  currencyName = this.cfg.server.name
133
133
  }
134
+ if (!this.cfg.custoRepo) {
135
+ throw Error(
136
+ 'Requested getCurrencyAssetBaseUrl while configuration is not available (yet?)'
137
+ )
138
+ }
134
139
  return `${this.cfg.custoRepo}${currencyName}`
135
140
  }
136
141
 
137
142
  public getCssUrl (currencyName?: string) {
138
143
  try {
139
- // XXXvlab: I guess that we don't need to keep 'etherwallet' css names
140
- return `${this.getCurrencyAssetBaseUrl(currencyName)}/css/etherwallet-master.min.css`
144
+ // XXXvlab: I guess that we don't need to keep 'etherwallet' css
145
+ // names
146
+ return this.getCurrencyAssetBaseUrl(currencyName) +
147
+ '/css/etherwallet-master.min.css'
141
148
  } catch (e) {
149
+ console.log(
150
+ '`customization.getCssUrl(..)` called before configuration was ' +
151
+ "ready. Returning `localDefaultConf`'s value."
152
+ )
142
153
  return this.localDefaultConf.server.url_Css
143
154
  }
144
155
  }
@@ -149,6 +160,10 @@ export default abstract class CustomizationAbstract {
149
160
  // be agnostic ?
150
161
  return `${this.getCurrencyAssetBaseUrl(currencyName)}/images/lem.png`
151
162
  } catch (e) {
163
+ console.log(
164
+ '`customization.getCurrencyLogoUrl(..)` called before configuration ' +
165
+ 'was ready. Returning empty string.'
166
+ )
152
167
  return ''
153
168
  }
154
169
  }
@@ -36,7 +36,7 @@ function padLeftEven (hex) {
36
36
  }
37
37
 
38
38
  export function addTinyMoreToGas (hex) {
39
- hex = this.sanitizeHex(hex)
39
+ hex = sanitizeHex(hex)
40
40
  return new BigNumber(hex).plus(etherUnits.getValueOfUnit('gwei'))
41
41
  .toDigits(2).toString(16)
42
42
  }
@@ -71,3 +71,44 @@ export function encodeNumber (number) {
71
71
 
72
72
  return valueHex
73
73
  }
74
+
75
+
76
+ /* @skip-prod-transpilation */
77
+ if (import.meta.vitest) {
78
+ const { it, expect, describe } = import.meta.vitest
79
+ describe('encodeNumber', () => {
80
+ it('should encode 0 to "00...0000"', () => {
81
+ expect(encodeNumber(0)).toBe('0000000000000000000000000000000000000000000000000000000000000000')
82
+ })
83
+ it('should encode 1 to "00...0001"', () => {
84
+ expect(encodeNumber(1)).toBe('0000000000000000000000000000000000000000000000000000000000000001')
85
+ })
86
+ it('should encode 16 to "00...0010"', () => {
87
+ expect(encodeNumber(16)).toBe('0000000000000000000000000000000000000000000000000000000000000010')
88
+ })
89
+ it('should encode 0x1f_ffff_ffff_ffff to "00...001f_ffff_ffff_ffff"', () => {
90
+ expect(encodeNumber(0x1f_ffff_ffff_ffff)).toBe('000000000000000000000000000000000000000000000000001fffffffffffff')
91
+ })
92
+
93
+ it('should encode -1 to "ff...ffff"', () => {
94
+ expect(encodeNumber(-1)).toBe('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
95
+ })
96
+ it('should encode -0xf to "ff...fff1"', () => {
97
+ expect(encodeNumber(-0xf)).toBe('fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1')
98
+ })
99
+ it('should encode -0x10 to "ff...fff0"', () => {
100
+ expect(encodeNumber(-0x10)).toBe('fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0')
101
+ })
102
+ it('should encode -0x1f_ffff_ffff_fffff to "ff...ffe0_0000_0000_0001"', () => {
103
+ expect(encodeNumber(-0x1f_ffff_ffff_ffff)).toBe('ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000001')
104
+ })
105
+
106
+ it('should refuse to encode 0x20_0000_0000_0000', () => {
107
+ expect(() => encodeNumber(0x20_0000_0000_0000)).toThrowError('number type')
108
+ })
109
+ it('should refuse to encode -0x20_0000_0000_0000', () => {
110
+ expect(() => encodeNumber(-0x20_0000_0000_0000)).toThrowError('number type')
111
+ })
112
+
113
+ })
114
+ }
@@ -41,26 +41,26 @@ export function getValueOfUnit (unit) {
41
41
  export function fiatToWei (number, pricePerEther) {
42
42
  return new BigNumber(String(number))
43
43
  .div(pricePerEther)
44
- .times(this.getValueOfUnit('ether'))
44
+ .times(getValueOfUnit('ether'))
45
45
  .round(0)
46
46
  .toString(10)
47
47
  }
48
48
 
49
49
  export function toFiat (number, unit, multi) {
50
- return new BigNumber(this.toEther(number, unit))
50
+ return new BigNumber(toEther(number, unit))
51
51
  .times(multi)
52
52
  .round(5)
53
53
  .toString(10)
54
54
  }
55
55
 
56
56
  export function toEther (number, unit) {
57
- return new BigNumber(this.toWei(number, unit))
58
- .div(this.getValueOfUnit('ether'))
57
+ return new BigNumber(toWei(number, unit))
58
+ .div(getValueOfUnit('ether'))
59
59
  .toString(10)
60
60
  }
61
61
 
62
62
  export function toWei (number, unit) {
63
63
  return new BigNumber(String(number))
64
- .times(this.getValueOfUnit(unit))
64
+ .times(getValueOfUnit(unit))
65
65
  .toString(10)
66
66
  }
@@ -24,32 +24,23 @@ function isTxDataValid (txData) {
24
24
  }
25
25
 
26
26
  export function generateTx (txData, data) {
27
- try {
28
- isTxDataValid(txData)
27
+ isTxDataValid(txData)
29
28
 
30
- const rawTx: {[k: string]: any} = {
31
- nonce: ethFuncs.sanitizeHex(data.nonce),
32
- gasPrice: ethFuncs.sanitizeHex(
33
- ethFuncs.addTinyMoreToGas(data.gasprice)),
34
- gasLimit: ethFuncs.sanitizeHex(
35
- ethFuncs.decimalToHex(txData.gasLimit)),
36
- to: ethFuncs.sanitizeHex(txData.to),
37
- value: ethFuncs.sanitizeHex(
38
- ethFuncs.decimalToHex(etherUnits.toWei(txData.value, txData.unit))),
39
- data: ethFuncs.sanitizeHex(txData.data)
40
- }
41
- const eTx = new Tx(rawTx)
42
-
43
- eTx.sign(Buffer.from(txData.key, 'hex'))
44
- rawTx.rawTx = JSON.stringify(rawTx)
45
- rawTx.signedTx = '0x' + eTx.serialize().toString('hex')
46
- rawTx.isError = false
47
- return rawTx
48
- } catch (e) {
49
- return {
50
- isError: true,
51
- error: e
52
- }
29
+ const rawTx: {[k: string]: any} = {
30
+ nonce: ethFuncs.sanitizeHex(data.nonce),
31
+ gasPrice: ethFuncs.sanitizeHex(
32
+ ethFuncs.addTinyMoreToGas(data.gasprice)),
33
+ gasLimit: ethFuncs.sanitizeHex(
34
+ ethFuncs.decimalToHex(txData.gasLimit)),
35
+ to: ethFuncs.sanitizeHex(txData.to),
36
+ value: ethFuncs.sanitizeHex(
37
+ ethFuncs.decimalToHex(etherUnits.toWei(txData.value, txData.unit))),
38
+ data: ethFuncs.sanitizeHex(txData.data)
53
39
  }
40
+ const eTx = new Tx(rawTx)
41
+
42
+ eTx.sign(Buffer.from(txData.key, 'hex'))
43
+ rawTx.rawTx = JSON.stringify(rawTx)
44
+ return '0x' + eTx.serialize().toString('hex')
54
45
  }
55
46
 
@@ -0,0 +1,16 @@
1
+ export class APIError extends Error {
2
+ data: string
3
+ constructor (message, data) {
4
+ super(message)
5
+ this.name = 'APIError'
6
+ this.data = data
7
+ }
8
+ }
9
+
10
+ export class NoEndpointAvailable extends Error {
11
+ data: string
12
+ constructor (message) {
13
+ super(message)
14
+ this.name = 'NoEndpointAvailable'
15
+ }
16
+ }