Skip to content

Release v3.0.0 (#32) - #33

Merged
ManulParihar merged 1 commit into
mainfrom
release-v3
Sep 2, 2026
Merged

ManulParihar merged 1 commit into
mainfrom
release-v3

Conversation

@ManulParihar

@ManulParihar ManulParihar commented Sep 2, 2026 •

Copy link
Copy Markdown
Member

Kokio SDK v3.0.0

TL;DR

The protocol moved off ETH purchases and off wei pricing, and Base Sepolia was
redeployed. Every address in v2.1.0 is stale and buyDataBundle no longer exists
on chain, so v2.1.0 cannot encode a single purchase call. This brings the SDK back
in line: prices are USD cents, purchases go through an ERC-20 path, and there is a
new paymentAdapter surface on both exports.

Breaking on both . and ./admin. 15 commits, 63 files, 398 tests green.

What changed

  1. Prices are USD cents, not wei. 123456 reads as $1234.56. The field is a
    uint64 on chain, still a bigint in TypeScript.

    v2.1.0 v3.0.0
    eSIMWallet.dataBundlePriceCap() eSIMWallet.priceCapUSDCents()
    eSIMWallet.setDataBundlePriceCap(cap) eSIMWallet.setPriceCapUSDCents(cap)
    registry.defaultDataBundlePriceCap() registry.defaultPriceCapUSDCents()
    registry.setDefaultDataBundlePriceCap(cap) registry.setDefaultPriceCapUSDCents(cap)
    protocolAdmin.setDefaultDataBundlePriceCapCall(cap) protocolAdmin.setDefaultPriceCapUSDCentsCall(cap)

    The "no ceiling" fallback still answers maxUint256, not zero.

  2. DataBundleDetails changed shape. viem encodes structs by exact key, so this
    is a hard break for every caller:

    { dataBundleID: string, dataBundlePrice: bigint } becomes
    { id: Hex, priceUSDCents: bigint, settlement: Settlement }.

    Settlement is a new exported enum: DeviceWallet (0), ExternalWallet (1),
    Fiat (2). It says which contract, if any, actually saw the money move.

  3. Purchases take a token, not ETH.

    v2.1.0 v3.0.0
    eSIMWallet.buyDataBundle(details, value) eSIMWallet.buyDataBundleWithToken(details, asset, maxAmountIn, paymentReference)
    deviceWallet.toggleAccessToETH(esim, on) deviceWallet.toggleAccessToFunds(esim, on)
    deviceWallet.canPullETH(esim) deviceWallet.canPullFunds(esim)
    n/a eSIMWallet.sendTokenToDeviceWallet(token, amount)

    maxAmountIn is in the token's own smallest unit. Take it from
    paymentAdapter.quote(asset, priceUSDCents). Do not compute it from a price and an
    assumed decimals count. paymentReference is an offchain order id, spendable once
    per eSIM wallet.

    ETH itself did not leave the protocol. sendETHToDeviceWallet and the factory
    deposit path are untouched. Only the purchase path moved to tokens.

  4. New paymentAdapter surface, on both Kokio and KokioAdmin.

    Reads: quote, resolveAsset, assets, settlementToken, registry,
    usedReferences, upgradeManager. Owner writes on the admin side: registerAsset,
    updateAsset, acceptOwnership. The adapter is owned by the timelock, so
    protocolAdmin gained setPaymentAdapterCall plus ownership and upgrade payload
    coverage for it. New exported Asset type mirrors the on-chain struct.

  5. Purchases paid for outside the protocol. registry.recordSettledPurchase on the
    admin surface records a card or external-wallet payment. No money moves through it,
    and it refuses Settlement.DeviceWallet. Comes with registry.paymentAdapter,
    registry.usedPaymentReferences and registry.requireLazyHistoryCopied.

  6. Lazy history ordering. lazyWalletRegistry.outstandingHistoryEntries(eSIMIdentifier)
    tells you whether a purchase would land ahead of history that has not been copied in
    yet. batchPopulateHistory callers must now set settlement to ExternalWallet or
    Fiat; DeviceWallet reverts.

  7. Base Sepolia addresses. All six moved, plus a new PAYMENT_ADAPTER key.

    Key Address
    DEVICE_WALLET_FACTORY 0x0BB3BA8D9233514a4aA6D72c243a2473f9cFf0bb
    ESIM_WALLET_FACTORY 0x57da54e07705de17c713ec311ac193e83470D5a5
    LAZY_WALLET_REGISTRY 0x5bE46Cf216186Bc2E3C220729331D6bE7d186e84
    REGISTRY 0x916b6b554119c789EF3026EDeB0E1Ba741b42A49
    P256VERIFIER 0x6FA3E7E145476Dc4682734Fd845019A3872b4821
    PROTOCOL_ADMIN 0xdDeCC2C1345BC966337B5f4Fe57EC2D5bfad751A
    PAYMENT_ADAPTER 0xBFaA666a8074924588E96507c307b680ecCeB2c1

    ENTRY_POINT and SENDER_CREATOR did not move. The counterfactual address
    derivation is unaffected: the beacon proxy creation code hash is unchanged, so
    createSmartAccount keeps its existing pin.

  8. Chain list trimmed to Base and Base Sepolia. Mainnet, Sepolia, Optimism,
    Optimism Sepolia, Arbitrum One and Arbitrum Sepolia were empty placeholder address
    books that could only ever be rejected. Base Mainnet stays as a placeholder because
    the protocol does ship there next. Callers passing any of the six removed chain ids
    now get a type error instead of a runtime rejection.

  9. All 10 ABIs regenerated against the current contracts, plus a new
    PaymentAdapter ABI. Two event names were corrected on chain and are now correct
    here: UpdatedDeviceWalletAssociatedWithESIMWallet and ESIMWalletFactoryDeployed.
    Anything indexing the old spellings goes silent rather than erroring.

  10. Revert decoding covers the new and renamed errors, including
    AssetNotAllowed, AssetNeedsSwap, PaymentReferenceAlreadyUsed,
    SettlementNotFunded, SettlementNotAsserted and HistoryNotFullyCopied.

  11. Docs updated across every page, with two new ones:
    docs/mobile/payment-adapter.md and docs/admin/payment-adapter.md.

Migrating

  1. Bump to 3.0.0.
  2. Rewrite every DataBundleDetails literal to { id, priceUSDCents, settlement },
    with id as a bytes32 hex string.
  3. Convert prices from wei to USD cents.
  4. Replace buyDataBundle with buyDataBundleWithToken, sourcing maxAmountIn
    from paymentAdapter.quote and paymentReference from your order system.
  5. Rename toggleAccessToETH and canPullETH to the Funds spellings, and the
    four price-cap methods per the table above.

Verification

  • npm run build clean.
  • npm test: 398 passing across 13 files.
  • Every Base Sepolia address checked with cast code and a name-revealing view
    before it was written into constants.ts.

A merge commit doesn't carry the "Release" text from a squashed
branch commit, so the publish workflow silently skipped v3.0.0.
Now it fires on any PR to main merged with a Release label, and
runs the test suite before publishing.
@ManulParihar
ManulParihar merged commit 3467501 into main Sep 2, 2026
@ManulParihar
ManulParihar deleted the release-v3 branch September 2, 2026 12:06
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