@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
package/src/index.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import * as ethFuncs from './ethereum/ethFuncs' // Utilities to pass on
2
2
  import * as memo from './memo'
3
+ import * as qr from './qr'
3
4
 
4
5
  // Only required for blockie helper
5
6
  import blockies from './blockies'
6
7
  import Wallet from './ethereum/myetherwallet'
8
+ import * as utils from './utils'
7
9
 
8
10
  import * as t from './type'
9
11
 
@@ -17,8 +19,8 @@ import ConnectionMgrAbstract from './connection'
17
19
  import CustomizationAbstract from './customization'
18
20
  import MessagingWalletAbstract from './wallet'
19
21
  import BcReadAbstract from './bcRead'
20
- import BcTransactionAbstract from './bcTransaction'
21
-
22
+ import { BcTransactionAbstract, transactionFactory } from './bcTransaction'
23
+ import localTransactionDefs from './config/transactions'
22
24
 
23
25
 
24
26
  function createIcon (address: string | Wallet) {
@@ -39,16 +41,18 @@ abstract class AbstractJsc3l {
39
41
  protected abstract persistentStore: t.IPersistentStore
40
42
 
41
43
  localDefaultConf: {}
44
+ defaultTransactionDefs: []
42
45
 
43
46
  endpoint: string
44
47
 
45
48
  _Endpoint: new (baseUrl: any) => EndpointAbstract
46
49
  _connection: null | ConnectionMgrAbstract
47
50
  _http: null | HttpAbstract
51
+ utils = utils
48
52
 
49
-
50
- constructor (localDefaultConf?) {
53
+ constructor (localDefaultConf?, defaultTransactionDefs?) {
51
54
  this.localDefaultConf = localDefaultConf || {}
55
+ this.defaultTransactionDefs = defaultTransactionDefs || localTransactionDefs
52
56
  }
53
57
 
54
58
  /**
@@ -117,7 +121,7 @@ abstract class AbstractJsc3l {
117
121
  */
118
122
  async getConfig (repo: string, currencyName: string) {
119
123
  const cfgJson = this.connection.getLocalConfJSON()
120
- if (cfgJson && cfgJson.server.name === currencyName) {
124
+ if (cfgJson && cfgJson.server?.name === currencyName) {
121
125
  return cfgJson
122
126
  }
123
127
  return await this.connection.getConfJSON(currencyName, repo)
@@ -163,32 +167,46 @@ abstract class AbstractJsc3l {
163
167
  }
164
168
 
165
169
 
166
- getBcTransaction (endpointUrl, contracts): BcTransactionAbstract {
170
+ getBcTransaction (
171
+ endpointUrl, contracts, transactionDefs
172
+ ): BcTransactionAbstract {
167
173
  const self = this
168
174
  class BcTransaction extends BcTransactionAbstract {
169
175
  ajaxReq = self.getAjaxReq(endpointUrl)
170
176
  contracts = contracts
171
177
  }
178
+ transactionFactory(transactionDefs, BcTransaction)
172
179
  return new BcTransaction()
173
180
  }
174
181
 
175
182
 
176
183
  _currencyMgrPromises = {}
177
- async getCurrencyMgr (currencyName: string, endpointUrl?: string, repoUrl?: string) {
178
- const key = Array.from(arguments).join('\0')
184
+ async getCurrencyMgr (
185
+ currencyName: string, endpointUrl?: string, repoUrl?: string,
186
+ transactionDefs?: any[],
187
+ ) {
188
+
189
+ const key = JSON.stringify(Array.from(arguments))
179
190
 
180
191
  if (!this._currencyMgrPromises[key]) {
181
192
  this._currencyMgrPromises[key] =
182
- this._getCurrencyMgr(currencyName, endpointUrl, repoUrl)
193
+ this._getCurrencyMgr(currencyName, endpointUrl, repoUrl, transactionDefs)
183
194
  }
184
195
 
185
- return await this._currencyMgrPromises[key]
186
- }
196
+ try {
197
+ return await this._currencyMgrPromises[key]
198
+ } catch(e) {
199
+ delete this._currencyMgrPromises[key]
200
+ throw e
201
+ }
187
202
 
203
+ }
188
204
 
189
205
  async _getCurrencyMgr (currencyName: string,
190
206
  endpointUrl?: string,
191
- repoUrl?: string): Promise<any> {
207
+ repoUrl?: string,
208
+ transactionDefs?: any[],
209
+ ): Promise<any> {
192
210
  if (!repoUrl) {
193
211
  if (this.connection.repo) {
194
212
  repoUrl = this.connection.repo
@@ -205,15 +223,19 @@ abstract class AbstractJsc3l {
205
223
  }
206
224
  }
207
225
 
226
+ transactionDefs = transactionDefs || localTransactionDefs
227
+
208
228
  const config = await this.getConfig(repoUrl, currencyName)
209
229
  const customization = this.getCustomization(config)
210
230
  const contracts = [
211
231
  customization.getContract1(),
212
- customization.getContract2()
232
+ customization.getContract2(),
233
+ customization.getContract3()
213
234
  ]
214
235
 
215
236
  const wallet = this.getWallet(
216
- endpointUrl, currencyName, customization.getUnlockUrl())
237
+ endpointUrl, currencyName, customization.getUnlockUrl()
238
+ )
217
239
  return {
218
240
  // unlockWallet: (jsonData, password) => wallet.getWalletFromPrivKeyFile(jsonData, password),
219
241
  jsc3l: this,
@@ -221,20 +243,19 @@ abstract class AbstractJsc3l {
221
243
  ajaxReq: this.getAjaxReq(endpointUrl),
222
244
  wallet: wallet,
223
245
  bcRead: this.getBcRead(endpointUrl, contracts),
224
- bcTransaction: this.getBcTransaction(endpointUrl, contracts),
246
+ bcTransaction: this.getBcTransaction(
247
+ endpointUrl, contracts, transactionDefs
248
+ ),
225
249
  }
226
250
  }
227
251
  }
228
252
 
229
253
 
230
-
231
-
232
-
233
-
234
254
  Object.assign(AbstractJsc3l.prototype, {
235
255
  memo,
236
256
  ethFuncs,
237
- createIcon
257
+ createIcon,
258
+ qr,
238
259
  })
239
260
 
240
261
 
@@ -290,13 +311,13 @@ abstract class IntegratedJsc3lAbstract extends AbstractJsc3l {
290
311
  */
291
312
  get wallet (): MessagingWalletAbstract["constructor"] {
292
313
  if (!this.ajaxReq) {
293
- throw Error('a connect() is required before accessing wallet')
314
+ throw new Error('a connect() is required before accessing wallet')
294
315
  }
295
316
  let localCfg: any
296
317
  try {
297
318
  localCfg = this.customization
298
319
  } catch (e) {
299
- throw Error('A local conf needs to be available before accessing wallet')
320
+ throw new Error('A local conf needs to be available before accessing wallet')
300
321
  }
301
322
  return this.getWallet(
302
323
  this.ajaxReq.endpoint.baseUrl,
@@ -319,13 +340,13 @@ abstract class IntegratedJsc3lAbstract extends AbstractJsc3l {
319
340
  */
320
341
  get bcRead (): BcReadAbstract {
321
342
  if (!this.ajaxReq) {
322
- throw Error('an init() is required before accessing bcRead')
343
+ throw new Error('an init() is required before accessing bcRead')
323
344
  }
324
345
  let localCfg: any
325
346
  try {
326
347
  localCfg = this.customization
327
348
  } catch (e) {
328
- throw Error('A local conf needs to be available before accessing wallet')
349
+ throw new Error('A local conf needs to be available before accessing wallet')
329
350
  }
330
351
  return this.getBcRead(
331
352
  this.ajaxReq.endpoint.baseUrl,
@@ -348,17 +369,22 @@ abstract class IntegratedJsc3lAbstract extends AbstractJsc3l {
348
369
  */
349
370
  get bcTransaction (): BcTransactionAbstract {
350
371
  if (!this.ajaxReq) {
351
- throw Error('an init() is required before accessing bcTransaction')
372
+ throw new Error('an init() is required before accessing bcTransaction')
352
373
  }
353
374
  let localCfg: any
354
375
  try {
355
376
  localCfg = this.customization
356
377
  } catch (e) {
357
- throw Error('A local conf needs to be available before accessing wallet')
378
+ throw new Error('A local conf needs to be available before accessing wallet')
358
379
  }
359
380
  return this.getBcTransaction(
360
381
  this.ajaxReq.endpoint.baseUrl,
361
- [localCfg.getContract1(), localCfg.getContract2()]
382
+ [
383
+ localCfg.getContract1(),
384
+ localCfg.getContract2(),
385
+ localCfg.getContract3(),
386
+ ],
387
+ this.defaultTransactionDefs
362
388
  )
363
389
  }
364
390
 
package/src/qr.ts CHANGED
@@ -1,20 +1,43 @@
1
1
  import ethUtil from 'ethereumjs-util'
2
2
 
3
3
 
4
- export function checkSignedQRFromString (qrString, intendedRecipientAddress) {
5
- let data:string, signature: string
6
- try {
7
- ({ data, signature } = JSON.parse(qrString))
8
- } catch (e) {
9
- return 'InvalidFormat'
10
- }
11
- return checkSignedQR(data, signature, intendedRecipientAddress)
4
+
5
+ type Signature = {
6
+ v: string,
7
+ r: string,
8
+ s: string,
9
+ }
10
+
11
+ type QRDataRaw = {
12
+ address: string,
13
+ destinary: string,
14
+ begin: string,
15
+ end: string,
16
+ viewbalance: boolean,
17
+ viewoldtran: boolean,
18
+ message_key?: string,
19
+ }
20
+
21
+ type QRData = {
22
+ address: string,
23
+ destinary: string,
24
+ begin: Date,
25
+ end: Date,
26
+ viewbalance: boolean,
27
+ viewoldtran: boolean,
28
+ message_key?: string,
12
29
  }
13
30
 
14
- export function checkSignedQR (data, signature, intendedRecipientAddress) {
31
+
32
+ export type SignedQR = {data: QRDataRaw, signature: Signature}
33
+
34
+
35
+ export function checkSignedQR (qrContent: SignedQR, intendedRecipientAddress) {
36
+
15
37
  let hash: string
16
38
  let publicSignKey: string
17
39
  let receiverAddress: string
40
+ const { data, signature } = qrContent
18
41
  try {
19
42
  hash = ethUtil.sha3(JSON.stringify(data))
20
43
  publicSignKey = ethUtil.ecrecover(
@@ -22,13 +45,64 @@ export function checkSignedQR (data, signature, intendedRecipientAddress) {
22
45
  receiverAddress = ethUtil.bufferToHex(
23
46
  ethUtil.publicToAddress(publicSignKey))
24
47
  } catch (e) {
48
+ // XXXVlab: should probably use exceptions
25
49
  return 'InvalidFormat'
26
50
  }
27
51
 
28
- if (receiverAddress !== data.address) { return 'InvalidSignature' }
29
- if (data.destinary !== intendedRecipientAddress) { return 'NotForYou' }
52
+ if (receiverAddress !== data.address) {
53
+ return 'InvalidSignature'
54
+ }
55
+ if (data.destinary !== intendedRecipientAddress) {
56
+ return 'NotForYou'
57
+ }
30
58
  if ((new Date(data.end)).getTime() < (new Date()).getTime()) {
31
59
  return 'Expired'
32
60
  }
33
- return { signature, data }
61
+ return true
62
+ }
63
+
64
+
65
+ export function makeSignedQRFragments (
66
+ qrContent: SignedQR,
67
+ fragmentCount: number
68
+ ) {
69
+
70
+ const signatureId = qrContent.signature.s.substring(4, 8)
71
+
72
+ const qrString = JSON.stringify(qrContent)
73
+ const fragmentSize = Math.ceil(qrString.length / fragmentCount)
74
+ const fragments = {
75
+ full: qrString,
76
+ }
77
+
78
+ for (let i = 0; i < fragmentCount; i++) {
79
+ fragments[i] = `FRAG_CR${signatureId}${i}${qrString.substring(
80
+ fragmentSize * i,
81
+ Math.min(fragmentSize * (i + 1), qrString.length)
82
+ )}`
83
+ }
84
+
85
+ return fragments
86
+ }
87
+
88
+
89
+ export function makeSignedQRContent (obj: QRData, privKey: string): SignedQR {
90
+ const { begin, end } = obj
91
+ const formatDate = (date: Date) =>
92
+ `${date.getFullYear()}/${(date.getMonth()+1)}/${date.getDate()}`
93
+ const data = Object.assign(obj, {
94
+ begin: formatDate(begin),
95
+ end: formatDate(end),
96
+ })
97
+
98
+ const hash = ethUtil.sha3(JSON.stringify(data))
99
+ const { v, r, s } = ethUtil.ecsign(hash, privKey)
100
+ const signature = {
101
+ v,
102
+ r: '0x' + r.toString('hex'),
103
+ s: '0x' + s.toString('hex'),
104
+ }
105
+
106
+ return { data, signature }
107
+
34
108
  }
@@ -1,9 +1,10 @@
1
1
 
2
+ import { APIError } from '../exception'
3
+
2
4
  class URL {
3
5
  static SERVER = 'api.php';
4
6
  static ENROLL = 'enroll.php';
5
7
  static TRANLIST = 'trnslist.php';
6
- static TRANCHECK = 'api.php';
7
8
  static EXPORTTRAN = 'export.php';
8
9
  static GETCODE = 'getuid.php';
9
10
  static GETADDRESS = 'getadd.php';
@@ -35,14 +36,13 @@ export default abstract class AjaxReqAbstract {
35
36
  queuePost () {
36
37
  const { data, resolve, reject } = this.pendingPosts[0]
37
38
 
38
- try {
39
- this.endpoint.post(URL.SERVER, data).then(data => {
40
- resolve(data.data)
41
- })
42
- } catch (err) {
43
- console.log(err)
44
- reject(err)
45
- }
39
+ this.endpoint.post(URL.SERVER, data).then(res => {
40
+ if (res.error) {
41
+ reject(new APIError(res.msg, res.data))
42
+ return
43
+ }
44
+ resolve(res.data)
45
+ })
46
46
  this.pendingPosts.splice(0, 1)
47
47
  if (this.pendingPosts.length > 0) { this.queuePost() }
48
48
  }
@@ -50,18 +50,7 @@ export default abstract class AjaxReqAbstract {
50
50
 
51
51
  getBalance (addr) { return this.post({ balance: addr }) }
52
52
  getTransactionData (addr) { return this.post({ txdata: addr }) }
53
- async sendTx (rawTx, additionalData) {
54
- const data: {[k: string]: any} =
55
- await this.post(Object.assign({}, { rawtx: rawTx }, additionalData ?? {}))
56
-
57
- return {
58
- isError: !!data.error,
59
- error: data.error ? data.data : data.msg
60
- }
61
- }
62
-
63
-
64
- getEstimatedGas (txobj) { return this.post({ estimatedGas: txobj }) }
53
+ sendTx (rawTx, more) { return this.post({ rawtx: rawTx, ...(more ?? {}) }) }
65
54
  getEthCall (txobj) { return this.post({ ethCall: txobj }) }
66
55
 
67
56
  getEthCallAt (txobj, blockNb) {
@@ -77,14 +66,6 @@ export default abstract class AjaxReqAbstract {
77
66
  return this.endpoint.post(URL.ENROLL, { data: JSON.stringify(data) })
78
67
  }
79
68
 
80
- validateEnrollmentLetter (id, currency, signature) {
81
- return this.enrollPost({ id, currency, signature })
82
- }
83
-
84
- enrollAddress (id, address, currency, token) {
85
- return this.enrollPost({ id, addresse: address, token, currency })
86
- }
87
-
88
69
  async getTransList (id, count, offset) {
89
70
  // for some strange reasons, the answer is stringified 2 times,
90
71
  // so we need to unpack each entry a second time.
@@ -92,16 +73,9 @@ export default abstract class AjaxReqAbstract {
92
73
  return data.map((dataJSON) => JSON.parse(dataJSON))
93
74
  }
94
75
 
95
- getTransCheck (hash) {
96
- return this.endpoint.get(URL.TRANCHECK, { hash })
97
- }
98
-
99
- getExportTransList (id, start, end) {
100
- return this.endpoint.get(URL.EXPORTTRAN, { addr: id, start, end })
101
- }
102
-
103
- getExportTransListWithId (id, start, end) {
104
- return this.endpoint.get(URL.EXPORTTRAN, { addr: id, start, end })
76
+ async getExportTransList (id, start, end) {
77
+ const data = await this.endpoint.get(URL.EXPORTTRAN, { addr: id, start, end })
78
+ return data.map((dataJSON) => JSON.parse(dataJSON))
105
79
  }
106
80
 
107
81
  getCodesFromAddresses (addresses, currency, caller, signature) {
@@ -149,9 +123,13 @@ export default abstract class AjaxReqAbstract {
149
123
  currBlock () { return this.endpoint.get(URL.SERVER) }
150
124
 
151
125
  async getBlock (hash) {
126
+ return (await this.getTransactionInfo(hash)).transaction
127
+ }
128
+
129
+ async getTransactionInfo (hash) {
152
130
  let res = await this.endpoint.get(URL.SERVER, { hash })
153
131
  if (res && typeof res !== 'object') {
154
- res = JSON.parse(res).transaction
132
+ res = JSON.parse(res)
155
133
  }
156
134
  return res
157
135
  }