Skip to content

Commit

Permalink
wallet-http: modify account lookahead.
Browse files Browse the repository at this point in the history
  • Loading branch information
nodech committed May 30, 2023
1 parent 2664a7e commit d2da229
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 40 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -41,6 +41,8 @@ to these calls.

- HTTP Changes:
- Wallet and account create methods now accept `lookahead` values up to `2^32 - 1`.
- Create account is now: `POST /wallet/:id/account/:account` instead of `PUT /wallet/:id/account/:account`.
- Introduce new API to modify account: `PUT /wallet/:id/account/:account`. (old create)

- New RPC methods:
- `createbatch` and `sendbatch` create batch transactions with any number
Expand Down
18 changes: 18 additions & 0 deletions bin/hsw-cli
Expand Up @@ -21,6 +21,7 @@ const HELP = `
Commands:
$ abandon [hash]: Abandon a transaction.
$ account create [account-name]: Create account.
$ account modify [account-name]: Set account options.
$ account get [account-name]: Get account details.
$ account list: List account names.
$ address [account-name]: Derive new address.
Expand Down Expand Up @@ -233,6 +234,18 @@ class CLI {
this.log(account);
}

async modifyAccount() {
const name = this.config.str([0, 'name']);

const options = {
lookahead: this.config.uint('lookahead')
};

const account = await this.wallet.modifyAccount(name, options);

this.log(account);
}

async createAddress() {
const account = this.config.str([0, 'account']);
const addr = await this.wallet.createAddress(account);
Expand Down Expand Up @@ -579,6 +592,11 @@ class CLI {
await this.createAccount();
break;
}
if (this.argv[0] === 'modify') {
this.argv.shift();
await this.modifyAccount();
break;
}
if (this.argv[0] === 'get')
this.argv.shift();
await this.getAccount();
Expand Down
29 changes: 26 additions & 3 deletions lib/client/wallet.js
Expand Up @@ -682,6 +682,21 @@ class WalletClient extends Client {
*/

createAccount(id, name, options) {
if (name == null)
throw new Error('Account name is required.');

return this.post(`/wallet/${id}/account/${name}`, options);
}

/**
* Modify account.
* @param {String} id
* @param {String} name
* @param {Object} options
* @returns {Promise<Object>}
*/

modifyAccount(id, name, options) {
return this.put(`/wallet/${id}/account/${name}`, options);
}

Expand Down Expand Up @@ -1363,12 +1378,20 @@ class Wallet extends EventEmitter {
*/

createAccount(name, options) {
if (name == null)
throw new Error('Account name is required.');

return this.client.createAccount(this.id, name, options);
}

/**
* Modify account.
* @param {String} name
* @param {Object} options
* @returns {Promise<Object>}
*/

modifyAccount(name, options) {
return this.client.modifyAccount(this.id, name, options);
}

/**
* Create address.
* @param {Object} options
Expand Down
2 changes: 2 additions & 0 deletions lib/wallet/account.js
Expand Up @@ -563,6 +563,8 @@ class Account extends bio.Struct {
*/

async setLookahead(b, lookahead) {
assert((lookahead >>> 0) === lookahead, 'Lookahead must be a number.');

if (lookahead === this.lookahead)
return;

Expand Down
18 changes: 17 additions & 1 deletion lib/wallet/http.js
Expand Up @@ -337,7 +337,7 @@ class HTTP extends Server {
});

// Create account
this.put('/wallet/:id/account/:account', async (req, res) => {
this.post('/wallet/:id/account/:account', async (req, res) => {
const valid = Validator.fromRequest(req);
const passphrase = valid.str('passphrase');

Expand All @@ -362,6 +362,22 @@ class HTTP extends Server {
res.json(200, account.getJSON(balance));
});

// Modify account
this.put('/wallet/:id/account/:account', async (req, res) => {
const valid = Validator.fromRequest(req);
const passphrase = valid.str('passphrase');
const acct = valid.str('account');

const options = {
lookahead: valid.u32('lookahead')
};

const account = await req.wallet.modifyAccount(acct, options, passphrase);
const balance = await req.wallet.getBalance(account.accountIndex);

res.json(200, account.getJSON(balance));
});

// Change passphrase
this.post('/wallet/:id/passphrase', async (req, res) => {
const valid = Validator.fromRequest(req);
Expand Down
81 changes: 45 additions & 36 deletions lib/wallet/wallet.js
Expand Up @@ -659,6 +659,50 @@ class Wallet extends EventEmitter {
return account;
}

/**
* Modify an account. Requires passphrase if master key is encrypted.
* @param {String|Number} acct
* @param {Object} options
* @param {String} [passphrase]
* @returns {Promise<Account>}
*/

async modifyAccount(acct, options, passphrase) {
const unlock = await this.writeLock.lock();
try {
return await this._modifyAccount(acct, options, passphrase);
} finally {
unlock();
}
}

/**
* Create an account without a lock.
* @param {String|Number} acct
* @param {Object} options
* @param {String} [passphrase]
* @returns {Promise<Account>}
*/

async _modifyAccount(acct, options, passphrase) {
if (!await this.hasAccount(acct))
throw new Error(`Account ${acct} does not exist.`);

await this.unlock(passphrase);

const account = await this.getAccount(acct);
assert(account);

const b = this.db.batch();

if (options.lookahead != null)
await account.setLookahead(b, options.lookahead);

await b.write();

return account;
}

/**
* Ensure an account. Requires passphrase if master key is encrypted.
* @param {Object} options - See {@link Account} options.
Expand Down Expand Up @@ -714,7 +758,7 @@ class Wallet extends EventEmitter {
/**
* Retrieve an account from the database.
* @param {Number|String} acct
* @returns {Promise} - Returns {@link Account}.
* @returns {Promise<Account>}
*/

async getAccount(acct) {
Expand Down Expand Up @@ -4328,41 +4372,6 @@ class Wallet extends EventEmitter {
return paths;
}

/**
* Increase lookahead for account.
* @param {(Number|String)?} account
* @param {Number} lookahead
* @returns {Promise}
*/

async setLookahead(acct, lookahead) {
const unlock = await this.writeLock.lock();
try {
return this._setLookahead(acct, lookahead);
} finally {
unlock();
}
}

/**
* Increase lookahead for account (without a lock).
* @private
* @param {(Number|String)?} account
* @param {Number} lookahead
* @returns {Promise}
*/

async _setLookahead(acct, lookahead) {
const account = await this.getAccount(acct);

if (!account)
throw new Error('Account not found.');

const b = this.db.batch();
await account.setLookahead(b, lookahead);
await b.write();
}

/**
* Sync address depths based on a transaction's outputs.
* This is used for deriving new addresses when
Expand Down
13 changes: 13 additions & 0 deletions test/wallet-http-test.js
Expand Up @@ -124,6 +124,19 @@ describe('Wallet HTTP', function() {
assert.strictEqual(getNewAccount.lookahead, 1001);
});

it('should modify account lookahead to 1000', async () => {
const wname = 'lookahead2';
await wclient.createWallet(wname);

const defAccount = await wclient.getAccount(wname, 'default');
assert.strictEqual(defAccount.lookahead, 200);

const modified = await wclient.modifyAccount(wname, 'default', {
lookahead: 1000
});
assert.strictEqual(modified.lookahead, 1000);
});

it('should get key by address from watch-only', async () => {
const phrase = 'abandon abandon abandon abandon abandon abandon '
+ 'abandon abandon abandon abandon abandon about';
Expand Down

0 comments on commit d2da229

Please sign in to comment.