Skip to content

Commit

Permalink
Add account-selection UI to ChooseAddress request
Browse files Browse the repository at this point in the history
It's user-friendlier for onboarding in the CPL dashboard, to select their account, and not their address. Also makes sense for other uses.

It's opt-in with the `ui: 2` request option.
  • Loading branch information
sisou committed Nov 23, 2023
1 parent af4fd07 commit 5cf5a7e
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 40 deletions.
1 change: 1 addition & 0 deletions client/PublicRequestTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export interface ChooseAddressRequest extends BasicRequest {
disableLegacyAccounts?: boolean;
disableBip39Accounts?: boolean;
disableLedgerAccounts?: boolean;
ui?: number;
}

export interface ChooseAddressResult extends Address {
Expand Down
4 changes: 2 additions & 2 deletions demos/Demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class Demo {

document.querySelector('button#choose-address').addEventListener('click', async () => {
try {
const result = await demo.client.chooseAddress({ appName: 'Hub Demos' }, demo._defaultBehavior);
const result = await demo.client.chooseAddress({ appName: 'Hub Demos', ui: 2 }, demo._defaultBehavior);
console.log('Result', result);
document.querySelector('#result').textContent = `Address was chosen: ${result ? result.address : '-'}`;
} catch (e) {
Expand All @@ -173,7 +173,7 @@ class Demo {

document.querySelector('button#choose-address-and-btc').addEventListener('click', async () => {
try {
const result = await demo.client.chooseAddress({ appName: 'Hub Demos', returnBtcAddress: true }, demo._defaultBehavior);
const result = await demo.client.chooseAddress({ appName: 'Hub Demos', returnBtcAddress: true, ui: 2 }, demo._defaultBehavior);
console.log('Result', result);
document.querySelector('#result').textContent = `Address was chosen: ${result ? result.address : '-'}`;
} catch (e) {
Expand Down
19 changes: 18 additions & 1 deletion src/i18n/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"

#: src/views/ChooseAddress.vue:14
msgid "{appName} is asking for an account to use."
msgstr ""

#: src/views/ChooseAddress.vue:7
msgid "{appName} is asking for an address to use."
msgstr ""
Expand Down Expand Up @@ -275,8 +279,13 @@ msgstr ""
msgid "Choose a new Address"
msgstr ""

#: src/views/ChooseAddress.vue:12
msgid "Choose an Account"
msgstr ""

#: src/views/CashlinkReceive.vue:64
#: src/views/ChooseAddress.vue:4
#: src/views/ChooseAddress.vue:18
#: src/views/ChooseAddress.vue:5
msgid "Choose an Address"
msgstr ""

Expand All @@ -302,6 +311,10 @@ msgstr ""
msgid "Choose Sender"
msgstr ""

#: src/views/ChooseAddress.vue:20
msgid "Choose which Nimiq address to use."
msgstr ""

#: src/views/CashlinkReceive.vue:297
msgid "Claim Cashlink"
msgstr ""
Expand Down Expand Up @@ -673,6 +686,10 @@ msgstr ""
msgid "Login File saved!"
msgstr ""

#: src/views/ChooseAddress.vue:67
msgid "Login to another account"
msgstr ""

#: src/views/CashlinkReceive.vue:91
msgid "Login to existing account"
msgstr ""
Expand Down
1 change: 1 addition & 0 deletions src/lib/RequestParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ export class RequestParser {
disableLegacyAccounts: !!chooseAddressRequest.disableLegacyAccounts,
disableBip39Accounts: !!chooseAddressRequest.disableBip39Accounts,
disableLedgerAccounts: !!chooseAddressRequest.disableLedgerAccounts,
ui: chooseAddressRequest.ui,
} as ParsedChooseAddressRequest;
case RequestType.SIGNUP:
case RequestType.LOGIN:
Expand Down
1 change: 1 addition & 0 deletions src/lib/RequestTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface ParsedChooseAddressRequest extends ParsedBasicRequest {
disableLegacyAccounts: boolean;
disableBip39Accounts: boolean;
disableLedgerAccounts: boolean;
ui?: number;
}

export interface ParsedSignTransactionRequest extends ParsedBasicRequest {
Expand Down
12 changes: 10 additions & 2 deletions src/lib/WalletInfoCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export default class WalletInfoCollector {
};
}

public static async detectBitcoinAddresses(xpub: string, startIndex = 0): Promise<{
public static async detectBitcoinAddresses(xpub: string, startIndex = 0, onlyUnusedExternal = Infinity): Promise<{
internal: BtcAddressInfo[],
external: BtcAddressInfo[],
}> {
Expand Down Expand Up @@ -147,7 +147,7 @@ export default class WalletInfoCollector {

const addresses: [BtcAddressInfo[], BtcAddressInfo[]] = [[], []];

for (const INDEX of [EXTERNAL_INDEX, INTERNAL_INDEX]) {
addressTypeLoop: for (const INDEX of [EXTERNAL_INDEX, INTERNAL_INDEX]) {
const baseKey = extendedKey.derive(INDEX);
const basePath = `${BTC_ACCOUNT_KEY_PATH[xPubType][Config.bitcoinNetwork]}/${INDEX}`;

Expand Down Expand Up @@ -178,6 +178,14 @@ export default class WalletInfoCollector {
balance,
));

if (INDEX === EXTERNAL_INDEX && !used) {
// Found an unused external address, reducing remaining counter
onlyUnusedExternal -= 1;

// When all found, break outer loop and return
if (onlyUnusedExternal <= 0) break addressTypeLoop;
}

if (used) {
gap = 0;
} else {
Expand Down
Loading

0 comments on commit 5cf5a7e

Please sign in to comment.