@multiplechain/bitcoin 0.1.1 → 0.1.2
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/package.json +45 -45
- package/src/adapters/unisat.js +35 -0
- package/src/entity/coin.js +105 -0
- package/src/entity/token.js +5 -0
- package/src/{transaction.js → entity/transaction.js} +15 -62
- package/src/get-adapter.js +11 -0
- package/src/provider.js +133 -32
- package/src/utils.js +21 -0
- package/src/wallet.js +185 -0
package/package.json
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"namespace": "multiplechain",
|
|
3
|
-
"name": "@multiplechain/bitcoin",
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"description": "Bitcoin JS provider",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"serve": "parcel test.html --no-cache --dist-dir test",
|
|
8
|
-
"build": "webpack"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"src"
|
|
12
|
-
],
|
|
13
|
-
"main": "src/provider.js",
|
|
14
|
-
"types": "index.d.ts",
|
|
15
|
-
"typings": "index.d.ts",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/MultipleChain/bitcoin.git"
|
|
19
|
-
},
|
|
20
|
-
"keywords": [
|
|
21
|
-
"Blockchain",
|
|
22
|
-
"Bitcoin",
|
|
23
|
-
"Cryptocurrency"
|
|
24
|
-
],
|
|
25
|
-
"author": "MultipleChain",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"bugs": {
|
|
28
|
-
"url": "https://github.com/MultipleChain/bitcoin/issues"
|
|
29
|
-
},
|
|
30
|
-
"homepage": "https://github.com/MultipleChain/bitcoin",
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@multiplechain/utils": "^0.1.1",
|
|
33
|
-
"bignumber.js": "^9.1.1",
|
|
34
|
-
"web3-utils": "^1.8.1"
|
|
35
|
-
},
|
|
36
|
-
"devDependencies": {
|
|
37
|
-
"assert": "^2.0.0",
|
|
38
|
-
"buffer": "^5.7.1",
|
|
39
|
-
"events": "^3.3.0",
|
|
40
|
-
"process": "^0.11.10",
|
|
41
|
-
"stream-browserify": "^3.0.0",
|
|
42
|
-
"webpack": "^5.76.0",
|
|
43
|
-
"webpack-cli": "^5.0.1"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"namespace": "multiplechain",
|
|
3
|
+
"name": "@multiplechain/bitcoin",
|
|
4
|
+
"version": "0.1.2",
|
|
5
|
+
"description": "Bitcoin JS provider",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"serve": "parcel test.html --no-cache --dist-dir test",
|
|
8
|
+
"build": "webpack"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"main": "src/bitcoin-provider.js",
|
|
14
|
+
"types": "index.d.ts",
|
|
15
|
+
"typings": "index.d.ts",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/MultipleChain/bitcoin.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"Blockchain",
|
|
22
|
+
"Bitcoin",
|
|
23
|
+
"Cryptocurrency"
|
|
24
|
+
],
|
|
25
|
+
"author": "MultipleChain",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/MultipleChain/bitcoin/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/MultipleChain/bitcoin",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@multiplechain/utils": "^0.1.1",
|
|
33
|
+
"bignumber.js": "^9.1.1",
|
|
34
|
+
"web3-utils": "^1.8.1"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"assert": "^2.0.0",
|
|
38
|
+
"buffer": "^5.7.1",
|
|
39
|
+
"events": "^3.3.0",
|
|
40
|
+
"process": "^0.11.10",
|
|
41
|
+
"stream-browserify": "^3.0.0",
|
|
42
|
+
"webpack": "^5.76.0",
|
|
43
|
+
"webpack-cli": "^5.0.1"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module.exports = unisat = (provider) => {
|
|
2
|
+
|
|
3
|
+
const wallet = window.unisat;
|
|
4
|
+
|
|
5
|
+
const connect = async () => {
|
|
6
|
+
return new Promise(async (resolve, reject) => {
|
|
7
|
+
try {
|
|
8
|
+
wallet.requestAccounts()
|
|
9
|
+
.then(async () => {
|
|
10
|
+
wallet.switchNetwork(provider.network)
|
|
11
|
+
.then(async () => {
|
|
12
|
+
resolve((await wallet.getAccounts())[0]);
|
|
13
|
+
})
|
|
14
|
+
.catch(error => {
|
|
15
|
+
reject(error);
|
|
16
|
+
});
|
|
17
|
+
})
|
|
18
|
+
.catch(error => {
|
|
19
|
+
reject(error);
|
|
20
|
+
});
|
|
21
|
+
} catch (error) {
|
|
22
|
+
reject(error);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
key: 'unisat',
|
|
29
|
+
name: 'UniSat',
|
|
30
|
+
type: 'browser',
|
|
31
|
+
wallet,
|
|
32
|
+
connect,
|
|
33
|
+
download: 'https://unisat.io/download'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const utils = require('../utils');
|
|
2
|
+
|
|
3
|
+
class Coin {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @var {String}
|
|
7
|
+
*/
|
|
8
|
+
symbol;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @var {String}
|
|
12
|
+
*/
|
|
13
|
+
decimals;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @var {Provider}
|
|
17
|
+
*/
|
|
18
|
+
provider;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Provider} provider
|
|
22
|
+
*/
|
|
23
|
+
constructor(provider) {
|
|
24
|
+
this.provider = provider;
|
|
25
|
+
this.decimals = 8;
|
|
26
|
+
this.symbol = 'BTC';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @returns {String}
|
|
31
|
+
*/
|
|
32
|
+
getSymbol() {
|
|
33
|
+
return this.symbol;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @returns {Integer}
|
|
38
|
+
*/
|
|
39
|
+
getDecimals() {
|
|
40
|
+
return this.decimals;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @returns {Object}
|
|
45
|
+
*/
|
|
46
|
+
async getBalance() {
|
|
47
|
+
let balance = await this.provider.connectedWallet.wallet.getBalance();
|
|
48
|
+
return {
|
|
49
|
+
confirmed: utils.toDec(balance.confirmed, this.getDecimals()),
|
|
50
|
+
unconfirmed: utils.toDec(balance.unconfirmed, this.getDecimals()),
|
|
51
|
+
total: utils.toDec(balance.total, this.getDecimals())
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @returns {Number}
|
|
57
|
+
*/
|
|
58
|
+
async getConfirmedBalance() {
|
|
59
|
+
let balance = await this.getBalance();
|
|
60
|
+
return balance.confirmed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @returns {Number}
|
|
65
|
+
*/
|
|
66
|
+
async getUnconfirmedBalance() {
|
|
67
|
+
let balance = await this.getBalance();
|
|
68
|
+
return balance.unconfirmed;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @returns {Number}
|
|
73
|
+
*/
|
|
74
|
+
async getTotalBalance() {
|
|
75
|
+
let balance = await this.getBalance();
|
|
76
|
+
return balance.total;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {String} from
|
|
82
|
+
* @param {String} to
|
|
83
|
+
* @param {Number} amount
|
|
84
|
+
* @returns {String|Object}
|
|
85
|
+
*/
|
|
86
|
+
transfer(from, to, amount) {
|
|
87
|
+
return new Promise(async (resolve, reject) => {
|
|
88
|
+
|
|
89
|
+
if (parseFloat(amount) > await this.getConfirmedBalance(from)) {
|
|
90
|
+
return reject('insufficient-balance');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
amount = utils.toSatoshi(amount);
|
|
94
|
+
this.provider.connectedWallet.wallet.sendBitcoin(to, amount)
|
|
95
|
+
.then((txid) => {
|
|
96
|
+
resolve(txid);
|
|
97
|
+
})
|
|
98
|
+
.catch((error) => {
|
|
99
|
+
reject(error);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = Coin;
|
|
@@ -20,7 +20,7 @@ class Transaction {
|
|
|
20
20
|
/**
|
|
21
21
|
* @var {Number}
|
|
22
22
|
*/
|
|
23
|
-
timer;
|
|
23
|
+
timer = 30;
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* @param {String} hash
|
|
@@ -49,15 +49,7 @@ class Transaction {
|
|
|
49
49
|
*/
|
|
50
50
|
async getData() {
|
|
51
51
|
try {
|
|
52
|
-
|
|
53
|
-
let txApi;
|
|
54
|
-
|
|
55
|
-
if (this.provider.testnet) {
|
|
56
|
-
txApi = this.provider.api + 'tx/' + this.hash;
|
|
57
|
-
} else {
|
|
58
|
-
txApi = this.provider.api + 'rawtx/' + this.hash;
|
|
59
|
-
}
|
|
60
|
-
|
|
52
|
+
let txApi = this.provider.api + 'tx/' + this.hash;
|
|
61
53
|
this.data = await fetch(txApi).then(res => res.json());
|
|
62
54
|
} catch (error) {
|
|
63
55
|
throw new Error('There was a problem retrieving transaction data!');
|
|
@@ -72,13 +64,7 @@ class Transaction {
|
|
|
72
64
|
async getConfirmations() {
|
|
73
65
|
try {
|
|
74
66
|
|
|
75
|
-
let blockApi;
|
|
76
|
-
if (this.provider.testnet) {
|
|
77
|
-
blockApi = this.provider.api + 'blocks/tip/height';
|
|
78
|
-
} else {
|
|
79
|
-
blockApi = this.provider.api + 'latestblock';
|
|
80
|
-
}
|
|
81
|
-
|
|
67
|
+
let blockApi = this.provider.api + 'blocks/tip/height';
|
|
82
68
|
if (!this.data) await this.getData();
|
|
83
69
|
let latestBlock = await fetch(blockApi).then(res => res.json());
|
|
84
70
|
|
|
@@ -86,14 +72,7 @@ class Transaction {
|
|
|
86
72
|
latestBlock = latestBlock.height;
|
|
87
73
|
}
|
|
88
74
|
|
|
89
|
-
|
|
90
|
-
if (this.provider.testnet) {
|
|
91
|
-
blockHeight = this.data.status.block_height;
|
|
92
|
-
} else {
|
|
93
|
-
blockHeight = this.data.block_height;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return ((latestBlock - blockHeight) + 1);
|
|
75
|
+
return ((latestBlock - (this.data.status.block_height || 0)) + 1);
|
|
97
76
|
} catch (error) {}
|
|
98
77
|
}
|
|
99
78
|
|
|
@@ -133,14 +112,8 @@ class Transaction {
|
|
|
133
112
|
if (this.data == null) {
|
|
134
113
|
result = false;
|
|
135
114
|
} else {
|
|
136
|
-
if (this.
|
|
137
|
-
|
|
138
|
-
result = true;
|
|
139
|
-
}
|
|
140
|
-
} else {
|
|
141
|
-
if (this.data.block_height) {
|
|
142
|
-
result = true;
|
|
143
|
-
}
|
|
115
|
+
if (this.data.status.block_height) {
|
|
116
|
+
result = true;
|
|
144
117
|
}
|
|
145
118
|
}
|
|
146
119
|
|
|
@@ -173,31 +146,15 @@ class Transaction {
|
|
|
173
146
|
|
|
174
147
|
if (await this.validateTransaction()) {
|
|
175
148
|
|
|
176
|
-
let data
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
let index = this.data.vout.findIndex(object => {
|
|
180
|
-
return object.scriptpubkey_address == config.receiver;
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
data = this.data.vout[index];
|
|
184
|
-
|
|
185
|
-
data = {
|
|
186
|
-
receiver: data.scriptpubkey_address,
|
|
187
|
-
amount: utils.toDec(data.value, 8)
|
|
188
|
-
};
|
|
189
|
-
} else {
|
|
190
|
-
|
|
191
|
-
let index = this.data.out.findIndex(object => {
|
|
192
|
-
return object.addr == config.receiver;
|
|
193
|
-
});
|
|
149
|
+
let index = this.data.vout.findIndex(object => {
|
|
150
|
+
return object.scriptpubkey_address == config.receiver;
|
|
151
|
+
});
|
|
194
152
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
};
|
|
153
|
+
let data = this.data.vout[index];
|
|
154
|
+
|
|
155
|
+
data = {
|
|
156
|
+
receiver: data.scriptpubkey_address,
|
|
157
|
+
amount: utils.toDec(data.value, 8)
|
|
201
158
|
}
|
|
202
159
|
|
|
203
160
|
if (data.receiver == config.receiver && data.amount == config.amount) {
|
|
@@ -214,11 +171,7 @@ class Transaction {
|
|
|
214
171
|
* @returns {String}
|
|
215
172
|
*/
|
|
216
173
|
getUrl() {
|
|
217
|
-
|
|
218
|
-
return this.provider.explorer + 'tx/' + this.hash;
|
|
219
|
-
} else {
|
|
220
|
-
return this.provider.explorer + 'transactions/btc/' + this.hash;
|
|
221
|
-
}
|
|
174
|
+
return this.provider.explorer + 'tx/' + this.hash;
|
|
222
175
|
}
|
|
223
176
|
}
|
|
224
177
|
|
package/src/provider.js
CHANGED
|
@@ -1,40 +1,101 @@
|
|
|
1
|
-
const Transaction = require("./transaction");
|
|
2
1
|
const utils = require("@multiplechain/utils");
|
|
2
|
+
const Coin = require("./entity/coin");
|
|
3
|
+
const Token = require("./entity/token");
|
|
4
|
+
const Transaction = require("./entity/transaction");
|
|
3
5
|
|
|
4
6
|
class Provider {
|
|
5
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @var {String}
|
|
10
|
+
*/
|
|
6
11
|
api;
|
|
7
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @var {String}
|
|
15
|
+
*/
|
|
8
16
|
explorer;
|
|
9
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @var {Boolean}
|
|
20
|
+
*/
|
|
10
21
|
testnet;
|
|
11
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @var {String}
|
|
25
|
+
*/
|
|
26
|
+
network;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @var {Object}
|
|
30
|
+
*/
|
|
31
|
+
detectedWallets = [];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @var {Object}
|
|
35
|
+
*/
|
|
36
|
+
connectedWallet;
|
|
37
|
+
|
|
12
38
|
constructor(testnet = false) {
|
|
13
39
|
this.testnet = testnet;
|
|
40
|
+
this.network = testnet ? 'testnet' : 'livenet';
|
|
14
41
|
|
|
15
42
|
if (!this.testnet) {
|
|
16
|
-
this.api = "https://
|
|
17
|
-
this.explorer = "https://
|
|
43
|
+
this.api = "https://blockstream.info/api/";
|
|
44
|
+
this.explorer = "https://blockstream.info/";
|
|
18
45
|
} else {
|
|
19
46
|
this.api = "https://blockstream.info/testnet/api/";
|
|
20
47
|
this.explorer = "https://blockstream.info/testnet/";
|
|
21
48
|
}
|
|
49
|
+
|
|
50
|
+
this.detectWallets();
|
|
22
51
|
}
|
|
23
52
|
|
|
24
53
|
getWalletOpenLink(address, amount) {
|
|
25
54
|
return 'bitcoin' + ':' + String(address).toUpperCase() + '?amount=' + amount;
|
|
26
55
|
}
|
|
27
56
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
57
|
+
errorCheck(data) {
|
|
58
|
+
if (typeof data == 'string') {
|
|
59
|
+
if (data == 'Address on invalid network') {
|
|
60
|
+
return {
|
|
61
|
+
error: 'invalid-address'
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
return {
|
|
65
|
+
error: 'any-error'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} else if (data.error) {
|
|
69
|
+
if (data.error == 'not-found-or-invalid-arg') {
|
|
70
|
+
return {
|
|
71
|
+
error: 'invalid-address'
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
return {
|
|
75
|
+
error: 'any-error'
|
|
76
|
+
}
|
|
77
|
+
}
|
|
35
78
|
}
|
|
36
79
|
|
|
37
|
-
|
|
80
|
+
return data;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @param {String} receiver
|
|
85
|
+
* @returns
|
|
86
|
+
*/
|
|
87
|
+
async getLastTransactionByReceiver(receiver) {
|
|
88
|
+
|
|
89
|
+
let apiUrl = this.api + 'address/' + receiver + '/txs';
|
|
90
|
+
let data = await fetch(apiUrl).then(response => response.text());
|
|
91
|
+
try {
|
|
92
|
+
data = JSON.parse(data);
|
|
93
|
+
} catch (error) {}
|
|
94
|
+
|
|
95
|
+
data = this.errorCheck(data);
|
|
96
|
+
if (data.error) {
|
|
97
|
+
return data;
|
|
98
|
+
}
|
|
38
99
|
|
|
39
100
|
if (data.length == 0) {
|
|
40
101
|
return {
|
|
@@ -42,38 +103,78 @@ class Provider {
|
|
|
42
103
|
amount: 0
|
|
43
104
|
}
|
|
44
105
|
}
|
|
106
|
+
|
|
107
|
+
let tx = data[0];
|
|
45
108
|
|
|
46
|
-
|
|
109
|
+
let index = tx.vout.findIndex(object => {
|
|
110
|
+
return object.scriptpubkey_address == receiver;
|
|
111
|
+
});
|
|
47
112
|
|
|
48
|
-
|
|
113
|
+
data = tx.vout[index];
|
|
49
114
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
115
|
+
return {
|
|
116
|
+
hash: tx.txid,
|
|
117
|
+
amount: utils.toDec(data.value, 8)
|
|
118
|
+
};
|
|
119
|
+
}
|
|
53
120
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @param {Wallet} wallet
|
|
123
|
+
*/
|
|
124
|
+
setConnectedWallet(wallet) {
|
|
125
|
+
this.connectedWallet = wallet;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {String} adapter
|
|
130
|
+
* @returns {Promise}
|
|
131
|
+
*/
|
|
132
|
+
connectWallet(adapter) {
|
|
133
|
+
return new Promise(async (resolve, reject) => {
|
|
134
|
+
if (this.detectedWallets[adapter]) {
|
|
135
|
+
let wallet = this.detectedWallets[adapter];
|
|
136
|
+
wallet.connect()
|
|
137
|
+
.then(() => {
|
|
138
|
+
resolve(wallet);
|
|
139
|
+
})
|
|
140
|
+
.catch(error => {
|
|
141
|
+
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
reject('wallet-not-found');
|
|
59
145
|
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
let tx = data[0];
|
|
146
|
+
});
|
|
147
|
+
}
|
|
63
148
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
149
|
+
/**
|
|
150
|
+
* @param {Array} filter
|
|
151
|
+
* @returns {Array}
|
|
152
|
+
*/
|
|
153
|
+
getDetectedWallets(filter) {
|
|
154
|
+
if (!filter) return this.detectedWallets;
|
|
155
|
+
return Object.fromEntries(Object.entries(this.detectedWallets).filter(([key]) => {
|
|
156
|
+
return filter.includes(key);
|
|
157
|
+
}));
|
|
158
|
+
}
|
|
67
159
|
|
|
68
|
-
|
|
160
|
+
detectWallets() {
|
|
161
|
+
if (typeof window != 'undefined') {
|
|
162
|
+
const Wallet = require('./wallet');
|
|
69
163
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
164
|
+
if (typeof window.unisat !== 'undefined') {
|
|
165
|
+
this.detectedWallets['unisat'] = new Wallet('unisat', this);
|
|
166
|
+
}
|
|
74
167
|
}
|
|
75
168
|
}
|
|
76
169
|
|
|
170
|
+
Coin() {
|
|
171
|
+
return new Coin(this);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
Token(address) {
|
|
175
|
+
return new Token(address, this);
|
|
176
|
+
}
|
|
177
|
+
|
|
77
178
|
Transaction(hash) {
|
|
78
179
|
return new Transaction(hash, this);
|
|
79
180
|
}
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const BigNumber = require('bignumber.js');
|
|
2
|
+
const utils = require('@multiplechain/utils');
|
|
3
|
+
|
|
4
|
+
module.exports = Object.assign(utils, {
|
|
5
|
+
toSatoshi(amount) {
|
|
6
|
+
let decimals = 8;
|
|
7
|
+
let length = '1' + '0'.repeat(decimals);
|
|
8
|
+
let value = new BigNumber(amount.toString(10), 10).times(length);
|
|
9
|
+
return parseInt(value.toString(10));
|
|
10
|
+
},
|
|
11
|
+
rejectMessage(error, reject) {
|
|
12
|
+
|
|
13
|
+
if (typeof error == 'object') {
|
|
14
|
+
if (error.code == 4001 || error.message == 'User rejected the request.') {
|
|
15
|
+
return reject('request-rejected');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return reject(error);
|
|
20
|
+
}
|
|
21
|
+
})
|
package/src/wallet.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
const getAdapter = require('./get-adapter');
|
|
2
|
+
const utils = require('./utils');
|
|
3
|
+
|
|
4
|
+
class Wallet {
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @var {Object}
|
|
8
|
+
*/
|
|
9
|
+
adapter;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @var {Object}
|
|
13
|
+
*/
|
|
14
|
+
wallet;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @var {Object}
|
|
18
|
+
*/
|
|
19
|
+
provider;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @var {String}
|
|
23
|
+
*/
|
|
24
|
+
connectedAccount;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {String} adapter
|
|
28
|
+
* @param {Object} provider
|
|
29
|
+
*/
|
|
30
|
+
constructor(adapter, provider) {
|
|
31
|
+
this.provider = provider;
|
|
32
|
+
this.setAdapter(adapter);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {String} adapter
|
|
37
|
+
*/
|
|
38
|
+
setAdapter(adapter) {
|
|
39
|
+
this.adapter = getAdapter(adapter, this.provider);
|
|
40
|
+
this.wallet = this.adapter.wallet;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @returns {String}
|
|
45
|
+
*/
|
|
46
|
+
getKey() {
|
|
47
|
+
return this.adapter.key;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @returns {String}
|
|
52
|
+
*/
|
|
53
|
+
getName() {
|
|
54
|
+
return this.adapter.name;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @returns {String}
|
|
59
|
+
*/
|
|
60
|
+
getType() {
|
|
61
|
+
return this.adapter.type;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @returns {String}
|
|
66
|
+
*/
|
|
67
|
+
getDeepLink() {
|
|
68
|
+
return this.adapter.deepLink;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @returns {String}
|
|
73
|
+
*/
|
|
74
|
+
getDownloadLink() {
|
|
75
|
+
return this.adapter.download;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @returns {String}
|
|
80
|
+
*/
|
|
81
|
+
connect() {
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
let time = 0;
|
|
84
|
+
let timeout = 15;
|
|
85
|
+
let timer = setInterval(async () => {
|
|
86
|
+
time += 1;
|
|
87
|
+
if (time > timeout) {
|
|
88
|
+
clearInterval(timer);
|
|
89
|
+
reject('timeout');
|
|
90
|
+
}
|
|
91
|
+
}, 1000);
|
|
92
|
+
|
|
93
|
+
this.adapter.connect()
|
|
94
|
+
.then(async (connectedAccount) => {
|
|
95
|
+
let network = await this.wallet.getNetwork();
|
|
96
|
+
if (this.provider.network == network) {
|
|
97
|
+
this.provider.setConnectedWallet(this);
|
|
98
|
+
resolve(this.connectedAccount = connectedAccount);
|
|
99
|
+
} else {
|
|
100
|
+
reject('not-accepted-chain');
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
.catch((error) => {
|
|
104
|
+
utils.rejectMessage(error, reject);
|
|
105
|
+
})
|
|
106
|
+
.finally(() => {
|
|
107
|
+
clearInterval(timer);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @returns {Array}
|
|
114
|
+
*/
|
|
115
|
+
getAccounts() {
|
|
116
|
+
return this.wallet.getAccounts();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @returns {String}
|
|
121
|
+
*/
|
|
122
|
+
getPublicKey() {
|
|
123
|
+
return this.wallet.getPublicKey();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {String} to
|
|
129
|
+
* @param {Integer} amount
|
|
130
|
+
* @return {Transaction|Object}
|
|
131
|
+
* @throws {Error}
|
|
132
|
+
*/
|
|
133
|
+
coinTransfer(to, amount) {
|
|
134
|
+
return new Promise(async (resolve, reject) => {
|
|
135
|
+
try {
|
|
136
|
+
let coin = this.provider.Coin();
|
|
137
|
+
|
|
138
|
+
coin.transfer(this.connectedAccount, to, amount)
|
|
139
|
+
.then((transactionId) => {
|
|
140
|
+
resolve(this.provider.Transaction(transactionId));
|
|
141
|
+
})
|
|
142
|
+
.catch((error) => {
|
|
143
|
+
utils.rejectMessage(error, reject);
|
|
144
|
+
});
|
|
145
|
+
} catch (error) {
|
|
146
|
+
utils.rejectMessage(error, reject);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// TODO: implement
|
|
152
|
+
tokenTransfer(to, amount, tokenAddress) {
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {String} to
|
|
157
|
+
* @param {Integer} amount
|
|
158
|
+
* @param {String|null} tokenAddress
|
|
159
|
+
* @return {Transaction|Object}
|
|
160
|
+
* @throws {Error}
|
|
161
|
+
*/
|
|
162
|
+
transfer(to, amount, tokenAddress = null) {
|
|
163
|
+
if (tokenAddress) {
|
|
164
|
+
return this.tokenTransfer(to, amount, tokenAddress);
|
|
165
|
+
} else {
|
|
166
|
+
return this.coinTransfer(to, amount);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Events
|
|
171
|
+
accountsChanged(callback) {
|
|
172
|
+
this.wallet.on('accountsChanged', (accounts) => {
|
|
173
|
+
callback(accounts);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
networkChanged(callback) {
|
|
178
|
+
this.wallet.on('networkChanged', (network) => {
|
|
179
|
+
callback(network);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
module.exports = Wallet;
|