@com-chain/jsc3l 2.0.1-rc.7 → 2.0.1-rc.8

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/index.ts CHANGED
@@ -1,5 +1,6 @@
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'
@@ -17,8 +18,8 @@ import ConnectionMgrAbstract from './connection'
17
18
  import CustomizationAbstract from './customization'
18
19
  import MessagingWalletAbstract from './wallet'
19
20
  import BcReadAbstract from './bcRead'
20
- import BcTransactionAbstract from './bcTransaction'
21
-
21
+ import { BcTransactionAbstract, transactionFactory } from './bcTransaction'
22
+ import localTransactionDefs from './config/transactions'
22
23
 
23
24
 
24
25
  function createIcon (address: string | Wallet) {
@@ -39,6 +40,7 @@ abstract class AbstractJsc3l {
39
40
  protected abstract persistentStore: t.IPersistentStore
40
41
 
41
42
  localDefaultConf: {}
43
+ defaultTransactionDefs: []
42
44
 
43
45
  endpoint: string
44
46
 
@@ -47,8 +49,9 @@ abstract class AbstractJsc3l {
47
49
  _http: null | HttpAbstract
48
50
 
49
51
 
50
- constructor (localDefaultConf?) {
52
+ constructor (localDefaultConf?, defaultTransactionDefs?) {
51
53
  this.localDefaultConf = localDefaultConf || {}
54
+ this.defaultTransactionDefs = defaultTransactionDefs || localTransactionDefs
52
55
  }
53
56
 
54
57
  /**
@@ -163,23 +166,30 @@ abstract class AbstractJsc3l {
163
166
  }
164
167
 
165
168
 
166
- getBcTransaction (endpointUrl, contracts): BcTransactionAbstract {
169
+ getBcTransaction (
170
+ endpointUrl, contracts, transactionDefs
171
+ ): BcTransactionAbstract {
167
172
  const self = this
168
173
  class BcTransaction extends BcTransactionAbstract {
169
174
  ajaxReq = self.getAjaxReq(endpointUrl)
170
175
  contracts = contracts
171
176
  }
177
+ transactionFactory(transactionDefs, BcTransaction)
172
178
  return new BcTransaction()
173
179
  }
174
180
 
175
181
 
176
182
  _currencyMgrPromises = {}
177
- async getCurrencyMgr (currencyName: string, endpointUrl?: string, repoUrl?: string) {
178
- const key = Array.from(arguments).join('\0')
183
+ async getCurrencyMgr (
184
+ currencyName: string, endpointUrl?: string, repoUrl?: string,
185
+ transactionDefs?: any[],
186
+ ) {
187
+
188
+ const key = JSON.stringify(Array.from(arguments))
179
189
 
180
190
  if (!this._currencyMgrPromises[key]) {
181
191
  this._currencyMgrPromises[key] =
182
- this._getCurrencyMgr(currencyName, endpointUrl, repoUrl)
192
+ this._getCurrencyMgr(currencyName, endpointUrl, repoUrl, transactionDefs)
183
193
  }
184
194
 
185
195
  return await this._currencyMgrPromises[key]
@@ -188,7 +198,9 @@ abstract class AbstractJsc3l {
188
198
 
189
199
  async _getCurrencyMgr (currencyName: string,
190
200
  endpointUrl?: string,
191
- repoUrl?: string): Promise<any> {
201
+ repoUrl?: string,
202
+ transactionDefs?: any[],
203
+ ): Promise<any> {
192
204
  if (!repoUrl) {
193
205
  if (this.connection.repo) {
194
206
  repoUrl = this.connection.repo
@@ -205,15 +217,19 @@ abstract class AbstractJsc3l {
205
217
  }
206
218
  }
207
219
 
220
+ transactionDefs = transactionDefs || localTransactionDefs
221
+
208
222
  const config = await this.getConfig(repoUrl, currencyName)
209
223
  const customization = this.getCustomization(config)
210
224
  const contracts = [
211
225
  customization.getContract1(),
212
- customization.getContract2()
226
+ customization.getContract2(),
227
+ customization.getContract3()
213
228
  ]
214
229
 
215
230
  const wallet = this.getWallet(
216
- endpointUrl, currencyName, customization.getUnlockUrl())
231
+ endpointUrl, currencyName, customization.getUnlockUrl()
232
+ )
217
233
  return {
218
234
  // unlockWallet: (jsonData, password) => wallet.getWalletFromPrivKeyFile(jsonData, password),
219
235
  jsc3l: this,
@@ -221,7 +237,9 @@ abstract class AbstractJsc3l {
221
237
  ajaxReq: this.getAjaxReq(endpointUrl),
222
238
  wallet: wallet,
223
239
  bcRead: this.getBcRead(endpointUrl, contracts),
224
- bcTransaction: this.getBcTransaction(endpointUrl, contracts),
240
+ bcTransaction: this.getBcTransaction(
241
+ endpointUrl, contracts, transactionDefs
242
+ ),
225
243
  }
226
244
  }
227
245
  }
@@ -230,7 +248,8 @@ abstract class AbstractJsc3l {
230
248
  Object.assign(AbstractJsc3l.prototype, {
231
249
  memo,
232
250
  ethFuncs,
233
- createIcon
251
+ createIcon,
252
+ qr,
234
253
  })
235
254
 
236
255
 
@@ -354,7 +373,12 @@ abstract class IntegratedJsc3lAbstract extends AbstractJsc3l {
354
373
  }
355
374
  return this.getBcTransaction(
356
375
  this.ajaxReq.endpoint.baseUrl,
357
- [localCfg.getContract1(), localCfg.getContract2()]
376
+ [
377
+ localCfg.getContract1(),
378
+ localCfg.getContract2(),
379
+ localCfg.getContract3(),
380
+ ],
381
+ this.defaultTransactionDefs
358
382
  )
359
383
  }
360
384
 
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()}/${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
  }
@@ -80,14 +80,6 @@ export default abstract class AjaxReqAbstract {
80
80
  return this.endpoint.post(URL.ENROLL, { data: JSON.stringify(data) })
81
81
  }
82
82
 
83
- validateEnrollmentLetter (id, currency, signature) {
84
- return this.enrollPost({ id, currency, signature })
85
- }
86
-
87
- enrollAddress (id, address, currency, token) {
88
- return this.enrollPost({ id, addresse: address, token, currency })
89
- }
90
-
91
83
  async getTransList (id, count, offset) {
92
84
  // for some strange reasons, the answer is stringified 2 times,
93
85
  // so we need to unpack each entry a second time.
package/src/wallet.ts CHANGED
@@ -1,6 +1,7 @@
1
- import ethUtil from 'ethereumjs-util'
2
-
3
1
  import AjaxReq from './rest/ajaxReq'
2
+ import {
3
+ checkSignedQR, SignedQR, makeSignedQRContent, makeSignedQRFragments
4
+ } from './qr'
4
5
  import { shortenAddress, cipherMsg, decipherMsg } from './ethereum/cipher'
5
6
  import Wallet from './ethereum/myetherwallet'
6
7
 
@@ -121,10 +122,22 @@ export default abstract class MessagingWalletAbstract extends Wallet {
121
122
  })
122
123
  }
123
124
 
124
- public enrollAddress (codeId, token) {
125
- return this.ajaxReq.enrollAddress(
126
- codeId, this.getAddressString(),
127
- this.currencyName, token)
125
+ public validateEnrollment (id, signature) {
126
+ return this.ajaxReq.enrollPost({
127
+ id,
128
+ signature,
129
+ currency: this.currencyName,
130
+ })
131
+ }
132
+
133
+ public enrollAddress (id, token) {
134
+ return this.ajaxReq.enrollPost({
135
+ id,
136
+ token,
137
+ currency: this.currencyName,
138
+ // XXXvlab: Yes, typo is intentional here (in PHP API):
139
+ addresse: this.getAddressString(),
140
+ })
128
141
  }
129
142
 
130
143
  public requestUnlock () {
@@ -148,54 +161,38 @@ export default abstract class MessagingWalletAbstract extends Wallet {
148
161
  }
149
162
  }
150
163
 
151
-
152
164
  //
153
- // QR Codes requires EthUtils
165
+ // QR Code helpers
154
166
  //
155
167
 
156
- public makeSignedQRWithPubKey (objContent, pubKey) {
157
- objContent.message_key = cipherMsg(
158
- pubKey, this.messageKeysFromWallet()
159
- )
160
- objContent.address = this.getAddressString()
161
- return this.makeSignedQR(objContent)
168
+ public makeSignedQRContent (obj, pubKey: string | null) {
169
+ return makeSignedQRContent({
170
+ server: this.currencyName,
171
+ address: this.getAddressString(),
172
+ ...obj,
173
+ ...pubKey && {
174
+ message_key: cipherMsg(pubKey, this.messageKeysFromWallet())
175
+ },
176
+ }, this.privKey)
162
177
  }
163
178
 
164
- public makeSignedQR (obj) {
165
-
166
- // Values expected:
167
- const {
168
- server, destinary, begin, end,
169
- viewbalance, viewoldtran, pub_key
170
- } = obj
171
- const formatDate = (date) =>
172
- `${begin.getFullYear()}/${begin.getMonth()}/${begin.getDate()}`
173
- const objContent = Object.assign(obj, {
174
- address: this.getAddressString(),
175
- begin: formatDate(begin),
176
- end: formatDate(end)
177
- })
179
+ public makeSignedQRFragments (
180
+ obj, fragmentCount: number, pubKey: string | null
181
+ ) {
182
+ return makeSignedQRFragments(
183
+ this.makeSignedQRContent(obj, pubKey),
184
+ fragmentCount,
185
+ )
186
+ }
178
187
 
179
- const hash = ethUtil.sha3(JSON.stringify(objContent))
180
- const signature = ethUtil.ecsign(hash, this.privKey)
181
- return {
182
- signature,
183
- qrContent: JSON.stringify({
184
- data: objContent,
185
- signature: {
186
- v: signature.v,
187
- r: '0x' + signature.r.toString('hex'),
188
- s: '0x' + signature.s.toString('hex')
189
- }
190
- })
188
+ public checkSignedQRFromString (qrString: string) {
189
+ let qrContent: SignedQR
190
+ try {
191
+ qrContent = JSON.parse(qrString)
192
+ } catch (e) {
193
+ return 'InvalidFormat'
191
194
  }
195
+ return checkSignedQR(qrContent, this.getAddressString())
192
196
  }
193
197
 
194
198
  }
195
-
196
- // // TODO: What to do with this validateEnrollment
197
- // public static validateEnrollment (codeId, signature) {
198
- // return this.ajaxReq.validateEnrollmentLetter(
199
- // codeId, this.currencyName, signature)
200
- // }
201
-