Skip to content

Commit b52bd59

Browse files
authored
Merge pull request #47 from AElfProject/dev
Dev
2 parents 8567235 + 0d15dae commit b52bd59

File tree

30 files changed

+7037
-8478
lines changed

30 files changed

+7037
-8478
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ test.js
99
test.data.js
1010
app/view/
1111
app/public/assets/output/
12-
.DS_Store
12+
.DS_Store
13+
.vscode/

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ at first
3737
### 1.Change config
3838
3939
```shell
40-
cp config/demo.config.default.js config/config.default.js
40+
cp config/demo.config.default.js config/config.default.js
4141
// set your own config.keys
4242

4343
cp config/demo.config.node.js config/config.node.js
@@ -98,4 +98,10 @@ sudo npm install --unsafe-perm=true --allow-root
9898
sh build.sh pro # or npm start
9999
```
100100
101+
### How to deal with int64
102+
103+
Use Long.js
104+
105+
https://www.npmjs.com/package/long
106+
101107
# Docker[TODO]

app/controller/address.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
* @file address.js
33
* @author huangzongzhe
44
*/
5+
/* eslint-disable fecs-camelcase */
56
'use strict';
67

78
const Controller = require('../core/baseController.js');
89
const {apiServerProvider} = require('../../config/config.node.js');
9-
const {getNodesInfo} = require('../utils/utils.js');
1010

1111
class addressController extends Controller {
1212
// the structure of return data is almost the same as the getTokens API of aelf-block-api.
@@ -27,27 +27,45 @@ class addressController extends Controller {
2727
required: false,
2828
allowEmpty: true,
2929
min: 0
30+
},
31+
contract_address: {
32+
type: 'string',
33+
required: false,
34+
allowEmpty: true,
35+
min: 0
3036
}
3137
};
3238

3339
try {
3440
let {
3541
address,
3642
limit,
37-
page
43+
page,
44+
contract_address
3845
} = ctx.request.query;
3946
let options = {
4047
address,
4148
limit: limit ? parseInt(limit, 0) : 0,
42-
page: page ? parseInt(page, 0) : 0
49+
page: page ? parseInt(page, 0) : 0,
50+
contract_address: contract_address || ''
4351
};
4452

4553
ctx.validate(keysRule, options);
4654

47-
const nodesInfo = (await ctx.curl(apiServerProvider
55+
let nodesInfo = (await ctx.curl(
56+
apiServerProvider
4857
+ `/api/address/tokens?address=${address}&nodes_info=1&limit=${limit}&page=${page}`, {
49-
dataType: 'json'
50-
})).data;
58+
dataType: 'json'
59+
}
60+
)).data;
61+
62+
if (contract_address) {
63+
nodesInfo = [nodesInfo.find(item => {
64+
if (item.contract_address === contract_address) {
65+
return true;
66+
}
67+
})];
68+
}
5169

5270
let result = [];
5371
if (nodesInfo.length) {

app/controller/proxy.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// 校验、组装参数。
1515
// 调用 Service 进行业务处理,必要时处理转换 Service 的返回结果,让它适应用户的需求。
1616
// 通过 HTTP 将结果响应给用户。
17+
/* eslint-disable fecs-camelcase */
1718
'use strict';
1819

1920
const Controller = require('../core/baseController.js');

app/router.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
module.exports = app => {
77
const {router, controller} = app;
88
router.get('/', controller.home.index);
9+
10+
router.get('/test', controller.test.test);
11+
912
router.get('/transactiondetail', controller.home.transactionDetail);
1013

1114
router.get('/wallet/api/proxy', controller.proxy.getProxy);

app/service/address.js

Lines changed: 90 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,116 @@
33
* @author huangzongzhe
44
* 2018.12
55
*/
6+
/* eslint-disable fecs-camelcase */
7+
68
const Service = require('../core/baseService');
7-
const {nodesHttpProviderSelect} = require('../utils/utils');
9+
const protoDecode = require('../utils/protoDecode');
10+
const Long = require('long');
11+
// const {nodesHttpProviderSelect} = require('../utils/utils');
812

9-
const GETBALANCETIMEOUT = 1000;
13+
// const GETBALANCETIMEOUT = 1000;
1014

1115
class ProxyService extends Service {
1216

17+
// use Long.js to deal with Balance.
1318
async getTokens(options, nodesInfo) {
1419
const getTokensBalance = () => new Promise((resolve, reject) => {
1520
const ctx = this.ctx;
1621

17-
let tokensInfo = {};
1822
let tokensInfoArray = [];
1923
const nodesInfoLength = nodesInfo.length;
2024
tokensInfoArray.length = nodesInfoLength;
2125
let nodesInfoCount = 0;
2226

23-
nodesInfo.map((item, index) => {
24-
const contract_address = item.contract_address;
25-
const url = nodesHttpProviderSelect(item.api_domain, item.api_ip)
26-
+ '/api/address/balance?'
27-
+ `address=${options.address}`
28-
+ `&contract_address=${contract_address}`;
29-
30-
let tokenInfo = {};
31-
32-
ctx.curl(url, {
33-
dataType: 'json',
34-
timeout: GETBALANCETIMEOUT
35-
}).then(resut => {
36-
tokenInfo = resut.data;
37-
tokenInfo.error = 0;
38-
39-
}).catch(error => {
40-
let message = error.message;
41-
// Don not expose IP.
42-
message = message.split(',')[0];
43-
tokenInfo.msg = message;
44-
tokenInfo.error = 1;
45-
46-
}).finally(() => {
47-
tokenInfo.token_name = item.token_name;
48-
tokenInfo.chain_id = item.chain_id;
49-
tokenInfo.symbol = item.symbol;
50-
tokenInfo.name = item.name;
51-
tokenInfo.address = options.address;
52-
tokenInfo.contract_address = contract_address;
53-
54-
tokenInfo.income = tokenInfo.income || 0;
55-
tokenInfo.expenditure = tokenInfo.expenditure || 0;
56-
tokenInfo.balance = tokenInfo.balance || 0;
57-
27+
const getBalance = (contractInstance, item, index) => {
28+
contractInstance.GetBalance.call({
29+
symbol: item.symbol,
30+
owner: options.address
31+
}, (err, result) => {
32+
let tokenInfo = {
33+
token_name: item.token_name,
34+
chain_id: item.chain_id,
35+
symbol: item.symbol,
36+
name: item.name,
37+
address: options.address,
38+
contract_address: item.contract_address,
39+
balance: {
40+
low: 0,
41+
high: 0,
42+
unsigned: true
43+
}
44+
};
45+
if (!err) {
46+
tokenInfo.balance = new Long(result.balance || '0');
47+
}
5848
tokensInfoArray[index] = tokenInfo;
5949
nodesInfoCount++;
6050

6151
if (nodesInfoCount === nodesInfoLength) {
6252
resolve(tokensInfoArray);
6353
}
6454
});
55+
};
56+
57+
nodesInfo.map((item, index) => {
58+
// 1.看插件是否初始化了实例,如果初始化了,使用。
59+
// 2.如果没有初始化,初始化实例,并使用。
60+
const aelfContractInstances = ctx.app.aelf.contractInstances;
61+
const {
62+
contract_address,
63+
chain_id
64+
} = item;
65+
if (aelfContractInstances[contract_address + chain_id]) {
66+
getBalance(aelfContractInstances[contract_address + chain_id], item, index);
67+
}
68+
else {
69+
ctx.app.aelf.initContractInstance(item).then(contractInstance => {
70+
getBalance(contractInstance, item, index);
71+
});
72+
}
73+
74+
// Backup 方案, 不走rpc,走 aelf-block-api
75+
// const contract_address = item.contract_address;
76+
// const url = nodesHttpProviderSelect(item.api_domain, item.api_ip)
77+
// + '/api/address/balance?'
78+
// + `address=${options.address}`
79+
// + `&contract_address=${contract_address}`;
80+
81+
// let tokenInfo = {};
82+
83+
// ctx.curl(url, {
84+
// dataType: 'json',
85+
// timeout: GETBALANCETIMEOUT
86+
// }).then(resut => {
87+
// tokenInfo = resut.data;
88+
// tokenInfo.error = 0;
89+
90+
// }).catch(error => {
91+
// let message = error.message;
92+
// // Don not expose IP.
93+
// message = message.split(',')[0];
94+
// tokenInfo.msg = message;
95+
// tokenInfo.error = 1;
96+
97+
// }).finally(() => {
98+
// tokenInfo.token_name = item.token_name;
99+
// tokenInfo.chain_id = item.chain_id;
100+
// tokenInfo.symbol = item.symbol;
101+
// tokenInfo.name = item.name;
102+
// tokenInfo.address = options.address;
103+
// tokenInfo.contract_address = contract_address;
104+
105+
// tokenInfo.income = tokenInfo.income || 0;
106+
// tokenInfo.expenditure = tokenInfo.expenditure || 0;
107+
// tokenInfo.balance = tokenInfo.balance || 0;
108+
109+
// tokensInfoArray[index] = tokenInfo;
110+
// nodesInfoCount++;
111+
112+
// if (nodesInfoCount === nodesInfoLength) {
113+
// resolve(tokensInfoArray);
114+
// }
115+
// });
65116
});
66117
});
67118

@@ -72,4 +123,4 @@ class ProxyService extends Service {
72123

73124
}
74125

75-
module.exports = ProxyService;
126+
module.exports = ProxyService;

app/utils/protoDecode.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @file protoDecode.js
3+
* @author huangzongzhe
4+
* useless now
5+
*/
6+
7+
const proto = require('aelf-sdk').pbjs;
8+
const stringToBuffer = require('./stringToBuffer');
9+
10+
function protoToInt64(protoValue) {
11+
const reader = new proto.Reader(stringToBuffer(protoValue));
12+
return reader.uint64();
13+
}
14+
15+
module.exports = {
16+
protoToInt64
17+
};

app/utils/stringToBuffer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @file stringToBuffer.js
3+
* @author huangzongzhe
4+
* useless now
5+
*/
6+
7+
module.exports = function (input) {
8+
let resultArray = [];
9+
if (typeof input !== 'string' || input.length % 2 !== 0) {
10+
throw Error('invalid input');
11+
}
12+
for (let i = 0, length = input.length; i < length; i += 2) {
13+
resultArray.push('0x' + input.slice(i, i + 2));
14+
}
15+
return Buffer.from(resultArray);
16+
};

app/web/js/langConfig/en-US.js

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* intl 英文词库
55
*/
66

7-
const en_US = {
7+
export default {
88
'aelf.': ' ',
99
'aelf.WalletDetail': 'WalletDetail',
1010
'aelf.TransactionList': 'Transaction List',
@@ -48,7 +48,7 @@ const en_US = {
4848
'aelf.Becareful08': 'Please write them down carefully and keep them in a secure location!',
4949
'aelf.Becareful09': 'Please DO NOT use screen capture!',
5050
'aelf.Becareful010': 'If anyone obtains your Mnemonic, they WILL obtain your digital assets!',
51-
'aelf.Confirm Mnemonic ': 'Confirm Mnemonic',
51+
'aelf.ConfirmMnemonic ': 'Confirm Mnemonic',
5252
'aelf.hint01': 'Mnemonic is not in the right sequence, please rearrange!',
5353
'aelf.hint02': 'To confirm your backup, please click on the Mnemonic in order.',
5454
'aelf.Copy Private Key': 'Copy Private Key',
@@ -67,8 +67,7 @@ const en_US = {
6767
'aelf.Old password': 'Old password',
6868
'aelf.Forget your password': 'Forget your password? Importing mnemonic or private key can be reset.',
6969
'aelf.Immediately import': 'Immediately import',
70-
'aelf.hint03': 'In this wallet, there is no Mnemonic when import Private Key. But we can get '
71-
+ 'Private Key when we import Mnemonic.',
70+
'aelf.hint03': 'In this wallet, there is no Mnemonic when import Private Key. But we can get Private Key when we import Mnemonic.',
7271
'aelf.Import': 'Import',
7372
'aelf.System Setting': 'System Setting',
7473
'aelf.Network': 'Network',
@@ -88,20 +87,10 @@ const en_US = {
8887
'aelf.HelpTitle04': 'What is the AElf Wallet?',
8988
'aelf.HelpTitle05': 'How to change the password?',
9089
'aelf.HelpTitle06': 'What if I forget my password?',
91-
'aelf.mnemonicCon01': 'The Mnemonics is equivalent to the bank card + '
92-
+ 'password of a traditional financial institution. '
93-
+ 'Please keep it in a safe place. A Mnemonics is another manifestation of a plaintext private'
94-
+ ' key that is designed to help users remember'
95-
+ ' complex private keys (64-bit hashes). Mnemonicss are generally composed of 12, 15, 18, and 21 words. These'
96-
+ ' words are taken from a fixed vocabulary. The order of generation '
97-
+ 'is also based on a certain algorithm. The Mnemonics is an unencrypted private '
98-
+ 'key. When people get your Mnemonics, you can take away your assets with little effort.',
90+
'aelf.mnemonicCon01': 'The Mnemonics is equivalent to the bank card + password of a traditional financial institution. Please keep it in a safe place. A Mnemonics is another manifestation of a plaintext private key that is designed to help users remember complex private keys (64-bit hashes). Mnemonicss are generally composed of 12, 15, 18, and 21 words. These words are taken from a fixed vocabulary. The order of generation is also based on a certain algorithm. The Mnemonics is an unencrypted private key. When people get your Mnemonics, you can take away your assets with little effort.',
9991
'aelf.mnemonicCon02': 'Therefore, users must pay attention to three points when backing up the Mnemonics:',
100-
'aelf.mnemonicCon03': '1. Use physical media as much as possible. For example, write Mnemonicss on paper. '
101-
+ 'Do not use screenshots or photos on networked devices as much as possible to prevent hackers from stealing.',
102-
'aelf.mnemonicCon04': '2. Verify that the backup Mnemonics is correct multiple times.'
103-
+ ' Once you have misread a letter or word, it will bring great suffering to the sub'
104-
+ 'sequent retrieval of the correct Mnemonics.',
92+
'aelf.mnemonicCon03': '1. Use physical media as much as possible. For example, write Mnemonicss on paper. Do not use screenshots or photos on networked devices as much as possible to prevent hackers from stealing.',
93+
'aelf.mnemonicCon04': '2. Verify that the backup Mnemonics is correct multiple times. Once you have misread a letter or word, it will bring great suffering to the subsequent retrieval of the correct Mnemonics.',
10594
'aelf.mnemonicCon05': '3. Keep the Mnemonics after the backup in a safe place, and do a good job of anti-theft and anti-lost measures.',
10695
'aefl.keystoreCon01': 'The Keystore file is a file format (JSON) for storing the private key. It uses user-defined password encryption to protect the wallet to a certain extent, and the degree of protection depends on the password strength of the wallet. If the password is similar to 123456, it is extremely unsafe.',
10796
'aefl.keystoreCon02': 'So users must pay attention to three points when backing up Keystore:',
@@ -149,5 +138,3 @@ const en_US = {
149138
'aelf.The passwords confirmed error.': 'The passwords confirmed error.',
150139
'aelf.The passwords is not strong.': 'The passwords is not strong.'
151140
};
152-
153-
export default en_US;

0 commit comments

Comments
 (0)