Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
abe645d
feat!: add Tron support and replace walletAddress with activeWallet
tolgahan-arikan Oct 8, 2026
ac21282
feat(app): add a Tron Nile panel to the sample app
tolgahan-arikan Oct 8, 2026
411b658
fix(deps): upgrade CBOR Java to 4.5.6 for CVE-2024-23684
tolgahan-arikan Oct 8, 2026
f0b20d4
refactor!: align public API with the TypeScript and Swift SDKs
tolgahan-arikan Oct 8, 2026
a21b0f5
feat(app): add Solana to the sample app
tolgahan-arikan Oct 8, 2026
95131d6
docs: describe Tron balance fields and page equality changes
tolgahan-arikan Oct 8, 2026
2bf1bd0
Merge remote-tracking branch 'origin/master' into add-tron-support
tolgahan-arikan Oct 8, 2026
d6dd695
fix: reject an empty walletAddress in signature verification
tolgahan-arikan Oct 8, 2026
df865f3
fix: drop the isEthereumAddressValue alias and hide isEthereumHexAddr…
tolgahan-arikan Oct 8, 2026
ac97d8e
fix(docs): note that wallet is the first OMSWalletSessionExpiredEvent…
tolgahan-arikan Oct 8, 2026
a9ca796
fix(app): guard the Tron panel against double taps and show Nile inde…
tolgahan-arikan Oct 8, 2026
a9afdc8
refactor: share Solana and Tron fee-balance enrichment
tolgahan-arikan Oct 8, 2026
768bdd4
refactor: remove dead SDK internals and small duplications
tolgahan-arikan Oct 8, 2026
1abe4e5
chore(build): share the javap runner and drop dead POM fallbacks
tolgahan-arikan Oct 8, 2026
8ad7e0c
test: remove the unused googleIdTokenSessionAuth helper
tolgahan-arikan Oct 8, 2026
5e0b41b
refactor(app): simplify the email code and session lifetime handlers
tolgahan-arikan Oct 8, 2026
1af6d9b
build: dump the public API with binary-compatibility-validator
tolgahan-arikan Oct 9, 2026
0e33c79
build: drop uncallable synthetic bridges from the public API dump
tolgahan-arikan Oct 9, 2026
6c42feb
refactor!: remove backward-compatibility leftovers
tolgahan-arikan Oct 9, 2026
40d969d
fix(app): show the WaaS transaction ID separately from on-chain hashes
tolgahan-arikan Oct 9, 2026
b8308af
docs: correct Tron, migration, and sample app details
tolgahan-arikan Oct 9, 2026
2121a09
feat(app): add a mainnet switch to the Solana and Tron panels
tolgahan-arikan Oct 15, 2026
1261725
Merge remote-tracking branch 'origin/master' into add-tron-support
tolgahan-arikan Oct 15, 2026
ac2d5bf
Merge remote-tracking branch 'origin/master' into add-tron-support
tolgahan-arikan Oct 16, 2026
62025dc
test: cover exact Solana, signing, access, and indexer request bodies
tolgahan-arikan Oct 16, 2026
32f632e
test: tighten weak tests
tolgahan-arikan Oct 16, 2026
119c7f5
test: remove duplicate and low-value tests
tolgahan-arikan Oct 16, 2026
836b099
test: share test fixtures
tolgahan-arikan Oct 16, 2026
35dc006
fix: accept real AWS Nitro attestation documents
tolgahan-arikan Oct 16, 2026
1665a75
Merge remote-tracking branch 'origin/master' into add-tron-support
tolgahan-arikan Oct 16, 2026
cc42c0a
docs: fix stale testing and error-contract references
tolgahan-arikan Oct 19, 2026
125e5c0
test: cover wallet response networkFamily and keyOrigin validation
tolgahan-arikan Oct 19, 2026
54d43d8
test: remove assertions that cannot fail
tolgahan-arikan Oct 19, 2026
9e1c072
chore(release): prepare 0.4.0
tolgahan-arikan Oct 19, 2026
ae1c540
chore(waas): regenerate client from waas 54d91262
tolgahan-arikan Oct 23, 2026
c80cf7e
feat(session): refresh the sliding credential expiry
tolgahan-arikan Oct 23, 2026
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
19 changes: 14 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ current-stable and supported-minimum Expo compatibility.
- Verify `docs/api.md` is current and every public symbol is grouped.
- `./gradlew :oms-wallet-kotlin-sdk:checkPublicApiBaseline`
- Compare the public API against `oms-wallet-kotlin-sdk/api/public-api.txt`.
`dumpPublicApi` in the same module regenerates the baseline.
`dumpPublicApi` in the same module regenerates the baseline. The dump uses the
binary-compatibility-validator library, so `internal` and synthetic declarations are excluded,
and it fails if it mentions a non-public SDK type or its top-level declarations differ from
`docs/api.md`; run `generateApiDocs`
first when the public API changes.
- `./gradlew :oms-wallet-kotlin-sdk:checkReleaseArtifactBoundary`
- Check that the release AAR excludes generated WaaS bytecode and Java-callable
implementation details.
Expand Down Expand Up @@ -192,9 +196,9 @@ result.
`https://github.com/0xsequence/waas` project; update this generated client
from upstream as needed.
- `WalletClient.kt`, `WalletRequestSigner.kt`, `WalletAuthChallenge.kt`,
`AndroidKeystoreP256CredentialSigner.kt`, and `AndroidKeystoreSessionStore.kt`
handle auth state, credentials, nonces, signing, and persisted sessions. Treat
behavior changes here as security-sensitive and add regression tests.
`AndroidKeystoreP256CredentialSigner.kt`, `AndroidSessionMetadataStore.kt`, and
`PersistedSessionRecord.kt` handle auth state, credentials, nonces, signing, and
persisted sessions. Treat behavior changes here as security-sensitive and add regression tests.
- Wallet auth, signing, access, session, and transaction tests live under
`oms-wallet-kotlin-sdk/src/test/java/technology/polygon/omswallet/wallet/`. Add
narrowly scoped tests near the behavior being changed instead of broad setup
Expand Down Expand Up @@ -266,7 +270,12 @@ and the execution command reference.
- `oms-wallet-kotlin-sdk/src/main/java/technology/polygon/omswallet/internal/generated/waas/WaasWalletClient.kt`
is generated by `webrpc-gen` from the upstream `0xsequence/waas` project.
Treat that upstream repository as the source of truth and update the generated
client here only when the SDK needs a WaaS API refresh.
client here only when the SDK needs a WaaS API refresh. To refresh it, copy
upstream `proto/clients/waas.gen.kt` (webrpc's built-in `kotlin` target) and
replace its `io.sequence.waas` package with
`technology.polygon.omswallet.internal.generated.waas`; the file header keeps
the schema version and generation command. Keep the hand-built `Webrpc`
header value in `WalletClient.kt` in step with that header.
- `build/`, `*/build/`, `.gradle/`, `.gradle-user/`, `.npm-cache/`,
`.android-user/`, `.kotlin/`, `.idea/`, `.codex/`, and `local.properties` are
ignored local artifacts.
Expand Down
234 changes: 234 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,240 @@
This document records breaking changes and the steps to migrate between published
versions of `io.github.0xsequence:oms-wallet-kotlin-sdk`.

## 0.4.0

### Active wallet replaces `walletAddress`

`omsWallet.wallet.walletAddress` was removed. Read the active wallet from
`omsWallet.wallet.activeWallet`, which is a `Wallet` (`id`, `type`, `address`, `reference`,
`keyOrigin`) or `null` when signed out. Branch on `type` before passing the address to
family-specific code:

```kotlin
// 0.3.x
val address = omsWallet.wallet.walletAddress

// 0.4.0
val activeWallet = omsWallet.wallet.activeWallet
if (activeWallet?.type == WalletType.Ethereum) {
val ethereumAddress = activeWallet.address
}
```

The `walletAddress` property was also removed from `WalletActivationResult` (formerly
`WalletSelectionResult`) and `CompleteAuthResult.WalletSelected`. Use `result.wallet.address`. Code that creates or
destructures these data classes positionally must drop the removed first component.

### `session` is null when signed out

`OMSWalletSessionState` was renamed to `OMSWalletSession`, and `omsWallet.wallet.session` is now
`OMSWalletSession?`. Previously it returned an object whose fields were all `null` when signed
out. The `walletAddress` property was removed, and `expiresAt` and `auth` are now non-null.
`session` is non-null exactly when `activeWallet` is.

```kotlin
// 0.3.x
val email = omsWallet.wallet.session.auth?.email

// 0.4.0
val email = omsWallet.wallet.session?.auth?.email
```

`OMSWalletSessionExpiredEvent` gained `wallet: Wallet?`, and its `session` is an
`OMSWalletSession` without `walletAddress`. `wallet` is `null` when the credential expired while a
manual wallet selection was still pending. `wallet` is the first constructor property, so code that
creates or destructures the event positionally must account for it; prefer named arguments.

### Sliding session expiry

The wallet API now extends a session's expiry with use, up to the requested lifetime, and
`WalletClient.MAX_SESSION_LIFETIME_SECONDS` rose from 30 days (`2_592_000`) to 180 days
(`15_552_000`); the default lifetime is unchanged. `OMSWalletSession.expiresAt` and
`WalletCredential.expiresAt` are the current expiry, which the SDK refreshes, so do not cache them
as a fixed end time. A session also ends with `OMS_SESSION_EXPIRED` (and an `onSessionExpired`
event) when the wallet API reports its credential expired or unknown.

### One-time sign-in after upgrading

Saved sessions now record the full active wallet, including its type. Sessions saved by 0.3.x do
not, so 0.4.0 discards them on load and users sign in once after upgrading.

### Contract method names

`callContract` (and the new `callTronContract`) now require `method` to be a bare function name
such as `"transfer"`. The wallet service builds the signature from the `args` types and never
accepted full signatures; the SDK now rejects values such as `"transfer(address,uint256)"` with
`OMSWalletValidationException` before sending a request.

```kotlin
// 0.3.x
omsWallet.wallet.callContract(network, contract, method = "transfer(address,uint256)", args = args)

// 0.4.0
omsWallet.wallet.callContract(network, contractAddress, method = "transfer", args = args)
```

The contract parameter of `callContract` and `callTronContract` is now named `contractAddress`.
Positional calls are unchanged; update named arguments:

```kotlin
// 0.3.x
omsWallet.wallet.callContract(network = network, contract = token, method = "transfer", args = args)

// 0.4.0
omsWallet.wallet.callContract(network = network, contractAddress = token, method = "transfer", args = args)
```

### Signature verification targets a wallet address

Every verification method (`isValidMessageSignature`, `isValidTypedDataSignature`,
`isValidSolanaMessageSignature`, `isValidTronMessageSignature`, `isValidTronTypedDataSignature`)
takes an optional trailing `walletAddress` and no `walletId`. The SDK always sends `networkFamily`
and `walletAddress` to the wallet service and never sends `walletId`; `isValidTypedDataSignature`
now also sends `networkFamily = "evm"`.

- Passing `walletAddress` verifies any wallet and no longer requires a session, so the EVM and
Solana methods now work while signed out.
- Omitting `walletAddress` uses the active wallet's address. Without a session the methods still
throw `OMSWalletSessionException`. When the active wallet belongs to another family (for example
an active Ethereum wallet for `isValidSolanaMessageSignature`, or an active Tron wallet for
`isValidTypedDataSignature`), they now throw `OMSWalletValidationException` before any request.
Previously such calls reached the wallet service, which rejected them with an
`OMSWalletRequestException`.
- A given but empty or whitespace-only `walletAddress` throws `OMSWalletValidationException`
(`walletAddress must not be empty`) before any request. Omit `walletAddress` to verify against
the active wallet.

```kotlin
// 0.3.x: always the active wallet, which had to be signed in
omsWallet.wallet.isValidMessageSignature(network, message, signature)

// 0.4.0: the active wallet (unchanged call), or any Ethereum wallet, even while signed out
omsWallet.wallet.isValidMessageSignature(network, message, signature)
omsWallet.wallet.isValidMessageSignature(network, message, signature, walletAddress = "0x…")
```

### Renamed types

| 0.3.x | 0.4.0 |
|---|---|
| `WalletSelectionResult` | `WalletActivationResult` |
| `TokenBalancesResult` | `BalancesResult` |
| `OidcRedirectAuthMode` | `OidcAuthMode` (wire values `auth-code`/`auth-code-pkce` are unchanged, so pending redirects saved by 0.3.x still load) |

```kotlin
// 0.3.x
val result: WalletSelectionResult = omsWallet.wallet.useWallet(walletId)
val balances: TokenBalancesResult = omsWallet.indexer.getBalances(walletAddress)

// 0.4.0
val result: WalletActivationResult = omsWallet.wallet.useWallet(walletId)
val balances: BalancesResult = omsWallet.indexer.getBalances(walletAddress)
```

### Transaction status polling options

`TransactionStatusPollingOptions` properties were renamed to match the TypeScript and Swift SDKs.
The defaults (`400`, `5`, `2_000`, `60_000` milliseconds/polls), the constructor order, and the
polling behavior are unchanged. Validation messages use the new names (for example
`"timeoutMs must not be negative"`).

| 0.3.x | 0.4.0 |
|---|---|
| `fastPollIntervalMillis` | `fastIntervalMs` |
| `fastPollCount` | `fastPollCount` |
| `pollIntervalMillis` | `intervalMs` |
| `timeoutMillis` | `timeoutMs` |

```kotlin
// 0.3.x
TransactionStatusPollingOptions(timeoutMillis = 120_000L, pollIntervalMillis = 3_000L)

// 0.4.0
TransactionStatusPollingOptions(timeoutMs = 120_000L, intervalMs = 3_000L)
```

### `sendTransaction(network, to, value)` takes `mode`

The `to`/`value` overload gained `mode: TransactionMode = TransactionMode.Relayer` before
`waitForStatus`, matching `callContract` and `sendSolanaTransfer`. Positional calls that passed
`waitForStatus` fourth must name it:

```kotlin
// 0.3.x
omsWallet.wallet.sendTransaction(network, to, value, false)

// 0.4.0
omsWallet.wallet.sendTransaction(network, to, value, waitForStatus = false)
omsWallet.wallet.sendTransaction(network, to, value, mode = TransactionMode.Native)
```

### OIDC parameter order

Parameters now follow the same order as the TypeScript and Swift SDKs. Defaults are unchanged and
named arguments are unaffected:

- `signInWithOidcIdToken(idToken, issuer, audience, walletType, walletSelection, sessionLifetimeSeconds, provider, providerLabel)`:
`walletType` now comes before `walletSelection`.
- `startOidcRedirectAuth(provider: CustomOidcProviderConfig, walletType, walletSelection, sessionLifetimeSeconds, loginHint, authorizeParams)`:
`loginHint` now comes before `authorizeParams`.

```kotlin
// 0.3.x
omsWallet.wallet.signInWithOidcIdToken(idToken, issuer, audience, WalletSelectionBehavior.Manual, WalletType.Solana)

// 0.4.0
omsWallet.wallet.signInWithOidcIdToken(idToken, issuer, audience, WalletType.Solana, WalletSelectionBehavior.Manual)
```

### Address-already-imported errors

Importing a key whose address is already imported (WaaS `AddressAlreadyImported`, code `7313`)
now throws `OMSWalletRequestException` with `code = OMSWalletErrorCode.WalletAddressAlreadyImported`
(`OMS_WALLET_ADDRESS_ALREADY_IMPORTED`), `status = 409`, and `retryable = false`. It previously
used `OMSWalletErrorCode.RequestFailed`:

```kotlin
// 0.3.x
catch (error: OMSWalletRequestException) {
if (error.code == OMSWalletErrorCode.RequestFailed && error.status == 409) showAlreadyImported()
}

// 0.4.0
catch (error: OMSWalletRequestException) {
if (error.code == OMSWalletErrorCode.WalletAddressAlreadyImported) showAlreadyImported()
}
```

### Indexer page cursors

`TokenBalancesPageRequest` and `TokenBalancesPage` gained trailing `column`, `before`, `after`, and
`sort` properties (`SortBy`, `SortOrder`). Omitted request fields are not sent. A page response
whose `sort` entries are malformed or use an order other than `DESC`/`ASC` now fails with
`OMSWalletResponseException` (`OMS_INVALID_RESPONSE`); previously the SDK ignored those fields.
Because these are data-class properties, `TokenBalancesPage` equality and `toString()` now include
them.

### Wallet responses

Ethereum wallet addresses returned by the wallet API must be `0x` followed by 40 hexadecimal
characters (checksum casing is not enforced). Other values fail with `OMSWalletResponseException`
(`OMS_INVALID_RESPONSE`). Wallet-family checks now use the wallet's stored type instead of the
address shape.

### Exhaustive `when` expressions

These public enums gained cases. Update exhaustive `when` expressions over them:

- `WalletType.Tron`
- `OMSWalletOperation.WalletSignTronMessage`, `WalletSignTronTypedData`,
`WalletIsValidTronMessageSignature`, `WalletIsValidTronTypedDataSignature`,
`WalletSendTronTransaction`, `WalletCallTronContract`, and `IndexerGetTronBalances`
- `OMSWalletErrorCode.WalletAddressAlreadyImported`

`WalletImportPrivateKey` also gained the `Tron` and `TronBytes` subtypes; exhaustive `when`
expressions over it need branches for them.

## 0.3.0

### Wallet types and key origin
Expand Down
Loading
Loading