@com-chain/jsc3l 2.0.1-rc.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/LICENSE +661 -0
- package/README.md +45 -0
- package/build/bcRead.d.ts +15 -0
- package/build/bcRead.js +123 -0
- package/build/bcRead.js.map +1 -0
- package/build/bcTransaction.d.ts +10 -0
- package/build/bcTransaction.js +135 -0
- package/build/bcTransaction.js.map +1 -0
- package/build/blockies.d.ts +1 -0
- package/build/blockies.js +91 -0
- package/build/blockies.js.map +1 -0
- package/build/config.d.ts +6 -0
- package/build/config.js +25 -0
- package/build/config.js.map +1 -0
- package/build/connection.d.ts +58 -0
- package/build/connection.js +204 -0
- package/build/connection.js.map +1 -0
- package/build/customization.d.ts +37 -0
- package/build/customization.js +129 -0
- package/build/customization.js.map +1 -0
- package/build/ethereum/cipher.d.ts +3 -0
- package/build/ethereum/cipher.js +94 -0
- package/build/ethereum/cipher.js.map +1 -0
- package/build/ethereum/ethFuncs.d.ts +12 -0
- package/build/ethereum/ethFuncs.js +70 -0
- package/build/ethereum/ethFuncs.js.map +1 -0
- package/build/ethereum/etherUnits.d.ts +5 -0
- package/build/ethereum/etherUnits.js +60 -0
- package/build/ethereum/etherUnits.js.map +1 -0
- package/build/ethereum/myetherwallet.d.ts +47 -0
- package/build/ethereum/myetherwallet.js +294 -0
- package/build/ethereum/myetherwallet.js.map +1 -0
- package/build/ethereum/uiFuncs.d.ts +3 -0
- package/build/ethereum/uiFuncs.js +51 -0
- package/build/ethereum/uiFuncs.js.map +1 -0
- package/build/index.d.ts +111 -0
- package/build/index.js +310 -0
- package/build/index.js.map +1 -0
- package/build/memo.d.ts +6 -0
- package/build/memo.js +24 -0
- package/build/memo.js.map +1 -0
- package/build/qr.d.ts +8 -0
- package/build/qr.js +35 -0
- package/build/qr.js.map +1 -0
- package/build/rest/ajaxReq.d.ts +31 -0
- package/build/rest/ajaxReq.js +127 -0
- package/build/rest/ajaxReq.js.map +1 -0
- package/build/rest/endpoint.d.ts +18 -0
- package/build/rest/endpoint.js +26 -0
- package/build/rest/endpoint.js.map +1 -0
- package/build/rest/http.d.ts +10 -0
- package/build/rest/http.js +60 -0
- package/build/rest/http.js.map +1 -0
- package/build/rest/serializer.d.ts +1 -0
- package/build/rest/serializer.js +94 -0
- package/build/rest/serializer.js.map +1 -0
- package/build/type.d.ts +24 -0
- package/build/type.js +9 -0
- package/build/type.js.map +1 -0
- package/build/wallet.d.ts +35 -0
- package/build/wallet.js +162 -0
- package/build/wallet.js.map +1 -0
- package/package.json +41 -0
- package/src/bcRead.ts +184 -0
- package/src/bcTransaction.ts +157 -0
- package/src/blockies.ts +113 -0
- package/src/config.ts +33 -0
- package/src/connection.ts +243 -0
- package/src/customization.ts +156 -0
- package/src/ethereum/cipher.ts +118 -0
- package/src/ethereum/ethFuncs.ts +73 -0
- package/src/ethereum/etherUnits.ts +66 -0
- package/src/ethereum/myetherwallet.ts +354 -0
- package/src/ethereum/uiFuncs.ts +55 -0
- package/src/index.ts +366 -0
- package/src/memo.ts +37 -0
- package/src/qr.ts +34 -0
- package/src/rest/ajaxReq.ts +160 -0
- package/src/rest/endpoint.ts +31 -0
- package/src/rest/http.ts +69 -0
- package/src/rest/serializer.ts +99 -0
- package/src/type.ts +37 -0
- package/src/wallet.ts +200 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
|
|
2
|
+
import { getNakedAddress, padLeft, encodeNumber } from './ethereum/ethFuncs'
|
|
3
|
+
import { generateTx } from './ethereum/uiFuncs'
|
|
4
|
+
import AjaxReq from './rest/ajaxReq'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function roundCent (strAmount:string) {
|
|
8
|
+
return Math.round(100 * parseFloat(strAmount))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
function typeConv (label: string): (x:any) => (string | number) {
|
|
13
|
+
if (label.endsWith('Address')) {
|
|
14
|
+
return (a) => padLeft(getNakedAddress(a), 64)
|
|
15
|
+
}
|
|
16
|
+
if (label.startsWith('limit') || label === 'amount') {
|
|
17
|
+
return (nb) => encodeNumber(roundCent(nb))
|
|
18
|
+
}
|
|
19
|
+
if (label.endsWith('Status') || label.endsWith('Type')) {
|
|
20
|
+
return (nb) => encodeNumber(nb)
|
|
21
|
+
}
|
|
22
|
+
if (label === 'status') {
|
|
23
|
+
return (nb) => (parseInt(nb, 10) === 0 ? 0 : 1)
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`Unexpected label '${label}' in FnDefs.`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export default abstract class BcTransactionAbstract {
|
|
30
|
+
|
|
31
|
+
abstract ajaxReq: AjaxReq
|
|
32
|
+
abstract contracts: string[]
|
|
33
|
+
|
|
34
|
+
// //////////////////////////////////////////////////////////////////////////
|
|
35
|
+
// CM VS Nant Handling
|
|
36
|
+
|
|
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
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const possible = res === 0
|
|
72
|
+
return { possible: possible, nant: nant, cm: cm }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// //////////////////////////////////////////////////////////////////////////
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
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
|
+
}
|
|
123
|
+
|
|
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)
|
|
136
|
+
}
|
|
137
|
+
const additionalPostData = hasAdditionalPostData ? args.pop() : {}
|
|
138
|
+
if (hasDelegate) {
|
|
139
|
+
additionalPostData.delegate = wallet.getAddressString()
|
|
140
|
+
}
|
|
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
|
+
}
|
|
156
|
+
}
|
|
157
|
+
})
|
package/src/blockies.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
|
|
2
|
+
// Adapted from
|
|
3
|
+
// https://github.com/alexvandesande/blockies/blob/master/blockies.js
|
|
4
|
+
// updated tayvano 3.9.16
|
|
5
|
+
|
|
6
|
+
// The random number is a js implementation of the Xorshift PRNG
|
|
7
|
+
const randseed = new Array(4) // Xorshift: [x, y, z, w] 32 bit values
|
|
8
|
+
|
|
9
|
+
function seedrand (seed) {
|
|
10
|
+
for (let i = 0; i < randseed.length; i++) {
|
|
11
|
+
randseed[i] = 0
|
|
12
|
+
}
|
|
13
|
+
for (let i = 0; i < seed.length; i++) {
|
|
14
|
+
randseed[i % 4] = ((randseed[i % 4] << 5) - randseed[i % 4]) +
|
|
15
|
+
seed.charCodeAt(i)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function rand () {
|
|
20
|
+
// based on Java's String.hashCode(), expanded to 4 32bit values
|
|
21
|
+
const t = randseed[0] ^ (randseed[0] << 11)
|
|
22
|
+
|
|
23
|
+
randseed[0] = randseed[1]
|
|
24
|
+
randseed[1] = randseed[2]
|
|
25
|
+
randseed[2] = randseed[3]
|
|
26
|
+
randseed[3] = (randseed[3] ^ (randseed[3] >> 19) ^ t ^ (t >> 8))
|
|
27
|
+
|
|
28
|
+
return (randseed[3] >>> 0) / ((1 << 31) >>> 0)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createColor () {
|
|
32
|
+
// saturation is the whole color spectrum
|
|
33
|
+
const h = Math.floor(rand() * 360)
|
|
34
|
+
// saturation goes from 40 to 100, it avoids greyish colors
|
|
35
|
+
const s = ((rand() * 60) + 40) + '%'
|
|
36
|
+
// lightness can be anything from 0 to 100, but probabilities are a
|
|
37
|
+
// bell curve around 50%
|
|
38
|
+
const l = ((rand() + rand() + rand() + rand()) * 25) + '%'
|
|
39
|
+
|
|
40
|
+
const color = 'hsl(' + h + ',' + s + ',' + l + ')'
|
|
41
|
+
return color
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function createImageData (size) {
|
|
45
|
+
const width = size // Only support square icons for now
|
|
46
|
+
const height = size
|
|
47
|
+
|
|
48
|
+
const dataWidth = Math.ceil(width / 2)
|
|
49
|
+
const mirrorWidth = width - dataWidth
|
|
50
|
+
|
|
51
|
+
const data = []
|
|
52
|
+
for (let y = 0; y < height; y++) {
|
|
53
|
+
let row = []
|
|
54
|
+
for (let x = 0; x < dataWidth; x++) {
|
|
55
|
+
// this makes foreground and background color to have a 43%
|
|
56
|
+
// (1/2.3) probability spot color has 13% chance
|
|
57
|
+
row[x] = Math.floor(rand() * 2.3)
|
|
58
|
+
}
|
|
59
|
+
const r = row.slice(0, mirrorWidth)
|
|
60
|
+
r.reverse()
|
|
61
|
+
row = row.concat(r)
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < row.length; i++) {
|
|
64
|
+
data.push(row[i])
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return data
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createCanvas (imageData, color, scale, bgcolor, spotcolor) {
|
|
72
|
+
const c = document.createElement('canvas')
|
|
73
|
+
const width = Math.sqrt(imageData.length)
|
|
74
|
+
c.width = c.height = width * scale
|
|
75
|
+
|
|
76
|
+
const cc = c.getContext('2d')
|
|
77
|
+
cc.fillStyle = bgcolor
|
|
78
|
+
cc.fillRect(0, 0, c.width, c.height)
|
|
79
|
+
cc.fillStyle = color
|
|
80
|
+
|
|
81
|
+
for (let i = 0; i < imageData.length; i++) {
|
|
82
|
+
const row = Math.floor(i / width)
|
|
83
|
+
const col = i % width
|
|
84
|
+
// if data is 2, choose spot color, if 1 choose foreground
|
|
85
|
+
cc.fillStyle = (imageData[i] === 1) ? color : spotcolor
|
|
86
|
+
|
|
87
|
+
// if data is 0, leave the background
|
|
88
|
+
if (imageData[i]) {
|
|
89
|
+
cc.fillRect(col * scale, row * scale, scale, scale)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return c
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default function (opts) {
|
|
97
|
+
opts = opts || {}
|
|
98
|
+
const size = opts.size || 8
|
|
99
|
+
const scale = opts.scale || 4
|
|
100
|
+
const seed = opts.seed || Math.floor((Math.random() *
|
|
101
|
+
Math.pow(10, 16))).toString(16)
|
|
102
|
+
|
|
103
|
+
seedrand(seed)
|
|
104
|
+
|
|
105
|
+
const color = opts.color || createColor()
|
|
106
|
+
const bgcolor = opts.bgcolor || createColor()
|
|
107
|
+
const spotcolor = opts.spotcolor || createColor()
|
|
108
|
+
const imageData = createImageData(size)
|
|
109
|
+
const canvas = createCanvas(imageData, color, scale, bgcolor, spotcolor)
|
|
110
|
+
|
|
111
|
+
return canvas
|
|
112
|
+
}
|
|
113
|
+
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
export const confEndPointsOur = [
|
|
3
|
+
'https://node-001.cchosting.org',
|
|
4
|
+
'https://node-002.cchosting.org',
|
|
5
|
+
'https://node-003.cchosting.org',
|
|
6
|
+
'https://node-004.cchosting.org',
|
|
7
|
+
'https://node-cc-001.cchosting.org/',
|
|
8
|
+
'https://api.monnaie-leman.org'
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
export const confEndPointsOther = [
|
|
12
|
+
'https://ipfs.io',
|
|
13
|
+
'https://ipfs.infura.io',
|
|
14
|
+
'https://ipfs.jes.xxx',
|
|
15
|
+
'https://siderus.io',
|
|
16
|
+
'https://hardbin.com',
|
|
17
|
+
'https://ipfs.infura.io',
|
|
18
|
+
'https://xmine128.tk'
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
// IPNS of the list of available ComChain currency configs
|
|
22
|
+
export const configRepo =
|
|
23
|
+
'/ipns/QmaAAZor2uLKnrzGCwyXTSwogJqmPjJgvpYgpmtz5XcSmR/configs'
|
|
24
|
+
|
|
25
|
+
// IPNS of the list of available ComChain end-points
|
|
26
|
+
export const nodesRepo =
|
|
27
|
+
'/ipns/QmcRWARTpuEf9E87cdA4FfjBkv7rKTJyfvsLFTzXsGATbL'
|
|
28
|
+
|
|
29
|
+
// IPNS of the configuration for the different currencies
|
|
30
|
+
export const custoRepo =
|
|
31
|
+
'/ipns/QmaAAZor2uLKnrzGCwyXTSwogJqmPjJgvpYgpmtz5XcSmR/resources/'
|
|
32
|
+
|
|
33
|
+
export const ping = configRepo + '/ping.json'
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import * as config from './config'
|
|
2
|
+
import HttpAbstract from './rest/http'
|
|
3
|
+
import * as t from './type'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
abstract class ConnectionAbstract {
|
|
7
|
+
|
|
8
|
+
protected abstract http: HttpAbstract
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
///
|
|
12
|
+
// [High level] Look for an available IPFS/IPNS node and return it
|
|
13
|
+
///
|
|
14
|
+
|
|
15
|
+
public async lookupAvailableComChainRepo (storedEndPointsSuggestion?: string[]) {
|
|
16
|
+
// 1. Check if a list of endpoint is stored locally (avoid a IPNS slow call)
|
|
17
|
+
const storedEndPoints = storedEndPointsSuggestion || []
|
|
18
|
+
|
|
19
|
+
const endPointLists = [
|
|
20
|
+
storedEndPoints, // 1. try locally stored end-points if any
|
|
21
|
+
config.confEndPointsOur, // 2. try the hard-coded Com-Chain list
|
|
22
|
+
config.confEndPointsOther // 3. As a backup try standard ipfs servers (slow)
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < endPointLists.length; i++) {
|
|
26
|
+
const repo = await this.checkRepo(endPointLists[i])
|
|
27
|
+
if (repo) return repo
|
|
28
|
+
}
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
///
|
|
33
|
+
// [High level] Get the list of endpoints and randomly select a up
|
|
34
|
+
// and running one
|
|
35
|
+
///
|
|
36
|
+
public async acquireEndPoint (repo: string) {
|
|
37
|
+
const apiNodes = await this.getCCEndPointList(repo)
|
|
38
|
+
if (!apiNodes) return false
|
|
39
|
+
const endpoint = await this.selectEndPoint(apiNodes)
|
|
40
|
+
return { apiNodes, endpoint }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
///
|
|
44
|
+
// [Lower level] Get the list of ComChain end-points from given repo
|
|
45
|
+
///
|
|
46
|
+
getCCEndPointList (repo: string) {
|
|
47
|
+
return this.http.get(repo + config.nodesRepo, { _: new Date().getTime() })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
///
|
|
51
|
+
// [Lower level] Select a ComChain end-point with up and running APIs
|
|
52
|
+
///
|
|
53
|
+
async selectEndPoint (nodes: string[]) {
|
|
54
|
+
while (nodes.length > 0) {
|
|
55
|
+
// randomly select a node (poor man's load balancing)
|
|
56
|
+
const id = Math.floor((Math.random() * nodes.length))
|
|
57
|
+
const node = nodes[id]
|
|
58
|
+
|
|
59
|
+
// check the node is up and running
|
|
60
|
+
const success = await this.testNode(node)
|
|
61
|
+
if (success) return node
|
|
62
|
+
nodes.splice(id, 1)
|
|
63
|
+
}
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
///
|
|
68
|
+
// [Lower level] Test if a end-point has up and running APIs
|
|
69
|
+
///
|
|
70
|
+
async testNode (apiAddress) {
|
|
71
|
+
const result = await this.testDbApi(apiAddress)
|
|
72
|
+
if (!result) return false
|
|
73
|
+
|
|
74
|
+
return this.testApi(apiAddress)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
// //////////////////////////////////////////////////////////////////////////
|
|
79
|
+
|
|
80
|
+
async checkRepo (repoList) {
|
|
81
|
+
while (repoList?.length) {
|
|
82
|
+
const id = Math.floor((Math.random() * repoList.length))
|
|
83
|
+
const repo = repoList[id]
|
|
84
|
+
try {
|
|
85
|
+
await this.http.get(repo + config.ping, null, { timeout: 3000 })
|
|
86
|
+
console.log(`Connection OK to ${repo}`)
|
|
87
|
+
return repo
|
|
88
|
+
} catch (err) {
|
|
89
|
+
console.log(`Failed to make contact ${repo} in less that 3s`)
|
|
90
|
+
console.log(` Reason: ${err}`)
|
|
91
|
+
repoList.splice(id, 1)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async testApi (apiAddress) {
|
|
98
|
+
try {
|
|
99
|
+
const answer = await this.http.get(
|
|
100
|
+
apiAddress + '/api.php', null,
|
|
101
|
+
{ timeout: 5000 })
|
|
102
|
+
return answer !== 'null' && !answer.error && answer
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.log(`API Check: HTTP request to ${apiAddress} failed`, err)
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async testDbApi (apiAddress) {
|
|
110
|
+
try {
|
|
111
|
+
const answer = await this.http.get(
|
|
112
|
+
apiAddress + '/dbcheck.php', null,
|
|
113
|
+
{ timeout: 5000 })
|
|
114
|
+
return answer === 'pong'
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.log(`DbAPI Check: HTTP request to ${apiAddress} failed`, err)
|
|
117
|
+
return false
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Gets the configuration for the given currency
|
|
124
|
+
*
|
|
125
|
+
*/
|
|
126
|
+
public async getConfJSON (repo, currencyName) {
|
|
127
|
+
try {
|
|
128
|
+
return await this.http.get(
|
|
129
|
+
`${repo}${config.configRepo}/${currencyName}.json`,
|
|
130
|
+
{ _: new Date().getTime() })
|
|
131
|
+
} catch (err) {
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Manages Persistent Store to keep list of nodes and avoid IPFS lookup
|
|
141
|
+
* when possible.
|
|
142
|
+
*
|
|
143
|
+
*/
|
|
144
|
+
export default abstract class ConnectionMgrAbstract extends ConnectionAbstract {
|
|
145
|
+
|
|
146
|
+
protected abstract persistentStore: t.IPersistentStore
|
|
147
|
+
|
|
148
|
+
repo: string
|
|
149
|
+
conf: any
|
|
150
|
+
endpoint: string
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* This lookup will store result in memory for speeding other methods.
|
|
155
|
+
*/
|
|
156
|
+
public async lookupAvailableComChainRepo (storedEndPointsSuggestion?: string[]) {
|
|
157
|
+
|
|
158
|
+
if (!storedEndPointsSuggestion) {
|
|
159
|
+
const apiNodeSuggestions = this.persistentStore.get('ApiNodes', '[]')
|
|
160
|
+
storedEndPointsSuggestion = JSON.parse(apiNodeSuggestions)
|
|
161
|
+
}
|
|
162
|
+
const repo = await super.lookupAvailableComChainRepo(storedEndPointsSuggestion)
|
|
163
|
+
if (!repo) {
|
|
164
|
+
throw new Error('No repository available.')
|
|
165
|
+
}
|
|
166
|
+
this.repo = repo
|
|
167
|
+
return repo
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* This lookup will store result in memory for speeding other methods.
|
|
173
|
+
* and saves the result in persistentStore for faster calls.
|
|
174
|
+
*/
|
|
175
|
+
public async acquireEndPoint (repo?: string) {
|
|
176
|
+
if (!repo) {
|
|
177
|
+
if (!this.repo) {
|
|
178
|
+
// Will have a look in the persistent store for suggestions,
|
|
179
|
+
// and save in `this.repo` the result for other methods.
|
|
180
|
+
await this.lookupAvailableComChainRepo()
|
|
181
|
+
}
|
|
182
|
+
repo = this.repo
|
|
183
|
+
}
|
|
184
|
+
const apiNodesEndpoint = await super.acquireEndPoint(repo)
|
|
185
|
+
if (!apiNodesEndpoint) {
|
|
186
|
+
throw new Error('Endpoint list retrieval failed.')
|
|
187
|
+
}
|
|
188
|
+
const { apiNodes, endpoint } = apiNodesEndpoint
|
|
189
|
+
if (typeof endpoint !== 'string') {
|
|
190
|
+
throw new Error('No endpoint in list seems available.')
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.persistentStore.set('ApiNodes', JSON.stringify(apiNodes))
|
|
194
|
+
this.endpoint = endpoint
|
|
195
|
+
return { apiNodes, endpoint }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* This lookup will store result in memory for speeding other methods.
|
|
201
|
+
* and saves the result in persistentStore for faster calls.
|
|
202
|
+
* - If argument `repo` is not provided, it'll use the last one in memory
|
|
203
|
+
* leaved by a previous call of `lookupAvailableComChainRepo()`.
|
|
204
|
+
* - If no previous call was made, it'll do one.
|
|
205
|
+
*/
|
|
206
|
+
public async getConfJSON (currencyName: string, repo?: string) {
|
|
207
|
+
if (!repo) {
|
|
208
|
+
if (!this.repo) {
|
|
209
|
+
// Will have a look in the persistent store for suggestions,
|
|
210
|
+
// and save in `this.repo` the result for other methods.
|
|
211
|
+
await this.lookupAvailableComChainRepo()
|
|
212
|
+
}
|
|
213
|
+
repo = this.repo
|
|
214
|
+
}
|
|
215
|
+
const conf = await super.getConfJSON(repo, currencyName)
|
|
216
|
+
if (!conf) {
|
|
217
|
+
throw new Error('Failed to get conf.')
|
|
218
|
+
}
|
|
219
|
+
this.persistentStore.set('ServerConf', JSON.stringify(conf))
|
|
220
|
+
this.conf = conf
|
|
221
|
+
// Completing with other informations
|
|
222
|
+
conf.repo = repo
|
|
223
|
+
conf.custoRepo = repo + config.custoRepo
|
|
224
|
+
return conf
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Return conf stored in memory or persistent storage (need to
|
|
230
|
+
* be not async).
|
|
231
|
+
*/
|
|
232
|
+
public getLocalConfJSON () {
|
|
233
|
+
if (this.conf) return this.conf
|
|
234
|
+
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
|
|
240
|
+
return cfg
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
|
|
2
|
+
export default abstract class CustomizationAbstract {
|
|
3
|
+
|
|
4
|
+
abstract cfg: any
|
|
5
|
+
localDefaultConf: any
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Pre-requisite: the variable confLocale should store an object with
|
|
9
|
+
* at least the following infos:
|
|
10
|
+
* localDefaultConf.server.lang
|
|
11
|
+
* localDefaultConf.server.notes
|
|
12
|
+
* localDefaultConf.server.url_Css
|
|
13
|
+
*/
|
|
14
|
+
constructor (localDefaultConf) {
|
|
15
|
+
this.localDefaultConf = localDefaultConf
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// [High level] Get the individual configuration
|
|
19
|
+
///
|
|
20
|
+
|
|
21
|
+
public getCurrencyName () {
|
|
22
|
+
return this.getServerConfig('name')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public getContract1 () {
|
|
26
|
+
return this.getServerConfig('contract_1')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public getContract2 () {
|
|
30
|
+
return this.getServerConfig('contract_2')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public getContract3 () {
|
|
34
|
+
return this.getServerConfig('contract_3')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public getHelpUrl () {
|
|
38
|
+
return this.getServerConfig('url_help')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public getCondUrl () {
|
|
42
|
+
return this.getServerConfig('url_cond')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public getUnlockUrl () {
|
|
46
|
+
return this.getServerConfig('url_unlock')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public getHowToUrl () {
|
|
50
|
+
return this.getServerConfig('url_howto')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public getWalletAddress () {
|
|
54
|
+
return this.getServerConfig('address')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public getCreationMessage () {
|
|
58
|
+
return this.getServerConfig('creat_message')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public getLang () {
|
|
62
|
+
return this.getServerConfig('lang') || this.localDefaultConf.server?.lang
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public getNoteValues () {
|
|
66
|
+
return this.getServerConfig('notes') || this.localDefaultConf.server?.notes
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public hasBn () {
|
|
70
|
+
return !!this.getNoteValues()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public hasNant () {
|
|
74
|
+
return this.getServerConfigSwitch('nant', false)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public hasCM () {
|
|
78
|
+
return this.getServerConfigSwitch('CM', false)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public hasAutor () {
|
|
82
|
+
return this.getServerConfigSwitch('autor', false)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public hasDeleg () {
|
|
86
|
+
return this.getServerConfigSwitch('deleg', false)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public hasPayRequest () {
|
|
90
|
+
return this.getServerConfigSwitch('payReq', false)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public passwordAutocomplete () {
|
|
94
|
+
let number = 10000
|
|
95
|
+
try {
|
|
96
|
+
if (this.cfg.server.passwordAutocomplete &&
|
|
97
|
+
this.cfg.server.passwordAutocomplete > 0) {
|
|
98
|
+
number = this.cfg.server.passwordAutocomplete
|
|
99
|
+
}
|
|
100
|
+
} catch (e) {
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
return number
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public getCurrencies () {
|
|
107
|
+
return this.getServerConfig('currencies')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ///////////////////////////////////////////////////////////////////////////
|
|
111
|
+
|
|
112
|
+
public getServerConfig (configName) {
|
|
113
|
+
try {
|
|
114
|
+
return this.cfg.server[configName]
|
|
115
|
+
} catch (e) {
|
|
116
|
+
return ''
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public getServerConfigSwitch (configName, defaultValue) {
|
|
121
|
+
try {
|
|
122
|
+
return this.cfg.server[configName].toString().toLowerCase() === 'true'
|
|
123
|
+
} catch (e) {
|
|
124
|
+
return defaultValue
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ///////////////////////////////////////////////////////////////////////////
|
|
129
|
+
|
|
130
|
+
public getCurrencyAssetBaseUrl (currencyName?: string) {
|
|
131
|
+
if (!currencyName) {
|
|
132
|
+
currencyName = this.cfg.server.name
|
|
133
|
+
}
|
|
134
|
+
return `${this.cfg.custoRepo}${currencyName}`
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public getCssUrl (currencyName?: string) {
|
|
138
|
+
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`
|
|
141
|
+
} catch (e) {
|
|
142
|
+
return this.localDefaultConf.server.url_Css
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public getCurrencyLogoUrl (currencyName?: string) {
|
|
147
|
+
try {
|
|
148
|
+
// XXXvlab: I guess that 'lem' stands for leman here. Shouldn't that
|
|
149
|
+
// be agnostic ?
|
|
150
|
+
return `${this.getCurrencyAssetBaseUrl(currencyName)}/images/lem.png`
|
|
151
|
+
} catch (e) {
|
|
152
|
+
return ''
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
}
|