Skip to content

Fix resumed lazy deploys missing eSIMs, and add a large lazy-history user flow test - #41

Merged
ManulParihar merged 10 commits into
mainfrom
test/lazy-wallet-history
Sep 25, 2026
Merged

ManulParihar merged 10 commits into
mainfrom
test/lazy-wallet-history

Conversation

@ManulParihar

Copy link
Copy Markdown
Member

What this does

Two things:

  1. Bug fix. When the backend's lazy deploy was interrupted and then resumed, the SDK returned only the eSIM wallets from the resumed call, not the whole device. A backend that copies history from that result then skipped the eSIMs deployed before the interruption, and every later purchase on those eSIMs reverted with HistoryNotFullyCopied.
  2. New test. A fork test for a user with a large purchase history who signs up late. It covers the whole path: record the history, deploy the wallets, copy the history, then keep using the app, including moving eSIMs to a new phone.

The bug

admin.lazyWalletRegistry.deployLazyWalletAndSetESIMIdentifier deploys a device wallet and all its eSIM wallets, in several transactions when needed. If a run stops partway, for example after an RPC timeout or a crash, calling it again picks up where it left off.

Before this change, the resumed call's eSIMWallets and eSIMIdentifiers only listed what that call deployed:

  • Interrupted after the first batch: the result listed only the later batches.
  • Interrupted after everything landed: the result was an empty list with alreadyComplete: true.

Kokio-BFF's deployment job stores this result and uses it to copy each eSIM's history and to save the wallet addresses. Nothing else rebuilds the list. On a fork, a 12 eSIM device resumed after its first batch returned 2 identifiers, and 10 eSIMs were left with their history never copied.

The fix

  • eSIMWallets and eSIMIdentifiers now always list every eSIM wallet the device has, in deploy order. On a resume, the earlier ones are read back from the lazy registry.
  • batches still lists only the transactions this call sent.
  • A fresh deploy makes no extra reads.

Kokio-BFF needs no code change. It gets the fix when it upgrades to 3.2.1 (it pins 3.1.0 today).

New test: a user with 88 purchases signs up

tests/consumer/lazyWalletDeploy.fork.test.ts, on a Base Sepolia fork with a local bundler and paymaster:

  1. The backend records 88 card and external wallet purchases across 20 eSIMs before the user has a wallet. Two eSIMs have 26 purchases each, more than the default copy batch of 25, and the rest have 1 to 3.
  2. The app's passkey resolves to the address the backend will deploy.
  3. The backend deploys the device wallet and all 20 eSIM wallets in 2 transactions.
  4. A new purchase is refused until the history is copied.
  5. The backend copies each eSIM's history. The two large ones take 2 transactions each.
  6. Every eSIM wallet holds exactly its own purchases, in order.
  7. Running the deploy and the copy again sends nothing and still lists all 20 wallets.
  8. The user buys a bundle from the app, and it lands after the copied history.
  9. The user buys 2 more eSIMs.
  10. The user sets up a new phone.
  11. The eSIM with the longest lazy history, plus one new eSIM, move to the new phone with their history intact.
  12. The new phone can buy on them. The old phone is refused.

Each step logs the transactions it sends and the eSIMs and bundles it adds or moves. To see the logs:

npm run build && INTEGRATION=1 npx vitest run tests/consumer/lazyWalletDeploy.fork.test.ts --no-file-parallelism --reporter=verbose

Purchases in this flow pay in USDCt, the settlement token on Base Sepolia.

Other changes

  • The fork setup shared by the user flow tests moved into tests/consumer/fixtures/forkFlowTarget.ts.
  • New fork integration test: a deploy interrupted after its first batch, then resumed, lists the whole device, and copying from the result clears every eSIM's history.
  • Unit tests updated for the resume and already-complete cases. The mock client can now answer per-index reads.
  • Docs: docs/admin/lazy-wallet-registry.md and the LazyDeployment type describe the new result.
  • tests/README.md describes the new flow.

Compatibility

deployLazyWalletAndSetESIMIdentifier now returns more entries on a resume than before. Any caller that relied on it returning only newly deployed wallets should read batches instead. Kokio-BFF is the only known caller, and it needs the full list.

Tests

  • Unit tests: 438 passed
  • Fork integration tests: 28 passed
  • Fork consumer tests: 44 passed
  • The live Base Sepolia run was not repeated.

Version

3.2.0 to 3.2.1

…device

One of the moved eSIMs is the lazy one with the longest history, which must
travel with it intact.
Each step prints the transactions it sends and the eSIMs and bundles they add
or move. USDCt is the settlement token on Base Sepolia.
A resumed deploy returned only the wallets from its own batches, and an empty
list when everything had already landed. A caller copying history from the
result then skipped the eSIMs an earlier call deployed, leaving their
purchases blocked. The wallets from earlier calls are now read back from the
lazy registry. batches still holds only what this call sent.
@ManulParihar
ManulParihar merged commit 23bf30b into main Sep 25, 2026
@ManulParihar
ManulParihar deleted the test/lazy-wallet-history branch September 25, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant