@airgap/bitcoin 0.13.45-beta.3 → 0.13.45-beta.5
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 +5 -5
- package/v0/index.js +10 -10
- package/v0/index.js.map +1 -1
- package/v0/protocol/BitcoinAddress.js +9 -8
- package/v0/protocol/BitcoinAddress.js.map +1 -1
- package/v0/protocol/BitcoinCryptoClient.js +85 -16
- package/v0/protocol/BitcoinCryptoClient.js.map +1 -1
- package/v0/protocol/BitcoinProtocol.js +987 -590
- package/v0/protocol/BitcoinProtocol.js.map +1 -1
- package/v0/protocol/BitcoinProtocolOptions.js +111 -45
- package/v0/protocol/BitcoinProtocolOptions.js.map +1 -1
- package/v0/protocol/BitcoinSegwitAddress.js +29 -12
- package/v0/protocol/BitcoinSegwitAddress.js.map +1 -1
- package/v0/protocol/BitcoinSegwitProtocol.js +483 -348
- package/v0/protocol/BitcoinSegwitProtocol.js.map +1 -1
- package/v0/protocol/BitcoinTestnetProtocol.js +36 -28
- package/v0/protocol/BitcoinTestnetProtocol.js.map +1 -1
- package/v0/serializer/validators/transaction-validator.js +30 -22
- package/v0/serializer/validators/transaction-validator.js.map +1 -1
- package/v0/serializer/validators/validators.js +23 -23
- package/v0/serializer/validators/validators.js.map +1 -1
- package/v1/block-explorer/BlockCypherBlockExplorer.js +61 -12
- package/v1/block-explorer/BlockCypherBlockExplorer.js.map +1 -1
- package/v1/data/BitcoinAddress.js +10 -9
- package/v1/data/BitcoinAddress.js.map +1 -1
- package/v1/data/BitcoinLegacyAddress.js +12 -11
- package/v1/data/BitcoinLegacyAddress.js.map +1 -1
- package/v1/data/BitcoinSegwitAddress.js +12 -11
- package/v1/data/BitcoinSegwitAddress.js.map +1 -1
- package/v1/data/BitcoinTaprootAddress.js +22 -31
- package/v1/data/BitcoinTaprootAddress.js.map +1 -1
- package/v1/index.js +11 -11
- package/v1/index.js.map +1 -1
- package/v1/module/BitcoinModule.d.ts +1 -1
- package/v1/module/BitcoinModule.js +102 -44
- package/v1/module/BitcoinModule.js.map +1 -1
- package/v1/module.js +3 -2
- package/v1/module.js.map +1 -1
- package/v1/protocol/BitcoinCryptoClient.js +90 -22
- package/v1/protocol/BitcoinCryptoClient.js.map +1 -1
- package/v1/protocol/BitcoinLegacyProtocol.js +796 -520
- package/v1/protocol/BitcoinLegacyProtocol.js.map +1 -1
- package/v1/protocol/BitcoinProtocol.js +1169 -735
- package/v1/protocol/BitcoinProtocol.js.map +1 -1
- package/v1/protocol/BitcoinSegwitProtocol.js +796 -542
- package/v1/protocol/BitcoinSegwitProtocol.js.map +1 -1
- package/v1/protocol/BitcoinTaprootProtocol.js +1000 -688
- package/v1/protocol/BitcoinTaprootProtocol.js.map +1 -1
- package/v1/protocol/BitcoinTestnetProtocol.js +33 -14
- package/v1/protocol/BitcoinTestnetProtocol.js.map +1 -1
- package/v1/serializer/v3/schemas/converter/transaction-converter.js +52 -29
- package/v1/serializer/v3/schemas/converter/transaction-converter.js.map +1 -1
- package/v1/serializer/v3/serializer-companion.js +165 -98
- package/v1/serializer/v3/serializer-companion.js.map +1 -1
- package/v1/serializer/v3/validators/transaction-validator.js +16 -13
- package/v1/serializer/v3/validators/transaction-validator.js.map +1 -1
- package/v1/serializer/v3/validators/validators.js +213 -122
- package/v1/serializer/v3/validators/validators.js.map +1 -1
- package/v1/types/crypto.d.ts +1 -1
- package/v1/types/key.d.ts +6 -6
- package/v1/types/protocol.d.ts +2 -2
- package/v1/types/transaction.d.ts +3 -3
- package/v1/utils/common.js +6 -4
- package/v1/utils/common.js.map +1 -1
- package/v1/utils/key.d.ts +6 -5
- package/v1/utils/key.js +39 -38
- package/v1/utils/key.js.map +1 -1
- package/v1/utils/network.js +4 -3
- package/v1/utils/network.js.map +1 -1
- package/v1/utils/protocol.js +19 -25
- package/v1/utils/protocol.js.map +1 -1
- package/v1/utils/signature.js +5 -4
- package/v1/utils/signature.js.map +1 -1
|
@@ -15,41 +15,77 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
return function (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (_) try {
|
|
41
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
62
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
63
|
+
if (ar || !(i in from)) {
|
|
64
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
65
|
+
ar[i] = from[i];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
69
|
+
};
|
|
35
70
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
71
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
72
|
};
|
|
38
73
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
74
|
exports.BitcoinProtocol = void 0;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
75
|
+
var index_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/axios-0.19.0/index"));
|
|
76
|
+
var bignumber_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/bignumber.js-9.0.0/bignumber"));
|
|
77
|
+
var index_2 = require("@airgap/coinlib-core/dependencies/src/bip39-2.5.0/index");
|
|
78
|
+
var bitcoinJSMessage = __importStar(require("@airgap/coinlib-core/dependencies/src/bitcoinjs-message-2.1.1/index"));
|
|
79
|
+
var errors_1 = require("@airgap/coinlib-core/errors");
|
|
80
|
+
var coinlib_error_1 = require("@airgap/coinlib-core/errors/coinlib-error");
|
|
81
|
+
var ProtocolSymbols_1 = require("@airgap/coinlib-core/utils/ProtocolSymbols");
|
|
82
|
+
var BitcoinAddress_1 = require("./BitcoinAddress");
|
|
83
|
+
var BitcoinCryptoClient_1 = require("./BitcoinCryptoClient");
|
|
84
|
+
var BitcoinProtocolOptions_1 = require("./BitcoinProtocolOptions");
|
|
85
|
+
var DUST_AMOUNT = 50;
|
|
86
|
+
var BitcoinProtocol = /** @class */ (function () {
|
|
87
|
+
function BitcoinProtocol(options) {
|
|
88
|
+
if (options === void 0) { options = new BitcoinProtocolOptions_1.BitcoinProtocolOptions(); }
|
|
53
89
|
this.options = options;
|
|
54
90
|
this.symbol = 'BTC';
|
|
55
91
|
this.name = 'Bitcoin (Legacy)';
|
|
@@ -78,596 +114,957 @@ class BitcoinProtocol {
|
|
|
78
114
|
}
|
|
79
115
|
];
|
|
80
116
|
this.supportsHD = true;
|
|
81
|
-
this.standardDerivationPath =
|
|
117
|
+
this.standardDerivationPath = "m/44'/0'/0'";
|
|
82
118
|
this.addressIsCaseSensitive = true;
|
|
83
119
|
this.addressValidationPattern = '^(?:[13]{1}[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[a-z0-9]{39,59})$';
|
|
84
120
|
this.addressPlaceholder = '1ABC...';
|
|
85
121
|
this.cryptoClient = new BitcoinCryptoClient_1.BitcoinCryptoClient(this, bitcoinJSMessage);
|
|
86
122
|
}
|
|
87
|
-
|
|
88
|
-
return this
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return this
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return this
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return this
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
123
|
+
BitcoinProtocol.prototype.getSymbol = function () {
|
|
124
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
125
|
+
return __generator(this, function (_a) {
|
|
126
|
+
return [2 /*return*/, this.symbol];
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
BitcoinProtocol.prototype.getName = function () {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
132
|
+
return __generator(this, function (_a) {
|
|
133
|
+
return [2 /*return*/, this.name];
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
BitcoinProtocol.prototype.getMarketSymbol = function () {
|
|
138
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
139
|
+
return __generator(this, function (_a) {
|
|
140
|
+
return [2 /*return*/, this.marketSymbol];
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
BitcoinProtocol.prototype.getAssetSymbol = function () {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
146
|
+
return __generator(this, function (_a) {
|
|
147
|
+
return [2 /*return*/, undefined];
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
BitcoinProtocol.prototype.getFeeSymbol = function () {
|
|
152
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
153
|
+
return __generator(this, function (_a) {
|
|
154
|
+
return [2 /*return*/, this.feeSymbol];
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
BitcoinProtocol.prototype.getFeeDefaults = function () {
|
|
159
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
160
|
+
return __generator(this, function (_a) {
|
|
161
|
+
return [2 /*return*/, this.feeDefaults];
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
BitcoinProtocol.prototype.getDecimals = function () {
|
|
166
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
167
|
+
return __generator(this, function (_a) {
|
|
168
|
+
return [2 /*return*/, this.decimals];
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
BitcoinProtocol.prototype.getFeeDecimals = function () {
|
|
173
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
174
|
+
return __generator(this, function (_a) {
|
|
175
|
+
return [2 /*return*/, this.feeDecimals];
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
BitcoinProtocol.prototype.getIdentifier = function () {
|
|
180
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
181
|
+
return __generator(this, function (_a) {
|
|
182
|
+
return [2 /*return*/, this.identifier];
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
BitcoinProtocol.prototype.getUnits = function () {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
188
|
+
return __generator(this, function (_a) {
|
|
189
|
+
return [2 /*return*/, this.units];
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
BitcoinProtocol.prototype.getSupportsHD = function () {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
195
|
+
return __generator(this, function (_a) {
|
|
196
|
+
return [2 /*return*/, this.supportsHD];
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
BitcoinProtocol.prototype.getStandardDerivationPath = function () {
|
|
201
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
202
|
+
return __generator(this, function (_a) {
|
|
203
|
+
return [2 /*return*/, this.standardDerivationPath];
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
BitcoinProtocol.prototype.getAddressIsCaseSensitive = function () {
|
|
208
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
209
|
+
return __generator(this, function (_a) {
|
|
210
|
+
return [2 /*return*/, this.addressIsCaseSensitive];
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
BitcoinProtocol.prototype.getAddressValidationPattern = function () {
|
|
215
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
216
|
+
return __generator(this, function (_a) {
|
|
217
|
+
return [2 /*return*/, this.addressValidationPattern];
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
BitcoinProtocol.prototype.getAddressPlaceholder = function () {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
223
|
+
return __generator(this, function (_a) {
|
|
224
|
+
return [2 /*return*/, this.addressPlaceholder];
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
BitcoinProtocol.prototype.getOptions = function () {
|
|
229
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
230
|
+
return __generator(this, function (_a) {
|
|
231
|
+
return [2 /*return*/, this.options];
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
BitcoinProtocol.prototype.getBlockExplorerLinkForAddress = function (address) {
|
|
236
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
237
|
+
return __generator(this, function (_a) {
|
|
238
|
+
return [2 /*return*/, this.options.network.blockExplorer.getAddressLink(address)];
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
};
|
|
242
|
+
BitcoinProtocol.prototype.getBlockExplorerLinkForTxId = function (txId) {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
244
|
+
return __generator(this, function (_a) {
|
|
245
|
+
return [2 /*return*/, this.options.network.blockExplorer.getTransactionLink(txId)];
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
};
|
|
249
|
+
BitcoinProtocol.prototype.getPublicKeyFromMnemonic = function (mnemonic, derivationPath, password) {
|
|
250
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
251
|
+
var secret;
|
|
252
|
+
return __generator(this, function (_a) {
|
|
253
|
+
secret = (0, index_2.mnemonicToSeed)(mnemonic, password);
|
|
254
|
+
return [2 /*return*/, this.getPublicKeyFromHexSecret(secret, derivationPath)];
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
BitcoinProtocol.prototype.getPrivateKeyFromMnemonic = function (mnemonic, derivationPath, password) {
|
|
259
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
260
|
+
var secret;
|
|
261
|
+
return __generator(this, function (_a) {
|
|
262
|
+
secret = (0, index_2.mnemonicToSeed)(mnemonic, password);
|
|
263
|
+
return [2 /*return*/, this.getPrivateKeyFromHexSecret(secret, derivationPath)];
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
BitcoinProtocol.prototype.getExtendedPublicKeyFromMnemonic = function (mnemonic, derivationPath, password) {
|
|
268
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
269
|
+
var secret;
|
|
270
|
+
return __generator(this, function (_a) {
|
|
271
|
+
secret = (0, index_2.mnemonicToSeed)(mnemonic, password);
|
|
272
|
+
return [2 /*return*/, this.getExtendedPublicKeyFromHexSecret(secret, derivationPath)];
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
BitcoinProtocol.prototype.getExtendedPrivateKeyFromMnemonic = function (mnemonic, derivationPath, password) {
|
|
277
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
278
|
+
var secret;
|
|
279
|
+
return __generator(this, function (_a) {
|
|
280
|
+
secret = (0, index_2.mnemonicToSeed)(mnemonic, password);
|
|
281
|
+
return [2 /*return*/, this.getExtendedPrivateKeyFromHexSecret(secret, derivationPath)];
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
BitcoinProtocol.prototype.getPublicKeyFromHexSecret = function (secret, derivationPath) {
|
|
286
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
287
|
+
var bitcoinNode;
|
|
288
|
+
return __generator(this, function (_a) {
|
|
289
|
+
bitcoinNode = this.options.config.bitcoinJSLib.HDNode.fromSeedHex(secret, this.options.network.extras.network);
|
|
290
|
+
return [2 /*return*/, bitcoinNode.derivePath(derivationPath).neutered().toBase58()];
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
BitcoinProtocol.prototype.getPrivateKeyFromHexSecret = function (secret, derivationPath) {
|
|
295
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
296
|
+
var bitcoinNode;
|
|
297
|
+
return __generator(this, function (_a) {
|
|
298
|
+
bitcoinNode = this.options.config.bitcoinJSLib.HDNode.fromSeedHex(secret, this.options.network.extras.network);
|
|
299
|
+
return [2 /*return*/, bitcoinNode.derivePath(derivationPath).keyPair.d.toBuffer(32).toString('hex')];
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
BitcoinProtocol.prototype.getExtendedPublicKeyFromHexSecret = function (secret, derivationPath) {
|
|
304
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
305
|
+
return __generator(this, function (_a) {
|
|
306
|
+
return [2 /*return*/, this.getPublicKeyFromHexSecret(secret, derivationPath)];
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
};
|
|
310
|
+
BitcoinProtocol.prototype.getExtendedPrivateKeyFromHexSecret = function (secret, derivationPath) {
|
|
311
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
312
|
+
var bitcoinNode;
|
|
313
|
+
return __generator(this, function (_a) {
|
|
314
|
+
bitcoinNode = this.options.config.bitcoinJSLib.HDNode.fromSeedHex(secret, this.options.network.extras.network);
|
|
315
|
+
return [2 /*return*/, bitcoinNode.derivePath(derivationPath).toBase58()];
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
};
|
|
319
|
+
BitcoinProtocol.prototype.getAddressFromPublicKey = function (publicKey, cursor) {
|
|
320
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
321
|
+
var node, address;
|
|
322
|
+
return __generator(this, function (_a) {
|
|
323
|
+
node = this.options.config.bitcoinJSLib.HDNode.fromBase58(publicKey, this.options.network.extras.network);
|
|
324
|
+
address = BitcoinAddress_1.BitcoinAddress.from(node);
|
|
325
|
+
return [2 /*return*/, {
|
|
326
|
+
address: address.asString(),
|
|
327
|
+
cursor: { hasNext: false }
|
|
328
|
+
}];
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
BitcoinProtocol.prototype.getAddressesFromPublicKey = function (publicKey, cursor) {
|
|
333
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
334
|
+
return __generator(this, function (_a) {
|
|
335
|
+
switch (_a.label) {
|
|
336
|
+
case 0: return [4 /*yield*/, this.getAddressFromPublicKey(publicKey, cursor)];
|
|
337
|
+
case 1: return [2 /*return*/, [_a.sent()]];
|
|
216
338
|
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
BitcoinProtocol.prototype.getAddressFromExtendedPublicKey = function (extendedPublicKey, visibilityDerivationIndex, addressDerivationIndex) {
|
|
343
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
344
|
+
var node, address;
|
|
345
|
+
return __generator(this, function (_a) {
|
|
346
|
+
node = this.options.config.bitcoinJSLib.HDNode.fromBase58(extendedPublicKey, this.options.network.extras.network);
|
|
347
|
+
address = BitcoinAddress_1.BitcoinAddress.from(node, visibilityDerivationIndex, addressDerivationIndex);
|
|
348
|
+
return [2 /*return*/, {
|
|
349
|
+
address: address.asString(),
|
|
350
|
+
cursor: { hasNext: false }
|
|
351
|
+
}];
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
};
|
|
355
|
+
BitcoinProtocol.prototype.getAddressesFromExtendedPublicKey = function (extendedPublicKey, visibilityDerivationIndex, addressCount, offset) {
|
|
356
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
357
|
+
var node, generatorArray;
|
|
358
|
+
return __generator(this, function (_a) {
|
|
359
|
+
node = this.options.config.bitcoinJSLib.HDNode.fromBase58(extendedPublicKey, this.options.network.extras.network);
|
|
360
|
+
generatorArray = Array.from(new Array(addressCount), function (_, i) { return i + offset; });
|
|
361
|
+
return [2 /*return*/, Promise.all(generatorArray.map(function (x) {
|
|
362
|
+
var address = BitcoinAddress_1.BitcoinAddress.from(node, visibilityDerivationIndex, x);
|
|
363
|
+
return {
|
|
364
|
+
address: address.asString(),
|
|
365
|
+
cursor: { hasNext: false }
|
|
366
|
+
};
|
|
367
|
+
}))];
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
BitcoinProtocol.prototype.signWithPrivateKey = function (privateKey, transaction) {
|
|
372
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
373
|
+
var transactionBuilder, _i, _a, input, _b, _c, output, generatedChangeAddress, i;
|
|
374
|
+
return __generator(this, function (_d) {
|
|
375
|
+
switch (_d.label) {
|
|
376
|
+
case 0:
|
|
377
|
+
transactionBuilder = new this.options.config.bitcoinJSLib.TransactionBuilder(this.options.network.extras.network);
|
|
378
|
+
for (_i = 0, _a = transaction.ins; _i < _a.length; _i++) {
|
|
379
|
+
input = _a[_i];
|
|
380
|
+
transactionBuilder.addInput(input.txId, input.vout);
|
|
381
|
+
}
|
|
382
|
+
_b = 0, _c = transaction.outs;
|
|
383
|
+
_d.label = 1;
|
|
384
|
+
case 1:
|
|
385
|
+
if (!(_b < _c.length)) return [3 /*break*/, 5];
|
|
386
|
+
output = _c[_b];
|
|
387
|
+
if (!output.isChange) return [3 /*break*/, 3];
|
|
388
|
+
return [4 /*yield*/, this.getAddressFromPublicKey(privateKey)];
|
|
389
|
+
case 2:
|
|
390
|
+
generatedChangeAddress = (_d.sent()).address;
|
|
391
|
+
if (generatedChangeAddress !== output.recipient) {
|
|
392
|
+
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'Change address could not be verified.');
|
|
393
|
+
}
|
|
394
|
+
_d.label = 3;
|
|
395
|
+
case 3:
|
|
396
|
+
transactionBuilder.addOutput(output.recipient, new bignumber_1.default(output.value).toNumber());
|
|
397
|
+
_d.label = 4;
|
|
398
|
+
case 4:
|
|
399
|
+
_b++;
|
|
400
|
+
return [3 /*break*/, 1];
|
|
401
|
+
case 5:
|
|
402
|
+
for (i = 0; i < transaction.ins.length; i++) {
|
|
403
|
+
// 2. `privateKey` is used as a hex string
|
|
404
|
+
transactionBuilder.sign(i, Buffer.from(privateKey, 'hex'));
|
|
405
|
+
}
|
|
406
|
+
// TODO: given 1 & 2, check if it works
|
|
407
|
+
return [2 /*return*/, transactionBuilder.build().toHex()];
|
|
241
408
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
BitcoinProtocol.prototype.signWithExtendedPrivateKey = function (extendedPrivateKey, transaction) {
|
|
413
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
414
|
+
var transactionBuilder, node, _i, _a, input, changeAddressBatchSize, changeAddressMaxAddresses, _b, _c, output, changeAddressIsValid, generatedChangeAddress, x, addresses, i;
|
|
415
|
+
return __generator(this, function (_d) {
|
|
416
|
+
switch (_d.label) {
|
|
417
|
+
case 0:
|
|
418
|
+
transactionBuilder = new this.options.config.bitcoinJSLib.TransactionBuilder(this.options.network.extras.network);
|
|
419
|
+
node = this.options.config.bitcoinJSLib.HDNode.fromBase58(extendedPrivateKey, this.options.network.extras.network);
|
|
420
|
+
for (_i = 0, _a = transaction.ins; _i < _a.length; _i++) {
|
|
421
|
+
input = _a[_i];
|
|
422
|
+
transactionBuilder.addInput(input.txId, input.vout);
|
|
423
|
+
}
|
|
424
|
+
changeAddressBatchSize = 10;
|
|
425
|
+
changeAddressMaxAddresses = 500;
|
|
426
|
+
_b = 0, _c = transaction.outs;
|
|
427
|
+
_d.label = 1;
|
|
428
|
+
case 1:
|
|
429
|
+
if (!(_b < _c.length)) return [3 /*break*/, 10];
|
|
430
|
+
output = _c[_b];
|
|
431
|
+
changeAddressIsValid = false;
|
|
432
|
+
if (!output.isChange) return [3 /*break*/, 8];
|
|
433
|
+
if (!output.derivationPath) return [3 /*break*/, 3];
|
|
434
|
+
return [4 /*yield*/, this.getAddressesFromExtendedPublicKey(extendedPrivateKey, 1, 1, parseInt(output.derivationPath, 10))];
|
|
435
|
+
case 2:
|
|
436
|
+
generatedChangeAddress = (_d.sent()).map(function (address) { return address.address; });
|
|
437
|
+
changeAddressIsValid = generatedChangeAddress.includes(output.recipient);
|
|
438
|
+
return [3 /*break*/, 7];
|
|
439
|
+
case 3:
|
|
440
|
+
x = 0;
|
|
441
|
+
_d.label = 4;
|
|
442
|
+
case 4:
|
|
443
|
+
if (!(x < changeAddressMaxAddresses)) return [3 /*break*/, 7];
|
|
444
|
+
return [4 /*yield*/, this.getAddressesFromExtendedPublicKey(extendedPrivateKey, 1, changeAddressBatchSize, x)];
|
|
445
|
+
case 5:
|
|
446
|
+
addresses = (_d.sent()).map(function (address) { return address.address; });
|
|
245
447
|
if (addresses.indexOf(output.recipient) >= 0) {
|
|
246
448
|
changeAddressIsValid = true;
|
|
247
449
|
x = changeAddressMaxAddresses;
|
|
248
450
|
}
|
|
451
|
+
_d.label = 6;
|
|
452
|
+
case 6:
|
|
453
|
+
x += changeAddressBatchSize;
|
|
454
|
+
return [3 /*break*/, 4];
|
|
455
|
+
case 7:
|
|
456
|
+
if (!changeAddressIsValid) {
|
|
457
|
+
throw new errors_1.InvalidValueError(coinlib_error_1.Domain.BITCOIN, 'Change address could not be verified.');
|
|
458
|
+
}
|
|
459
|
+
_d.label = 8;
|
|
460
|
+
case 8:
|
|
461
|
+
transactionBuilder.addOutput(output.recipient, new bignumber_1.default(output.value).toNumber());
|
|
462
|
+
_d.label = 9;
|
|
463
|
+
case 9:
|
|
464
|
+
_b++;
|
|
465
|
+
return [3 /*break*/, 1];
|
|
466
|
+
case 10:
|
|
467
|
+
for (i = 0; i < transaction.ins.length; i++) {
|
|
468
|
+
transactionBuilder.sign(i, node.derivePath(transaction.ins[i].derivationPath));
|
|
469
|
+
}
|
|
470
|
+
return [2 /*return*/, transactionBuilder.build().toHex()];
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
};
|
|
475
|
+
BitcoinProtocol.prototype.getTransactionDetails = function (unsignedTx) {
|
|
476
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
477
|
+
var transaction, feeCalculator, _i, _a, txIn, _b, _c, txOut, warnings;
|
|
478
|
+
return __generator(this, function (_d) {
|
|
479
|
+
transaction = unsignedTx.transaction;
|
|
480
|
+
feeCalculator = new bignumber_1.default(0);
|
|
481
|
+
for (_i = 0, _a = transaction.ins; _i < _a.length; _i++) {
|
|
482
|
+
txIn = _a[_i];
|
|
483
|
+
feeCalculator = feeCalculator.plus(new bignumber_1.default(txIn.value));
|
|
484
|
+
}
|
|
485
|
+
for (_b = 0, _c = transaction.outs; _b < _c.length; _b++) {
|
|
486
|
+
txOut = _c[_b];
|
|
487
|
+
feeCalculator = feeCalculator.minus(new bignumber_1.default(txOut.value));
|
|
488
|
+
}
|
|
489
|
+
warnings = [];
|
|
490
|
+
return [2 /*return*/, [
|
|
491
|
+
{
|
|
492
|
+
from: transaction.ins.map(function (obj) { return obj.address; }),
|
|
493
|
+
to: transaction.outs.filter(function (obj) { return !obj.isChange; }).map(function (obj) { return obj.recipient; }),
|
|
494
|
+
amount: transaction.outs
|
|
495
|
+
.filter(function (obj) { return !obj.isChange; })
|
|
496
|
+
.map(function (obj) { return new bignumber_1.default(obj.value); })
|
|
497
|
+
.reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); })
|
|
498
|
+
.toString(10),
|
|
499
|
+
fee: feeCalculator.toString(10),
|
|
500
|
+
protocolIdentifier: this.identifier,
|
|
501
|
+
network: this.options.network,
|
|
502
|
+
isInbound: false,
|
|
503
|
+
transactionDetails: unsignedTx.transaction,
|
|
504
|
+
warnings: warnings
|
|
505
|
+
}
|
|
506
|
+
]];
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
};
|
|
510
|
+
BitcoinProtocol.prototype.getTransactionDetailsFromSigned = function (signedTx) {
|
|
511
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
512
|
+
var tx, bitcoinTx;
|
|
513
|
+
var _this = this;
|
|
514
|
+
return __generator(this, function (_a) {
|
|
515
|
+
tx = {
|
|
516
|
+
to: [],
|
|
517
|
+
from: signedTx.from,
|
|
518
|
+
amount: signedTx.amount,
|
|
519
|
+
fee: signedTx.fee,
|
|
520
|
+
protocolIdentifier: this.identifier,
|
|
521
|
+
network: this.options.network,
|
|
522
|
+
isInbound: false,
|
|
523
|
+
transactionDetails: signedTx.transaction
|
|
524
|
+
};
|
|
525
|
+
bitcoinTx = this.options.config.bitcoinJSLib.Transaction.fromHex(signedTx.transaction);
|
|
526
|
+
bitcoinTx.outs.forEach(function (output) {
|
|
527
|
+
var address = _this.options.config.bitcoinJSLib.address.fromOutputScript(output.script, _this.options.network.extras.network);
|
|
528
|
+
// only works if one output is target and rest is change, but this way we can filter out change addresses
|
|
529
|
+
if (new bignumber_1.default(output.value).isEqualTo(signedTx.amount)) {
|
|
530
|
+
tx.to.push(address);
|
|
249
531
|
}
|
|
532
|
+
});
|
|
533
|
+
return [2 /*return*/, [tx]];
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
};
|
|
537
|
+
BitcoinProtocol.prototype.getBalanceOfAddresses = function (addresses) {
|
|
538
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
539
|
+
var valueAccumulator, _i, addresses_1, address, data;
|
|
540
|
+
return __generator(this, function (_a) {
|
|
541
|
+
switch (_a.label) {
|
|
542
|
+
case 0:
|
|
543
|
+
valueAccumulator = new bignumber_1.default(0);
|
|
544
|
+
_i = 0, addresses_1 = addresses;
|
|
545
|
+
_a.label = 1;
|
|
546
|
+
case 1:
|
|
547
|
+
if (!(_i < addresses_1.length)) return [3 /*break*/, 4];
|
|
548
|
+
address = addresses_1[_i];
|
|
549
|
+
return [4 /*yield*/, index_1.default.get("".concat(this.options.network.extras.indexerApi, "/api/v2/address/").concat(address, "?details=basic"), {
|
|
550
|
+
responseType: 'json'
|
|
551
|
+
})];
|
|
552
|
+
case 2:
|
|
553
|
+
data = (_a.sent()).data;
|
|
554
|
+
valueAccumulator = valueAccumulator.plus(new bignumber_1.default(data.balance));
|
|
555
|
+
_a.label = 3;
|
|
556
|
+
case 3:
|
|
557
|
+
_i++;
|
|
558
|
+
return [3 /*break*/, 1];
|
|
559
|
+
case 4: return [2 /*return*/, valueAccumulator.toString(10)];
|
|
250
560
|
}
|
|
251
|
-
|
|
252
|
-
|
|
561
|
+
});
|
|
562
|
+
});
|
|
563
|
+
};
|
|
564
|
+
BitcoinProtocol.prototype.getBalanceOfPublicKey = function (publicKey) {
|
|
565
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
566
|
+
var address;
|
|
567
|
+
return __generator(this, function (_a) {
|
|
568
|
+
switch (_a.label) {
|
|
569
|
+
case 0: return [4 /*yield*/, this.getAddressFromPublicKey(publicKey)];
|
|
570
|
+
case 1:
|
|
571
|
+
address = _a.sent();
|
|
572
|
+
return [2 /*return*/, this.getBalanceOfAddresses([address.address])];
|
|
253
573
|
}
|
|
254
|
-
}
|
|
255
|
-
transactionBuilder.addOutput(output.recipient, new bignumber_1.default(output.value).toNumber());
|
|
256
|
-
}
|
|
257
|
-
for (let i = 0; i < transaction.ins.length; i++) {
|
|
258
|
-
transactionBuilder.sign(i, node.derivePath(transaction.ins[i].derivationPath));
|
|
259
|
-
}
|
|
260
|
-
return transactionBuilder.build().toHex();
|
|
261
|
-
}
|
|
262
|
-
async getTransactionDetails(unsignedTx) {
|
|
263
|
-
// out of public information (both broadcaster and signer)
|
|
264
|
-
const transaction = unsignedTx.transaction;
|
|
265
|
-
let feeCalculator = new bignumber_1.default(0);
|
|
266
|
-
for (const txIn of transaction.ins) {
|
|
267
|
-
feeCalculator = feeCalculator.plus(new bignumber_1.default(txIn.value));
|
|
268
|
-
}
|
|
269
|
-
for (const txOut of transaction.outs) {
|
|
270
|
-
feeCalculator = feeCalculator.minus(new bignumber_1.default(txOut.value));
|
|
271
|
-
}
|
|
272
|
-
const warnings = [];
|
|
273
|
-
return [
|
|
274
|
-
{
|
|
275
|
-
from: transaction.ins.map((obj) => obj.address),
|
|
276
|
-
to: transaction.outs.filter((obj) => !obj.isChange).map((obj) => obj.recipient),
|
|
277
|
-
amount: transaction.outs
|
|
278
|
-
.filter((obj) => !obj.isChange)
|
|
279
|
-
.map((obj) => new bignumber_1.default(obj.value))
|
|
280
|
-
.reduce((accumulator, currentValue) => accumulator.plus(currentValue))
|
|
281
|
-
.toString(10),
|
|
282
|
-
fee: feeCalculator.toString(10),
|
|
283
|
-
protocolIdentifier: this.identifier,
|
|
284
|
-
network: this.options.network,
|
|
285
|
-
isInbound: false,
|
|
286
|
-
transactionDetails: unsignedTx.transaction,
|
|
287
|
-
warnings
|
|
288
|
-
}
|
|
289
|
-
];
|
|
290
|
-
}
|
|
291
|
-
async getTransactionDetailsFromSigned(signedTx) {
|
|
292
|
-
const tx = {
|
|
293
|
-
to: [],
|
|
294
|
-
from: signedTx.from,
|
|
295
|
-
amount: signedTx.amount,
|
|
296
|
-
fee: signedTx.fee,
|
|
297
|
-
protocolIdentifier: this.identifier,
|
|
298
|
-
network: this.options.network,
|
|
299
|
-
isInbound: false,
|
|
300
|
-
transactionDetails: signedTx.transaction
|
|
301
|
-
};
|
|
302
|
-
const bitcoinTx = this.options.config.bitcoinJSLib.Transaction.fromHex(signedTx.transaction);
|
|
303
|
-
bitcoinTx.outs.forEach((output) => {
|
|
304
|
-
const address = this.options.config.bitcoinJSLib.address.fromOutputScript(output.script, this.options.network.extras.network);
|
|
305
|
-
// only works if one output is target and rest is change, but this way we can filter out change addresses
|
|
306
|
-
if (new bignumber_1.default(output.value).isEqualTo(signedTx.amount)) {
|
|
307
|
-
tx.to.push(address);
|
|
308
|
-
}
|
|
574
|
+
});
|
|
309
575
|
});
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return this.getBalanceOfAddresses([address.address]);
|
|
326
|
-
}
|
|
327
|
-
async getBalanceOfExtendedPublicKey(extendedPublicKey, offset = 0) {
|
|
328
|
-
const { data } = await index_1.default.get(`${this.options.network.extras.indexerApi}/api/v2/xpub/${extendedPublicKey}?pageSize=1`, {
|
|
329
|
-
responseType: 'json'
|
|
576
|
+
};
|
|
577
|
+
BitcoinProtocol.prototype.getBalanceOfExtendedPublicKey = function (extendedPublicKey, offset) {
|
|
578
|
+
if (offset === void 0) { offset = 0; }
|
|
579
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
580
|
+
var data;
|
|
581
|
+
return __generator(this, function (_a) {
|
|
582
|
+
switch (_a.label) {
|
|
583
|
+
case 0: return [4 /*yield*/, index_1.default.get("".concat(this.options.network.extras.indexerApi, "/api/v2/xpub/").concat(extendedPublicKey, "?pageSize=1"), {
|
|
584
|
+
responseType: 'json'
|
|
585
|
+
})];
|
|
586
|
+
case 1:
|
|
587
|
+
data = (_a.sent()).data;
|
|
588
|
+
return [2 /*return*/, data.balance];
|
|
589
|
+
}
|
|
590
|
+
});
|
|
330
591
|
});
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
async getAvailableBalanceOfAddresses(addresses) {
|
|
337
|
-
return this.getBalanceOfAddresses(addresses);
|
|
338
|
-
}
|
|
339
|
-
async estimateMaxTransactionValueFromExtendedPublicKey(extendedPublicKey, recipients, fee) {
|
|
340
|
-
return this.getBalanceOfExtendedPublicKey(extendedPublicKey);
|
|
341
|
-
}
|
|
342
|
-
async estimateMaxTransactionValueFromPublicKey(publicKey, recipients, fee) {
|
|
343
|
-
return this.getBalanceOfPublicKey(publicKey);
|
|
344
|
-
}
|
|
345
|
-
async estimateFeeDefaultsFromExtendedPublicKey(publicKey, recipients, values, data) {
|
|
346
|
-
const result = (await index_1.default.get(`${this.options.network.extras.indexerApi}/api/v2/estimatefee/5`)).data.result;
|
|
347
|
-
const estimatedFee = new bignumber_1.default(result).shiftedBy(this.feeDecimals);
|
|
348
|
-
if (estimatedFee.isZero()) {
|
|
349
|
-
return this.feeDefaults;
|
|
350
|
-
}
|
|
351
|
-
const feeStepFactor = new bignumber_1.default(0.5);
|
|
352
|
-
const mediumFee = estimatedFee;
|
|
353
|
-
const lowFee = mediumFee.minus(mediumFee.times(feeStepFactor)).integerValue(bignumber_1.default.ROUND_FLOOR);
|
|
354
|
-
const highFee = mediumFee.plus(mediumFee.times(feeStepFactor)).integerValue(bignumber_1.default.ROUND_FLOOR);
|
|
355
|
-
return {
|
|
356
|
-
low: lowFee.shiftedBy(-this.feeDecimals).toFixed(),
|
|
357
|
-
medium: mediumFee.shiftedBy(-this.feeDecimals).toFixed(),
|
|
358
|
-
high: highFee.shiftedBy(-this.feeDecimals).toFixed()
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
async estimateFeeDefaultsFromPublicKey(publicKey, recipients, values, data) {
|
|
362
|
-
return Promise.reject('estimating fee defaults using non extended public key not implemented');
|
|
363
|
-
}
|
|
364
|
-
async prepareTransactionFromExtendedPublicKey(extendedPublicKey, offset, recipients, values, fee, extras) {
|
|
365
|
-
const wrappedValues = values.map((value) => new bignumber_1.default(value));
|
|
366
|
-
const wrappedFee = new bignumber_1.default(fee);
|
|
367
|
-
const transaction = {
|
|
368
|
-
ins: [],
|
|
369
|
-
outs: []
|
|
370
|
-
};
|
|
371
|
-
if (recipients.length !== wrappedValues.length) {
|
|
372
|
-
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'recipients do not match values');
|
|
373
|
-
}
|
|
374
|
-
const { data: utxos } = await index_1.default
|
|
375
|
-
.get(`${this.options.network.extras.indexerApi}/api/v2/utxo/${extendedPublicKey}?confirmed=true`, {
|
|
376
|
-
responseType: 'json'
|
|
377
|
-
})
|
|
378
|
-
.catch((error) => {
|
|
379
|
-
throw new errors_1.NetworkError(coinlib_error_1.Domain.BITCOIN, error);
|
|
380
|
-
});
|
|
381
|
-
if (utxos.length <= 0) {
|
|
382
|
-
throw new errors_1.BalanceError(coinlib_error_1.Domain.BITCOIN, 'not enough balance'); // no transactions found on those addresses, probably won't find anything in the next ones
|
|
383
|
-
}
|
|
384
|
-
const totalRequiredBalance = wrappedValues
|
|
385
|
-
.reduce((accumulator, currentValue) => accumulator.plus(currentValue))
|
|
386
|
-
.plus(wrappedFee);
|
|
387
|
-
let valueAccumulator = new bignumber_1.default(0);
|
|
388
|
-
const getPathIndexes = (path) => {
|
|
389
|
-
const result = path
|
|
390
|
-
.split('/')
|
|
391
|
-
.slice(-2)
|
|
392
|
-
.map((item) => parseInt(item, 10))
|
|
393
|
-
.filter((item) => !isNaN(item));
|
|
394
|
-
if (result.length !== 2) {
|
|
395
|
-
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'Unexpected path format');
|
|
396
|
-
}
|
|
397
|
-
return [result[0], result[1]];
|
|
398
|
-
};
|
|
399
|
-
for (const utxo of utxos) {
|
|
400
|
-
valueAccumulator = valueAccumulator.plus(utxo.value);
|
|
401
|
-
const indexes = getPathIndexes(utxo.path);
|
|
402
|
-
const derivedAddress = await this.getAddressFromExtendedPublicKey(extendedPublicKey, indexes[0], indexes[1]);
|
|
403
|
-
if (derivedAddress.address === utxo.address) {
|
|
404
|
-
transaction.ins.push({
|
|
405
|
-
txId: utxo.txid,
|
|
406
|
-
value: new bignumber_1.default(utxo.value).toString(10),
|
|
407
|
-
vout: utxo.vout,
|
|
408
|
-
address: utxo.address,
|
|
409
|
-
derivationPath: indexes.join('/')
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
throw new errors_1.InvalidValueError(coinlib_error_1.Domain.BITCOIN, `Invalid address ${JSON.stringify(utxo.address)} returned from API`);
|
|
414
|
-
}
|
|
415
|
-
if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
|
|
416
|
-
break;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
if (valueAccumulator.isLessThan(totalRequiredBalance)) {
|
|
420
|
-
throw new errors_1.BalanceError(coinlib_error_1.Domain.BITCOIN, 'not enough balance');
|
|
421
|
-
}
|
|
422
|
-
for (let i = 0; i < recipients.length; i++) {
|
|
423
|
-
transaction.outs.push({
|
|
424
|
-
recipient: recipients[i],
|
|
425
|
-
isChange: false,
|
|
426
|
-
value: wrappedValues[i].toString(10),
|
|
427
|
-
derivationPath: '' // TODO: Remove this as soon as our serializer supports optional properties
|
|
428
|
-
});
|
|
429
|
-
valueAccumulator = valueAccumulator.minus(wrappedValues[i]);
|
|
430
|
-
}
|
|
431
|
-
const lastUsedInternalAddress = Math.max(-1, ...utxos
|
|
432
|
-
.map((utxo) => getPathIndexes(utxo.path))
|
|
433
|
-
.filter((indexes) => indexes[0] === 1)
|
|
434
|
-
.map((indexes) => indexes[1]));
|
|
435
|
-
// If the change is considered dust, the transaction will fail.
|
|
436
|
-
// Dust is a variable value around 300-600 satoshis, depending on the configuration.
|
|
437
|
-
// We set a low fee here to not block any transactions, but it might still fail due to "dust".
|
|
438
|
-
const changeValue = valueAccumulator.minus(wrappedFee);
|
|
439
|
-
if (changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) {
|
|
440
|
-
const changeAddressIndex = lastUsedInternalAddress + 1;
|
|
441
|
-
const derivedAddress = await this.getAddressFromExtendedPublicKey(extendedPublicKey, 1, changeAddressIndex);
|
|
442
|
-
transaction.outs.push({
|
|
443
|
-
recipient: derivedAddress.address,
|
|
444
|
-
isChange: true,
|
|
445
|
-
value: changeValue.toString(10),
|
|
446
|
-
derivationPath: changeAddressIndex.toString()
|
|
592
|
+
};
|
|
593
|
+
BitcoinProtocol.prototype.getBalanceOfPublicKeyForSubProtocols = function (publicKey, subProtocols) {
|
|
594
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
595
|
+
return __generator(this, function (_a) {
|
|
596
|
+
throw Promise.reject('get balance of sub protocols not supported');
|
|
447
597
|
});
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
const transaction = {
|
|
455
|
-
ins: [],
|
|
456
|
-
outs: []
|
|
457
|
-
};
|
|
458
|
-
if (recipients.length !== wrappedValues.length) {
|
|
459
|
-
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'Recipient and value length does not match.');
|
|
460
|
-
}
|
|
461
|
-
const address = (await this.getAddressFromPublicKey(publicKey)).address;
|
|
462
|
-
const { data: utxos } = await index_1.default.get(`${this.options.network.extras.indexerApi}/api/v2/utxo/${address}`, {
|
|
463
|
-
responseType: 'json'
|
|
464
|
-
});
|
|
465
|
-
const totalRequiredBalance = wrappedValues
|
|
466
|
-
.reduce((accumulator, currentValue) => accumulator.plus(currentValue))
|
|
467
|
-
.plus(wrappedFee);
|
|
468
|
-
let valueAccumulator = new bignumber_1.default(0);
|
|
469
|
-
for (const utxo of utxos) {
|
|
470
|
-
valueAccumulator = valueAccumulator.plus(new bignumber_1.default(utxo.value));
|
|
471
|
-
transaction.ins.push({
|
|
472
|
-
txId: utxo.txid,
|
|
473
|
-
value: new bignumber_1.default(utxo.value).toString(10),
|
|
474
|
-
vout: utxo.vout,
|
|
475
|
-
address
|
|
476
|
-
});
|
|
477
|
-
if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
|
|
478
|
-
break;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
if (valueAccumulator.isLessThan(totalRequiredBalance)) {
|
|
482
|
-
throw new errors_1.BalanceError(coinlib_error_1.Domain.BITCOIN, `not enough balance, having ${valueAccumulator.toFixed()} of ${totalRequiredBalance.toFixed()}`);
|
|
483
|
-
}
|
|
484
|
-
// tx.addInput(utxo.txid, utxo.vout)
|
|
485
|
-
for (let i = 0; i < recipients.length; i++) {
|
|
486
|
-
transaction.outs.push({
|
|
487
|
-
recipient: recipients[i],
|
|
488
|
-
isChange: false,
|
|
489
|
-
value: wrappedValues[i].toString(10)
|
|
490
|
-
});
|
|
491
|
-
valueAccumulator = valueAccumulator.minus(wrappedValues[i]);
|
|
492
|
-
// tx.addOutput(recipients[i], values[i])
|
|
493
|
-
}
|
|
494
|
-
// If the change is considered dust, the transaction will fail.
|
|
495
|
-
// Dust is a variable value around 300-600 satoshis, depending on the configuration.
|
|
496
|
-
// We set a low fee here to not block any transactions, but it might still fail due to "dust".
|
|
497
|
-
const changeValue = valueAccumulator.minus(wrappedFee);
|
|
498
|
-
if (changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) {
|
|
499
|
-
transaction.outs.push({
|
|
500
|
-
recipient: address,
|
|
501
|
-
isChange: true,
|
|
502
|
-
value: changeValue.toString(10)
|
|
598
|
+
});
|
|
599
|
+
};
|
|
600
|
+
BitcoinProtocol.prototype.getAvailableBalanceOfAddresses = function (addresses) {
|
|
601
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
602
|
+
return __generator(this, function (_a) {
|
|
603
|
+
return [2 /*return*/, this.getBalanceOfAddresses(addresses)];
|
|
503
604
|
});
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
605
|
+
});
|
|
606
|
+
};
|
|
607
|
+
BitcoinProtocol.prototype.estimateMaxTransactionValueFromExtendedPublicKey = function (extendedPublicKey, recipients, fee) {
|
|
608
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
609
|
+
return __generator(this, function (_a) {
|
|
610
|
+
return [2 /*return*/, this.getBalanceOfExtendedPublicKey(extendedPublicKey)];
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
};
|
|
614
|
+
BitcoinProtocol.prototype.estimateMaxTransactionValueFromPublicKey = function (publicKey, recipients, fee) {
|
|
615
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
616
|
+
return __generator(this, function (_a) {
|
|
617
|
+
return [2 /*return*/, this.getBalanceOfPublicKey(publicKey)];
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
};
|
|
621
|
+
BitcoinProtocol.prototype.estimateFeeDefaultsFromExtendedPublicKey = function (publicKey, recipients, values, data) {
|
|
622
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
623
|
+
var result, estimatedFee, feeStepFactor, mediumFee, lowFee, highFee;
|
|
624
|
+
return __generator(this, function (_a) {
|
|
625
|
+
switch (_a.label) {
|
|
626
|
+
case 0: return [4 /*yield*/, index_1.default.get("".concat(this.options.network.extras.indexerApi, "/api/v2/estimatefee/5"))];
|
|
627
|
+
case 1:
|
|
628
|
+
result = (_a.sent()).data.result;
|
|
629
|
+
estimatedFee = new bignumber_1.default(result).shiftedBy(this.feeDecimals);
|
|
630
|
+
if (estimatedFee.isZero()) {
|
|
631
|
+
return [2 /*return*/, this.feeDefaults];
|
|
632
|
+
}
|
|
633
|
+
feeStepFactor = new bignumber_1.default(0.5);
|
|
634
|
+
mediumFee = estimatedFee;
|
|
635
|
+
lowFee = mediumFee.minus(mediumFee.times(feeStepFactor)).integerValue(bignumber_1.default.ROUND_FLOOR);
|
|
636
|
+
highFee = mediumFee.plus(mediumFee.times(feeStepFactor)).integerValue(bignumber_1.default.ROUND_FLOOR);
|
|
637
|
+
return [2 /*return*/, {
|
|
638
|
+
low: lowFee.shiftedBy(-this.feeDecimals).toFixed(),
|
|
639
|
+
medium: mediumFee.shiftedBy(-this.feeDecimals).toFixed(),
|
|
640
|
+
high: highFee.shiftedBy(-this.feeDecimals).toFixed()
|
|
641
|
+
}];
|
|
533
642
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
};
|
|
646
|
+
BitcoinProtocol.prototype.estimateFeeDefaultsFromPublicKey = function (publicKey, recipients, values, data) {
|
|
647
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
648
|
+
return __generator(this, function (_a) {
|
|
649
|
+
return [2 /*return*/, Promise.reject('estimating fee defaults using non extended public key not implemented')];
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
};
|
|
653
|
+
BitcoinProtocol.prototype.prepareTransactionFromExtendedPublicKey = function (extendedPublicKey, offset, recipients, values, fee, extras) {
|
|
654
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
655
|
+
var wrappedValues, wrappedFee, transaction, utxos, totalRequiredBalance, valueAccumulator, getPathIndexes, _i, utxos_1, utxo, indexes, derivedAddress, i, lastUsedInternalAddress, changeValue, changeAddressIndex, derivedAddress;
|
|
656
|
+
return __generator(this, function (_a) {
|
|
657
|
+
switch (_a.label) {
|
|
658
|
+
case 0:
|
|
659
|
+
wrappedValues = values.map(function (value) { return new bignumber_1.default(value); });
|
|
660
|
+
wrappedFee = new bignumber_1.default(fee);
|
|
661
|
+
transaction = {
|
|
662
|
+
ins: [],
|
|
663
|
+
outs: []
|
|
664
|
+
};
|
|
665
|
+
if (recipients.length !== wrappedValues.length) {
|
|
666
|
+
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'recipients do not match values');
|
|
541
667
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
668
|
+
return [4 /*yield*/, index_1.default
|
|
669
|
+
.get("".concat(this.options.network.extras.indexerApi, "/api/v2/utxo/").concat(extendedPublicKey, "?confirmed=true"), {
|
|
670
|
+
responseType: 'json'
|
|
671
|
+
})
|
|
672
|
+
.catch(function (error) {
|
|
673
|
+
throw new errors_1.NetworkError(coinlib_error_1.Domain.BITCOIN, error);
|
|
674
|
+
})];
|
|
675
|
+
case 1:
|
|
676
|
+
utxos = (_a.sent()).data;
|
|
677
|
+
if (utxos.length <= 0) {
|
|
678
|
+
throw new errors_1.BalanceError(coinlib_error_1.Domain.BITCOIN, 'not enough balance'); // no transactions found on those addresses, probably won't find anything in the next ones
|
|
545
679
|
}
|
|
546
|
-
|
|
680
|
+
totalRequiredBalance = wrappedValues
|
|
681
|
+
.reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); })
|
|
682
|
+
.plus(wrappedFee);
|
|
683
|
+
valueAccumulator = new bignumber_1.default(0);
|
|
684
|
+
getPathIndexes = function (path) {
|
|
685
|
+
var result = path
|
|
686
|
+
.split('/')
|
|
687
|
+
.slice(-2)
|
|
688
|
+
.map(function (item) { return parseInt(item, 10); })
|
|
689
|
+
.filter(function (item) { return !isNaN(item); });
|
|
690
|
+
if (result.length !== 2) {
|
|
691
|
+
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'Unexpected path format');
|
|
692
|
+
}
|
|
693
|
+
return [result[0], result[1]];
|
|
694
|
+
};
|
|
695
|
+
_i = 0, utxos_1 = utxos;
|
|
696
|
+
_a.label = 2;
|
|
697
|
+
case 2:
|
|
698
|
+
if (!(_i < utxos_1.length)) return [3 /*break*/, 5];
|
|
699
|
+
utxo = utxos_1[_i];
|
|
700
|
+
valueAccumulator = valueAccumulator.plus(utxo.value);
|
|
701
|
+
indexes = getPathIndexes(utxo.path);
|
|
702
|
+
return [4 /*yield*/, this.getAddressFromExtendedPublicKey(extendedPublicKey, indexes[0], indexes[1])];
|
|
703
|
+
case 3:
|
|
704
|
+
derivedAddress = _a.sent();
|
|
705
|
+
if (derivedAddress.address === utxo.address) {
|
|
706
|
+
transaction.ins.push({
|
|
707
|
+
txId: utxo.txid,
|
|
708
|
+
value: new bignumber_1.default(utxo.value).toString(10),
|
|
709
|
+
vout: utxo.vout,
|
|
710
|
+
address: utxo.address,
|
|
711
|
+
derivationPath: indexes.join('/')
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
throw new errors_1.InvalidValueError(coinlib_error_1.Domain.BITCOIN, "Invalid address ".concat(JSON.stringify(utxo.address), " returned from API"));
|
|
716
|
+
}
|
|
717
|
+
if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
|
|
718
|
+
return [3 /*break*/, 5];
|
|
719
|
+
}
|
|
720
|
+
_a.label = 4;
|
|
721
|
+
case 4:
|
|
722
|
+
_i++;
|
|
723
|
+
return [3 /*break*/, 2];
|
|
724
|
+
case 5:
|
|
725
|
+
if (valueAccumulator.isLessThan(totalRequiredBalance)) {
|
|
726
|
+
throw new errors_1.BalanceError(coinlib_error_1.Domain.BITCOIN, 'not enough balance');
|
|
727
|
+
}
|
|
728
|
+
for (i = 0; i < recipients.length; i++) {
|
|
729
|
+
transaction.outs.push({
|
|
730
|
+
recipient: recipients[i],
|
|
731
|
+
isChange: false,
|
|
732
|
+
value: wrappedValues[i].toString(10),
|
|
733
|
+
derivationPath: '' // TODO: Remove this as soon as our serializer supports optional properties
|
|
734
|
+
});
|
|
735
|
+
valueAccumulator = valueAccumulator.minus(wrappedValues[i]);
|
|
736
|
+
}
|
|
737
|
+
lastUsedInternalAddress = Math.max.apply(Math, __spreadArray([-1], utxos
|
|
738
|
+
.map(function (utxo) { return getPathIndexes(utxo.path); })
|
|
739
|
+
.filter(function (indexes) { return indexes[0] === 1; })
|
|
740
|
+
.map(function (indexes) { return indexes[1]; }), false));
|
|
741
|
+
changeValue = valueAccumulator.minus(wrappedFee);
|
|
742
|
+
if (!changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) return [3 /*break*/, 7];
|
|
743
|
+
changeAddressIndex = lastUsedInternalAddress + 1;
|
|
744
|
+
return [4 /*yield*/, this.getAddressFromExtendedPublicKey(extendedPublicKey, 1, changeAddressIndex)];
|
|
745
|
+
case 6:
|
|
746
|
+
derivedAddress = _a.sent();
|
|
747
|
+
transaction.outs.push({
|
|
748
|
+
recipient: derivedAddress.address,
|
|
749
|
+
isChange: true,
|
|
750
|
+
value: changeValue.toString(10),
|
|
751
|
+
derivationPath: changeAddressIndex.toString()
|
|
752
|
+
});
|
|
753
|
+
_a.label = 7;
|
|
754
|
+
case 7: return [2 /*return*/, transaction];
|
|
547
755
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
};
|
|
759
|
+
BitcoinProtocol.prototype.prepareTransactionFromPublicKey = function (publicKey, recipients, values, fee) {
|
|
760
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
761
|
+
var wrappedValues, wrappedFee, transaction, address, utxos, totalRequiredBalance, valueAccumulator, _i, utxos_2, utxo, i, changeValue;
|
|
762
|
+
return __generator(this, function (_a) {
|
|
763
|
+
switch (_a.label) {
|
|
764
|
+
case 0:
|
|
765
|
+
wrappedValues = values.map(function (value) { return new bignumber_1.default(value); });
|
|
766
|
+
wrappedFee = new bignumber_1.default(fee);
|
|
767
|
+
transaction = {
|
|
768
|
+
ins: [],
|
|
769
|
+
outs: []
|
|
770
|
+
};
|
|
771
|
+
if (recipients.length !== wrappedValues.length) {
|
|
772
|
+
throw new errors_1.ConditionViolationError(coinlib_error_1.Domain.BITCOIN, 'Recipient and value length does not match.');
|
|
773
|
+
}
|
|
774
|
+
return [4 /*yield*/, this.getAddressFromPublicKey(publicKey)];
|
|
775
|
+
case 1:
|
|
776
|
+
address = (_a.sent()).address;
|
|
777
|
+
return [4 /*yield*/, index_1.default.get("".concat(this.options.network.extras.indexerApi, "/api/v2/utxo/").concat(address), {
|
|
778
|
+
responseType: 'json'
|
|
779
|
+
})];
|
|
780
|
+
case 2:
|
|
781
|
+
utxos = (_a.sent()).data;
|
|
782
|
+
totalRequiredBalance = wrappedValues
|
|
783
|
+
.reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); })
|
|
784
|
+
.plus(wrappedFee);
|
|
785
|
+
valueAccumulator = new bignumber_1.default(0);
|
|
786
|
+
for (_i = 0, utxos_2 = utxos; _i < utxos_2.length; _i++) {
|
|
787
|
+
utxo = utxos_2[_i];
|
|
788
|
+
valueAccumulator = valueAccumulator.plus(new bignumber_1.default(utxo.value));
|
|
789
|
+
transaction.ins.push({
|
|
790
|
+
txId: utxo.txid,
|
|
791
|
+
value: new bignumber_1.default(utxo.value).toString(10),
|
|
792
|
+
vout: utxo.vout,
|
|
793
|
+
address: address
|
|
794
|
+
});
|
|
795
|
+
if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
|
|
796
|
+
break;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
if (valueAccumulator.isLessThan(totalRequiredBalance)) {
|
|
800
|
+
throw new errors_1.BalanceError(coinlib_error_1.Domain.BITCOIN, "not enough balance, having ".concat(valueAccumulator.toFixed(), " of ").concat(totalRequiredBalance.toFixed()));
|
|
801
|
+
}
|
|
802
|
+
// tx.addInput(utxo.txid, utxo.vout)
|
|
803
|
+
for (i = 0; i < recipients.length; i++) {
|
|
804
|
+
transaction.outs.push({
|
|
805
|
+
recipient: recipients[i],
|
|
806
|
+
isChange: false,
|
|
807
|
+
value: wrappedValues[i].toString(10)
|
|
808
|
+
});
|
|
809
|
+
valueAccumulator = valueAccumulator.minus(wrappedValues[i]);
|
|
810
|
+
// tx.addOutput(recipients[i], values[i])
|
|
811
|
+
}
|
|
812
|
+
changeValue = valueAccumulator.minus(wrappedFee);
|
|
813
|
+
if (changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) {
|
|
814
|
+
transaction.outs.push({
|
|
815
|
+
recipient: address,
|
|
816
|
+
isChange: true,
|
|
817
|
+
value: changeValue.toString(10)
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
return [2 /*return*/, transaction];
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
};
|
|
825
|
+
BitcoinProtocol.prototype.broadcastTransaction = function (rawTransaction) {
|
|
826
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
827
|
+
var data;
|
|
828
|
+
return __generator(this, function (_a) {
|
|
829
|
+
switch (_a.label) {
|
|
830
|
+
case 0: return [4 /*yield*/, index_1.default.post(this.options.network.extras.indexerApi + '/api/v2/sendtx/', rawTransaction)];
|
|
831
|
+
case 1:
|
|
832
|
+
data = (_a.sent()).data;
|
|
833
|
+
return [2 /*return*/, data.result];
|
|
595
834
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
835
|
+
});
|
|
836
|
+
});
|
|
837
|
+
};
|
|
838
|
+
BitcoinProtocol.prototype.getTransactionsFromExtendedPublicKey = function (extendedPublicKey, limit, cursor, addressOffset) {
|
|
839
|
+
var _a;
|
|
840
|
+
if (addressOffset === void 0) { addressOffset = 0; }
|
|
841
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
842
|
+
var page, data, ourAddresses, airGapTransactions, _i, _b, transaction, tempAirGapTransactionFrom, tempAirGapTransactionTo, tempAirGapTransactionIsInbound, amount, _c, _d, vin, _e, _f, vout, airGapTransaction;
|
|
843
|
+
return __generator(this, function (_g) {
|
|
844
|
+
switch (_g.label) {
|
|
845
|
+
case 0:
|
|
846
|
+
page = (_a = cursor === null || cursor === void 0 ? void 0 : cursor.page) !== null && _a !== void 0 ? _a : 1;
|
|
847
|
+
return [4 /*yield*/, index_1.default.get(this.options.network.extras.indexerApi +
|
|
848
|
+
'/api/v2/xpub/' +
|
|
849
|
+
extendedPublicKey +
|
|
850
|
+
"?details=txs&tokens=used&pageSize=".concat(limit, "&page=").concat(page), {
|
|
851
|
+
responseType: 'json'
|
|
852
|
+
})];
|
|
853
|
+
case 1:
|
|
854
|
+
data = (_g.sent()).data;
|
|
855
|
+
ourAddresses = (data.tokens || []).filter(function (token) { return token.type === 'XPUBAddress'; }).map(function (token) { return token.name; });
|
|
856
|
+
airGapTransactions = [];
|
|
857
|
+
if (data.page == page) {
|
|
858
|
+
for (_i = 0, _b = data.transactions || []; _i < _b.length; _i++) {
|
|
859
|
+
transaction = _b[_i];
|
|
860
|
+
tempAirGapTransactionFrom = [];
|
|
861
|
+
tempAirGapTransactionTo = [];
|
|
862
|
+
tempAirGapTransactionIsInbound = true;
|
|
863
|
+
amount = new bignumber_1.default(0);
|
|
864
|
+
for (_c = 0, _d = transaction.vin; _c < _d.length; _c++) {
|
|
865
|
+
vin = _d[_c];
|
|
866
|
+
if (this.containsSome(vin.addresses, ourAddresses)) {
|
|
867
|
+
tempAirGapTransactionIsInbound = false;
|
|
868
|
+
}
|
|
869
|
+
tempAirGapTransactionFrom.push.apply(tempAirGapTransactionFrom, vin.addresses);
|
|
870
|
+
amount = amount.plus(vin.value);
|
|
871
|
+
}
|
|
872
|
+
for (_e = 0, _f = transaction.vout; _e < _f.length; _e++) {
|
|
873
|
+
vout = _f[_e];
|
|
874
|
+
if (vout.addresses) {
|
|
875
|
+
tempAirGapTransactionTo.push.apply(tempAirGapTransactionTo, vout.addresses);
|
|
876
|
+
// If receiving address is our address, and transaction is outbound => our change
|
|
877
|
+
if (this.containsSome(vout.addresses, ourAddresses) && !tempAirGapTransactionIsInbound) {
|
|
878
|
+
// remove only if related to this address
|
|
879
|
+
amount = amount.minus(vout.value);
|
|
880
|
+
}
|
|
881
|
+
// If receiving address is not ours, and transaction isbound => senders change
|
|
882
|
+
if (!this.containsSome(vout.addresses, ourAddresses) && tempAirGapTransactionIsInbound) {
|
|
883
|
+
amount = amount.minus(vout.value);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
// deduct fee from amount
|
|
888
|
+
amount = amount.minus(transaction.fees);
|
|
889
|
+
airGapTransaction = {
|
|
890
|
+
hash: transaction.txid,
|
|
891
|
+
from: tempAirGapTransactionFrom,
|
|
892
|
+
to: tempAirGapTransactionTo,
|
|
893
|
+
isInbound: tempAirGapTransactionIsInbound,
|
|
894
|
+
amount: amount.toString(10),
|
|
895
|
+
fee: new bignumber_1.default(transaction.fees).toString(10),
|
|
896
|
+
blockHeight: transaction.blockHeight.toString(),
|
|
897
|
+
protocolIdentifier: this.identifier,
|
|
898
|
+
network: this.options.network,
|
|
899
|
+
timestamp: transaction.blockTime
|
|
900
|
+
};
|
|
901
|
+
airGapTransactions.push(airGapTransaction);
|
|
902
|
+
}
|
|
603
903
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
904
|
+
return [2 /*return*/, {
|
|
905
|
+
transactions: airGapTransactions,
|
|
906
|
+
cursor: {
|
|
907
|
+
page: cursor ? cursor.page + 1 : 2
|
|
908
|
+
}
|
|
909
|
+
}];
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
};
|
|
914
|
+
BitcoinProtocol.prototype.getTransactionsFromPublicKey = function (publicKey, limit, cursor) {
|
|
915
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
916
|
+
var address;
|
|
917
|
+
return __generator(this, function (_a) {
|
|
918
|
+
switch (_a.label) {
|
|
919
|
+
case 0: return [4 /*yield*/, this.getAddressFromPublicKey(publicKey)];
|
|
920
|
+
case 1:
|
|
921
|
+
address = _a.sent();
|
|
922
|
+
return [2 /*return*/, this.getTransactionsFromAddresses([address.address], limit, cursor)];
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
});
|
|
926
|
+
};
|
|
927
|
+
BitcoinProtocol.prototype.getTransactionsFromAddresses = function (addresses, limit, cursor) {
|
|
928
|
+
var _a;
|
|
929
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
930
|
+
var airGapTransactions, page, url, data, _i, _b, transaction, tempAirGapTransactionFrom, tempAirGapTransactionTo, tempAirGapTransactionIsInbound, amount, _c, _d, vin, _e, _f, vout, airGapTransaction;
|
|
931
|
+
return __generator(this, function (_g) {
|
|
932
|
+
switch (_g.label) {
|
|
933
|
+
case 0:
|
|
934
|
+
airGapTransactions = [];
|
|
935
|
+
page = (_a = cursor === null || cursor === void 0 ? void 0 : cursor.page) !== null && _a !== void 0 ? _a : 1;
|
|
936
|
+
url = "".concat(this.options.network.extras.indexerApi, "/api/v2/address/").concat(addresses[0], "?page=").concat(page, "&pageSize=").concat(limit, "&details=txs");
|
|
937
|
+
return [4 /*yield*/, index_1.default.get(url, {
|
|
938
|
+
responseType: 'json'
|
|
939
|
+
})];
|
|
940
|
+
case 1:
|
|
941
|
+
data = (_g.sent()).data;
|
|
942
|
+
if (data.page == page) {
|
|
943
|
+
for (_i = 0, _b = data.transactions || []; _i < _b.length; _i++) {
|
|
944
|
+
transaction = _b[_i];
|
|
945
|
+
tempAirGapTransactionFrom = [];
|
|
946
|
+
tempAirGapTransactionTo = [];
|
|
947
|
+
tempAirGapTransactionIsInbound = true;
|
|
948
|
+
amount = new bignumber_1.default(0);
|
|
949
|
+
for (_c = 0, _d = transaction.vin; _c < _d.length; _c++) {
|
|
950
|
+
vin = _d[_c];
|
|
951
|
+
if (vin.addresses && this.containsSome(vin.addresses, addresses)) {
|
|
952
|
+
tempAirGapTransactionIsInbound = false;
|
|
953
|
+
}
|
|
954
|
+
tempAirGapTransactionFrom.push.apply(tempAirGapTransactionFrom, vin.addresses);
|
|
955
|
+
amount = vin.value ? amount.plus(vin.value) : amount;
|
|
956
|
+
}
|
|
957
|
+
for (_e = 0, _f = transaction.vout; _e < _f.length; _e++) {
|
|
958
|
+
vout = _f[_e];
|
|
959
|
+
if (vout.addresses) {
|
|
960
|
+
tempAirGapTransactionTo.push.apply(tempAirGapTransactionTo, vout.addresses);
|
|
961
|
+
// If receiving address is our address, and transaction is outbound => our change
|
|
962
|
+
if (this.containsSome(vout.addresses, addresses) && !tempAirGapTransactionIsInbound) {
|
|
963
|
+
// remove only if related to this address
|
|
964
|
+
amount = amount.minus(new bignumber_1.default(vout.value));
|
|
965
|
+
}
|
|
966
|
+
// If receiving address is not ours, and transaction isbound => senders change
|
|
967
|
+
if (!this.containsSome(vout.addresses, addresses) && tempAirGapTransactionIsInbound) {
|
|
968
|
+
amount = amount.minus(new bignumber_1.default(vout.value));
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
// deduct fee from amount
|
|
973
|
+
amount = amount.minus(new bignumber_1.default(transaction.fees));
|
|
974
|
+
airGapTransaction = {
|
|
975
|
+
hash: transaction.txid,
|
|
976
|
+
from: tempAirGapTransactionFrom,
|
|
977
|
+
to: tempAirGapTransactionTo,
|
|
978
|
+
isInbound: tempAirGapTransactionIsInbound,
|
|
979
|
+
amount: amount.toString(10),
|
|
980
|
+
fee: new bignumber_1.default(transaction.fees).toString(10),
|
|
981
|
+
blockHeight: transaction.blockHeight.toString(),
|
|
982
|
+
protocolIdentifier: this.identifier,
|
|
983
|
+
network: this.options.network,
|
|
984
|
+
timestamp: transaction.blockTime
|
|
985
|
+
};
|
|
986
|
+
airGapTransactions.push(airGapTransaction);
|
|
987
|
+
}
|
|
607
988
|
}
|
|
608
|
-
|
|
989
|
+
return [2 /*return*/, {
|
|
990
|
+
transactions: airGapTransactions,
|
|
991
|
+
cursor: {
|
|
992
|
+
page: cursor ? cursor.page + 1 : 2
|
|
993
|
+
}
|
|
994
|
+
}];
|
|
609
995
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
isInbound: tempAirGapTransactionIsInbound,
|
|
617
|
-
amount: amount.toString(10),
|
|
618
|
-
fee: new bignumber_1.default(transaction.fees).toString(10),
|
|
619
|
-
blockHeight: transaction.blockHeight.toString(),
|
|
620
|
-
protocolIdentifier: this.identifier,
|
|
621
|
-
network: this.options.network,
|
|
622
|
-
timestamp: transaction.blockTime
|
|
623
|
-
};
|
|
624
|
-
airGapTransactions.push(airGapTransaction);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
transactions: airGapTransactions,
|
|
629
|
-
cursor: {
|
|
630
|
-
page: cursor ? cursor.page + 1 : 2
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
containsSome(needles, haystack) {
|
|
635
|
-
for (const needle of needles) {
|
|
996
|
+
});
|
|
997
|
+
});
|
|
998
|
+
};
|
|
999
|
+
BitcoinProtocol.prototype.containsSome = function (needles, haystack) {
|
|
1000
|
+
for (var _i = 0, needles_1 = needles; _i < needles_1.length; _i++) {
|
|
1001
|
+
var needle = needles_1[_i];
|
|
636
1002
|
if (haystack.indexOf(needle) > -1) {
|
|
637
1003
|
return true;
|
|
638
1004
|
}
|
|
639
1005
|
}
|
|
640
1006
|
return false;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
return this
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
return
|
|
670
|
-
|
|
671
|
-
|
|
1007
|
+
};
|
|
1008
|
+
BitcoinProtocol.prototype.signMessage = function (message, keypair) {
|
|
1009
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1010
|
+
return __generator(this, function (_a) {
|
|
1011
|
+
return [2 /*return*/, this.cryptoClient.signMessage(message, keypair)];
|
|
1012
|
+
});
|
|
1013
|
+
});
|
|
1014
|
+
};
|
|
1015
|
+
BitcoinProtocol.prototype.verifyMessage = function (message, signature, publicKey) {
|
|
1016
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1017
|
+
return __generator(this, function (_a) {
|
|
1018
|
+
return [2 /*return*/, this.cryptoClient.verifyMessage(message, signature, publicKey)];
|
|
1019
|
+
});
|
|
1020
|
+
});
|
|
1021
|
+
};
|
|
1022
|
+
BitcoinProtocol.prototype.encryptAsymmetric = function (message, publicKey) {
|
|
1023
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1024
|
+
var childPublicKey;
|
|
1025
|
+
return __generator(this, function (_a) {
|
|
1026
|
+
childPublicKey = this.options.config.bitcoinJSLib.HDNode.fromBase58(publicKey, this.options.network.extras.network)
|
|
1027
|
+
.derive(0)
|
|
1028
|
+
.derive(0)
|
|
1029
|
+
.getPublicKeyBuffer();
|
|
1030
|
+
return [2 /*return*/, this.cryptoClient.encryptAsymmetric(message, childPublicKey)];
|
|
1031
|
+
});
|
|
1032
|
+
});
|
|
1033
|
+
};
|
|
1034
|
+
BitcoinProtocol.prototype.decryptAsymmetric = function (message, keypair) {
|
|
1035
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1036
|
+
var childPrivateKey;
|
|
1037
|
+
return __generator(this, function (_a) {
|
|
1038
|
+
childPrivateKey = this.options.config.bitcoinJSLib.HDNode.fromBase58(keypair.privateKey, this.options.network.extras.network)
|
|
1039
|
+
.derive(0)
|
|
1040
|
+
.derive(0)
|
|
1041
|
+
.keyPair.d.toBuffer(32);
|
|
1042
|
+
return [2 /*return*/, this.cryptoClient.decryptAsymmetric(message, { publicKey: '', privateKey: childPrivateKey.toString('hex') })];
|
|
1043
|
+
});
|
|
1044
|
+
});
|
|
1045
|
+
};
|
|
1046
|
+
BitcoinProtocol.prototype.encryptAES = function (message, privateKey) {
|
|
1047
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1048
|
+
return __generator(this, function (_a) {
|
|
1049
|
+
return [2 /*return*/, this.cryptoClient.encryptAES(message, privateKey)];
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
};
|
|
1053
|
+
BitcoinProtocol.prototype.decryptAES = function (message, privateKey) {
|
|
1054
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1055
|
+
return __generator(this, function (_a) {
|
|
1056
|
+
return [2 /*return*/, this.cryptoClient.decryptAES(message, privateKey)];
|
|
1057
|
+
});
|
|
1058
|
+
});
|
|
1059
|
+
};
|
|
1060
|
+
BitcoinProtocol.prototype.getTransactionStatuses = function (transactionHashes) {
|
|
1061
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1062
|
+
return __generator(this, function (_a) {
|
|
1063
|
+
return [2 /*return*/, Promise.reject('Transaction status not implemented')];
|
|
1064
|
+
});
|
|
1065
|
+
});
|
|
1066
|
+
};
|
|
1067
|
+
return BitcoinProtocol;
|
|
1068
|
+
}());
|
|
672
1069
|
exports.BitcoinProtocol = BitcoinProtocol;
|
|
673
1070
|
//# sourceMappingURL=BitcoinProtocol.js.map
|