Code Duplication    Length = 104-108 lines in 2 locations

lib/api_client.js 2 locations

@@ 1155-1262 (lines=108) @@
1152
            identifier,
1153
            options.walletVersion,
1154
            result.primary_mnemonic,
1155
            result.encrypted_primary_seed,
1156
            result.encrypted_secret,
1157
            primaryPublicKeys,
1158
            backupPublicKey,
1159
            blocktrailPublicKeys,
1160
            keyIndex,
1161
            result.segwit || 0,
1162
            self.testnet,
1163
            result.checksum,
1164
            result.upgrade_key_index,
1165
            options.useCashAddress,
1166
            options.bypassNewAddressCheck
1167
        );
1168
1169
        wallet.recoverySecret = result.recovery_secret;
1170
1171
        if (!options.readOnly) {
1172
            return wallet.unlock(options).then(function() {
1173
                return wallet;
1174
            });
1175
        } else {
1176
            return wallet;
1177
        }
1178
    }));
1179
1180
    return deferred.promise;
1181
};
1182
1183
APIClient.CREATE_WALLET_PROGRESS_START = 0;
1184
APIClient.CREATE_WALLET_PROGRESS_ENCRYPT_SECRET = 4;
1185
APIClient.CREATE_WALLET_PROGRESS_ENCRYPT_PRIMARY = 5;
1186
APIClient.CREATE_WALLET_PROGRESS_ENCRYPT_RECOVERY = 6;
1187
APIClient.CREATE_WALLET_PROGRESS_PRIMARY = 10;
1188
APIClient.CREATE_WALLET_PROGRESS_BACKUP = 20;
1189
APIClient.CREATE_WALLET_PROGRESS_SUBMIT = 30;
1190
APIClient.CREATE_WALLET_PROGRESS_INIT = 40;
1191
APIClient.CREATE_WALLET_PROGRESS_DONE = 100;
1192
1193
/**
1194
 * create a new wallet
1195
 *   - will generate a new primary seed and backup seed
1196
 *
1197
 * Either takes two argument:
1198
 * @param options       object      {}
1199
 * @param [cb]          function    callback(err, wallet, primaryMnemonic, backupMnemonic, blocktrailPubKeys) // nocommit @TODO
1200
 *
1201
 * For v1 wallets (explicitly specify options.walletVersion=v1):
1202
 * @param options       object      {}
1203
 * @param [cb]          function    callback(err, wallet, primaryMnemonic, backupMnemonic, blocktrailPubKeys)
1204
 *
1205
 * Or takes four arguments (old, deprecated syntax):
1206
 * @param identifier    string      the wallet identifier to be initialized
1207
 * @param passphrase    string      the password to decrypt the mnemonic with
1208
 * @param keyIndex      int         override for the blocktrail cosign key to use (for development purposes)
1209
 * @param [cb]          function    callback(err, wallet, primaryMnemonic, backupMnemonic, blocktrailPubKeys)
1210
 * @returns {q.Promise}
1211
 */
1212
APIClient.prototype.createNewWallet = function(options, cb) {
1213
    /* jshint -W071, -W074 */
1214
1215
    var self = this;
1216
1217
    if (typeof options !== "object") {
1218
        // get the old-style arguments
1219
        var identifier = arguments[0];
1220
        var passphrase = arguments[1];
1221
        var keyIndex = arguments[2];
1222
        cb = arguments[3];
1223
1224
        // keyIndex is optional
1225
        if (typeof keyIndex === "function") {
1226
            cb = keyIndex;
1227
            keyIndex = null;
1228
        }
1229
1230
        options = {
1231
            identifier: identifier,
1232
            passphrase: passphrase,
1233
            keyIndex: keyIndex
1234
        };
1235
    }
1236
1237
    // default to v3
1238
    options.walletVersion = options.walletVersion || Wallet.WALLET_VERSION_V3;
1239
1240
    var deferred = q.defer();
1241
    deferred.promise.spreadNodeify(cb);
1242
1243
    q.nextTick(function() {
1244
        deferred.notify(APIClient.CREATE_WALLET_PROGRESS_START);
1245
1246
        options.keyIndex = options.keyIndex || 0;
1247
        options.passphrase = options.passphrase || options.password;
1248
        delete options.password;
1249
1250
        if (!options.identifier) {
1251
            deferred.reject(new blocktrail.WalletCreateError("Identifier is required"));
1252
            return deferred.promise;
1253
        }
1254
1255
        if (options.walletVersion === Wallet.WALLET_VERSION_V1) {
1256
            self._createNewWalletV1(options)
1257
                .progress(function(p) { deferred.notify(p); })
1258
                .then(function(r) { deferred.resolve(r); }, function(e) { deferred.reject(e); })
1259
            ;
1260
        } else if (options.walletVersion === Wallet.WALLET_VERSION_V2) {
1261
            self._createNewWalletV2(options)
1262
                .progress(function(p) { deferred.notify(p); })
1263
                .then(function(r) { deferred.resolve(r); }, function(e) { deferred.reject(e); })
1264
            ;
1265
        } else if (options.walletVersion === Wallet.WALLET_VERSION_V3) {
@@ 1264-1367 (lines=104) @@
1261
            self._createNewWalletV2(options)
1262
                .progress(function(p) { deferred.notify(p); })
1263
                .then(function(r) { deferred.resolve(r); }, function(e) { deferred.reject(e); })
1264
            ;
1265
        } else if (options.walletVersion === Wallet.WALLET_VERSION_V3) {
1266
            self._createNewWalletV3(options)
1267
                .progress(function(p) { deferred.notify(p); })
1268
                .then(function(r) { deferred.resolve(r); }, function(e) { deferred.reject(e); })
1269
            ;
1270
        } else {
1271
            deferred.reject(new blocktrail.WalletCreateError("Invalid wallet version!"));
1272
        }
1273
    });
1274
1275
    return deferred.promise;
1276
};
1277
1278
APIClient.prototype._createNewWalletV1 = function(options) {
1279
    var self = this;
1280
1281
    var deferred = q.defer();
1282
1283
    q.nextTick(function() {
1284
1285
        if (!options.primaryMnemonic && !options.primarySeed) {
1286
            if (!options.passphrase && !options.password) {
1287
                deferred.reject(new blocktrail.WalletCreateError("Can't generate Primary Mnemonic without a passphrase"));
1288
                return deferred.promise;
1289
            } else {
1290
                options.primaryMnemonic = bip39.generateMnemonic(Wallet.WALLET_ENTROPY_BITS);
1291
                if (options.storePrimaryMnemonic !== false) {
1292
                    options.storePrimaryMnemonic = true;
1293
                }
1294
            }
1295
        }
1296
1297
        if (!options.backupMnemonic && !options.backupPublicKey) {
1298
            options.backupMnemonic = bip39.generateMnemonic(Wallet.WALLET_ENTROPY_BITS);
1299
        }
1300
1301
        deferred.notify(APIClient.CREATE_WALLET_PROGRESS_PRIMARY);
1302
1303
        self.resolvePrimaryPrivateKeyFromOptions(options)
1304
            .then(function(options) {
1305
                deferred.notify(APIClient.CREATE_WALLET_PROGRESS_BACKUP);
1306
1307
                return self.resolveBackupPublicKeyFromOptions(options)
1308
                    .then(function(options) {
1309
                        deferred.notify(APIClient.CREATE_WALLET_PROGRESS_SUBMIT);
1310
1311
                        // create a checksum of our private key which we'll later use to verify we used the right password
1312
                        var pubKeyHash = bitcoin.crypto.hash160(options.primaryPrivateKey.getPublicKeyBuffer());
1313
                        var checksum = bitcoin.address.toBase58Check(pubKeyHash, self.network.pubKeyHash);
1314
                        var keyIndex = options.keyIndex;
1315
1316
                        var primaryPublicKey = options.primaryPrivateKey.deriveHardened(keyIndex).neutered();
1317
1318
                        // send the public keys to the server to store them
1319
                        //  and the mnemonic, which is safe because it's useless without the password
1320
                        return self.storeNewWalletV1(
1321
                            options.identifier,
1322
                            [primaryPublicKey.toBase58(), "M/" + keyIndex + "'"],
1323
                            [options.backupPublicKey.toBase58(), "M"],
1324
                            options.storePrimaryMnemonic ? options.primaryMnemonic : false,
1325
                            checksum,
1326
                            keyIndex,
1327
                            options.segwit || null
1328
                        )
1329
                            .then(function(result) {
1330
                                deferred.notify(APIClient.CREATE_WALLET_PROGRESS_INIT);
1331
1332
                                var blocktrailPublicKeys = _.mapValues(result.blocktrail_public_keys, function(blocktrailPublicKey) {
1333
                                    return bitcoin.HDNode.fromBase58(blocktrailPublicKey[0], self.network);
1334
                                });
1335
1336
                                var wallet = new Wallet(
1337
                                    self,
1338
                                    options.identifier,
1339
                                    Wallet.WALLET_VERSION_V1,
1340
                                    options.primaryMnemonic,
1341
                                    null,
1342
                                    null,
1343
                                    {keyIndex: primaryPublicKey},
1344
                                    options.backupPublicKey,
1345
                                    blocktrailPublicKeys,
1346
                                    keyIndex,
1347
                                    result.segwit || 0,
1348
                                    self.testnet,
1349
                                    checksum,
1350
                                    result.upgrade_key_index,
1351
                                    options.useCashAddress,
1352
                                    options.bypassNewAddressCheck
1353
                                );
1354
1355
                                return wallet.unlock({
1356
                                    walletVersion: Wallet.WALLET_VERSION_V1,
1357
                                    passphrase: options.passphrase,
1358
                                    primarySeed: options.primarySeed,
1359
                                    primaryMnemonic: null // explicit null
1360
                                }).then(function() {
1361
                                    deferred.notify(APIClient.CREATE_WALLET_PROGRESS_DONE);
1362
                                    return [
1363
                                        wallet,
1364
                                        {
1365
                                            walletVersion: wallet.walletVersion,
1366
                                            primaryMnemonic: options.primaryMnemonic,
1367
                                            backupMnemonic: options.backupMnemonic,
1368
                                            blocktrailPublicKeys: blocktrailPublicKeys
1369
                                        }
1370
                                    ];