Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

- fixed: Allow duplicate sync keys when performing a wallet split, in case a previous failed attempt left a repo behind.
- fixed: Do not lose wallet import history when doing a split-archive-split.

## 2.38.3 (2026-01-06)

- added: Added `change2.edge.app` server to default change server list.
Expand Down
1 change: 1 addition & 0 deletions src/core/fake/fake-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ function createLogin(request: ApiRequest, login?: DbLogin): HttpResponse {

// Set up repos:
const keys = asMaybe(asCreateKeysPayload, () => ({
allowExisting: false,
newSyncKeys: [],
keyBoxes: []
}))(body.data)
Expand Down
8 changes: 6 additions & 2 deletions src/core/login/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ export function makeKeyInfo(

/**
* Assembles all the resources needed to attach new keys to the account.
* @param allowExisting True if the sync keys were derived deterministically,
* which implies that duplicate sync keys on the server are not errors,
* but leftovers from an earlier failed splitting attempt.
*/
export function makeKeysKit(
ai: ApiInput,
sessionKey: SessionKey,
keyInfos: EdgeWalletInfo[]
keyInfos: EdgeWalletInfo[],
allowExisting: boolean = false
): LoginKit {
// For crash errors:
ai.props.log.breadcrumb('makeKeysKit', {})
Expand All @@ -95,7 +99,7 @@ export function makeKeysKit(

return {
loginId: sessionKey.loginId,
server: wasCreateKeysPayload({ keyBoxes, newSyncKeys }),
server: wasCreateKeysPayload({ allowExisting, keyBoxes, newSyncKeys }),
serverPath: '/v2/login/keys',
stash: { keyBoxes }
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/login/splitting.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a changelog entry for this fix as well. The current changelog only mentions the duplicate sync keys fix but not the preservation of migratedFromWalletId during wallet re-split.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export async function splitWalletInfo(
walletInfos[newWalletInfo.id] = {
archived: false,
deleted: false,
migratedFromWalletId: undefined
migratedFromWalletId: existingWalletInfo.migratedFromWalletId
}
await changeWalletStates(ai, accountId, walletInfos)
return newWalletInfo.id
Expand All @@ -157,7 +157,7 @@ export async function splitWalletInfo(
}

// Add the keys to the login:
const kit = makeKeysKit(ai, sessionKey, [newWalletInfo])
const kit = makeKeysKit(ai, sessionKey, [newWalletInfo], true)
await applyKit(ai, sessionKey, kit)

// Try to copy metadata on a best-effort basis.
Expand Down
1 change: 1 addition & 0 deletions src/types/server-cleaners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ export const asChangeVouchersPayload: Cleaner<ChangeVouchersPayload> = asObject(
)

export const asCreateKeysPayload: Cleaner<CreateKeysPayload> = asObject({
allowExisting: asOptional(asBoolean, false),
keyBoxes: asArray(asEdgeBox),
newSyncKeys: asOptional(asArray(asString), () => [])
})
Expand Down
1 change: 1 addition & 0 deletions src/types/server-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export interface ChangeVouchersPayload {
}

export interface CreateKeysPayload {
allowExisting: boolean
keyBoxes: EdgeBox[]
newSyncKeys: string[]
}
Expand Down
Loading