Smart account layer release preparation - #19
Merged
Conversation
Replace hardcoded AUTH_ENTRY_EXPIRATION_BUFFER with the user-configurable signatureExpirationLedgers in signing paths. The fundWallet path uses Util.LEDGERS_PER_HOUR directly as a testnet convenience method.
Improve nonce generation in the fundWallet testnet helper. Initialize SorobanServer eagerly in create() to eliminate an unsynchronized lazy init race condition.
Add multiSignerExecuteAndSubmit() for multi-signer authorization on arbitrary contract calls. Extract shared signing pipeline, add forceMethod support to multi-signer methods, and handle non-contract wallet auth entries.
…edger in poll result
…checks, normalize pubkey
…tion Refactor deployWallet into buildDeployTransaction and submitDeployTransaction for clean separation. Add deployPendingCredential() for retrying failed deployments with autoSubmit, autoFund, and forceMethod support. createWallet now always returns signedTransactionXdr and accepts forceMethod. Use configurable timeoutInSeconds and AbstractTransaction.MIN_BASE_FEE instead of hardcoded values. Fix demo retry deploy to actually deploy and fund.
…ization SDK: Add selectedSigners and forceMethod parameters to all state-changing methods on OZSignerManager, OZPolicyManager, and OZContextRuleManager. When selectedSigners is non-empty, operations route through the multi-signer signing pipeline. Change submitWithMultipleSigners visibility from private to internal. Demo (Compose): Split ContextRuleBuilderScreen into SignerManagementSection and PolicyManagementSection. Add edit-mode support for adding, removing, and modifying signers and policies on existing context rules. Read on-chain policy params via getContractData for pre-populating edit forms. Add multi-signer signer picker for create, edit, and remove operations. Implement auth context guard matching the TS SDK demo behavior. Demo (macOS): Mirror all Compose changes in the Swift app including bridge types, ViewModel edit logic, signer picker, and policy param reading.
All connection methods are now always expanded with descriptions visible. Removed expand/collapse toggle logic and chevron icons. Renamed "Connect with Address (Recovery)" to "Connect with Address".
- Add contractCall() to OZTransactionOperations for single-signer direct external contract calls - Add multiSignerContractCall() to OZMultiSignerManager for multi-signer direct external contract calls - Make submitWithMultipleSigners() public on OZMultiSignerManager - Add ApproveScreen to Compose and macOS demo apps using the new APIs - Add Approve navigation button to MainScreen on both platforms - Update api-reference.md with new methods
…ractCall internally
… policy updates in demo app - Simple threshold policy edits now call set_threshold() directly on the policy contract via the smart account's execute() entry point, routing to executeAndSubmit or multiSignerExecuteAndSubmit based on selectedSigners - Collect and display transaction hashes in context rule edit results on both platforms - Fix macOS app auto-dismissing on edit/create success instead of showing the result card - Remove standalone signer picker button from macOS Transfer and Approve screens to match web app behavior
- Fix restoredFromSession never returning true on session restore (code bug) - Rename getDeployer() to effectiveDeployer() on OZSmartAccountConfig for naming consistency - Cache deployer keypair in OZSmartAccountKit to avoid repeated creation - Make indexerClient and relayerClient public on OZSmartAccountKit - Remove unused createIndexerClient() from OZSmartAccountConfig - Remove dead deployWallet() method from OZWalletOperations - Remove unused KeyPair import from OZWalletOperations - Fix stale KDoc: connectWallet WebAuthn claim, authenticatePasskey code example, publicKey may be empty - Add missing @throws, @param documentation across all three classes - Add Indexer Client and Relayer Client sections to api-reference.md - Add platform-specific provider tables to OZSmartAccountConfig docs - Update Quick Start with session restore flow and correct amount type - Remove all TypeScript SDK references from source comments and docs
…d tests - Fix IDE warnings in OZWalletOperations: unused catch parameters, var to val, if-then foldable, unused method parameter - Update demo app to use OZBuilders for context rule type construction (Compose + macOS bridge) - Add OZBuildersTest with 9 unit tests covering all builder methods and edge cases - Add Builders section to api-reference.md documenting OZBuilders public API - Fix minor KDoc issues in OZBuilders
- Fix FRIENDBOT_RESERVE_XLM KDoc to describe actual behavior (retained in temp account, not funded by Friendbot) - Remove MAX_CONTEXT_RULES constant (not enforced by the OZ contract, from an older version) - Remove related test assertions
- Fix transfer() KDoc: no longer XLM-specific, describes any SEP-41 token - Fix transfer() flow: accurately shows delegation to contractCall() - Fix TransactionResult example: amount type corrected from Double to String - Add specific @throws types to all methods (replacing generic SmartAccountException) - Simplify submit() flow description to match actual delegation structure - Fix submitMultiSignerTransaction param description for clarity - Add KDoc to generateNonce() private method - Remove hardcoded timing claim from pollForConfirmation - Remove unused ktor imports - Fix Transaction Operations doc chapter: missing exceptions, incomplete examples
… and isPrimary, fix KDoc, improve docs - Delete unused markDeployed method and its tests - Wire up updateLastUsed after successful signing in both submit() and submitWithMultipleSigners() - Set isPrimary = false for additional passkey signers in addNewPasskeySigner() - Make internal: markDeploymentFailed, updateCredential, updateLastUsed, setPrimary - Fix KDoc: state machine add sync and failed->deleted paths, saveCredential overwrite/isPrimary/contractId behavior, sync failure handling, missing @param nickname - Remove unused existing variables in markDeploymentFailed and updateCredential - Document missing public methods in api-reference: getCredential, getCredentialsByContract, getForConnectedWallet, saveCredential, clearAll - Fix incorrect throws in docs: saveCredential, getForConnectedWallet - Fix StoredCredential field order and defaults to match source - Add missing throws to getPendingCredentials and syncAll docs
…lManager SDK changes: - Add removeSigner(contextRuleId, signer) convenience overload that resolves signer ID via single RPC call - Make parseContextRule internal on OZContextRuleManager for single-rule fetch - Fix isPrimary: default to false in createPendingCredential, set true only in createWallet - Fix double-prefixed error message in addNewPasskeySigner WebAuthn exception - Fix thread safety claim in OZSignerManager class KDoc - Fix addSigner KDoc: clarify signer ID not in TransactionResult - Fix removeSigner KDoc: specific @throws, correct code example - Add bounds check for signerIds array in signer-based removeSigner Documentation: - Remove TS SDK divergence note from addNewPasskeySigner - Add removeSigner (by signer value) section - Add missing code examples for addPasskey, addEd25519, removeSigner - Fix addNewPasskeySigner throws: add ValidationException, StorageException - Add throws sections to addPasskey, addDelegated, addEd25519 - Document missing credential manager methods: getCredential, getCredentialsByContract, getForConnectedWallet, saveCredential, clearAll - Fix incorrect throws in docs: saveCredential, getForConnectedWallet - Fix StoredCredential field order and defaults
- Add removePolicy(contextRuleId, policyAddress) convenience overload with single-rule fetch and bounds check - Add threshold > 0 validation to SimpleThreshold.toScVal() and WeightedThreshold.toScVal() - Add policyAddress format validation to address-based removePolicy - Make sortMapByKeyXdr internal - Fix PolicyInstallParams KDoc: "at least M-of-N", add note about convenience methods, fix example - Fix spendingLimit param: no longer XLM-specific, describes decimal string with 7 decimal places - Simplify convenience method flow descriptions to "delegates to addPolicy" - Standardize @throws across all methods with specific exception types - Fix HostFunctionXDR typo to HostFunctionXdr in return tags - Add throws and examples to all policy methods in api-reference.md - Add removePolicy (by address) section to api-reference.md - Add test for new removePolicy overload
…fix KDoc and tests - Document getContextRule, listContextRules, ParsedContextRule in api-reference.md - Make resolveContextRuleIdsForEntry internal, buildInvocationContextTypes and contextRuleTypeMatches private - Fix resolveContextRuleIdsForEntry KDoc: add missing Tier 3 (selected subset) to algorithm - Fix stale v0.7.0 reference, vague @throws, missing @throws on updateValidUntil and parseSigner - Fix 3 pre-existing test failures: isPrimary default change, threshold > 0 validation
… docs - Fix SelectedSigner.Passkey equals/hashCode for ByteArray content equality - Remove duplicate keyData validation, duplicate @OptIn, redundant casts - Remove duplicate null checks on externalWallet (guarded at method entry) - Extract shared validation into validateContractCallArgs helper - Fix step numbering, remove TS SDK references, fix stale version comment - Fix docs: amount not XLM-specific, add throws/validation info
…ess, fix KDoc - Make get(), hasSigners(), hasWalletAdapter internal; InMemoryWalletConnectionStorage internal - Add disconnectByAddress(address) to ExternalWalletAdapter for per-address cleanup - Call disconnectByAddress from remove() and removeWalletFromStorage from addFromSecret - Document WalletConnectionStorage interface and constructor parameters - Fix stale KDoc references, add missing side effect documentation
… and docs
- Normalize indexerUrl once in init as baseUrl, remove repeated trimEnd calls
- Implement AutoCloseable for use {} block support
- Use Network.TESTNET.networkPassphrase instead of hardcoded string
- Extract health status magic string to HEALTH_STATUS_OK constant
- Fix @throws on performRequest, lookupByCredentialId, getStats
- Document all response types, factory methods, constructor params in api-reference
- Fix IndexedSigner: add Native type, correct credential ID format to hex
… tests Documentation: - Document Events chapter: add once, removeAllListeners, listenerCount, setErrorHandler - Document Exceptions chapter: add SmartAccountErrorCode enum with all 26 codes - Document Types chapter: add TransactionResult, PolicyInstallParams, StoredCredential, CredentialDeploymentStatus, ConnectedWallet, SignAuthEntryResult - Fix WebAuthnAuthenticationResult property order - Rewrite Platform-Specific Implementations with actual constructors and parameters - Document Relayer Client: fix method signatures, add RelayerResponse and RelayerErrorCodes - Remove phantom constants AUTH_ENTRY_EXPIRATION_BUFFER and MAX_CONTEXT_RULES from docs SDK fixes: - Refactor OZRelayerClient: persistent HTTP client, AutoCloseable, remove withHttpClient - Add isLocalhostUrl validation to prevent http://localhost.evil.com bypass - Add client identification headers (X-Client-Name, X-Client-Version) to OZIndexerClient - Extract header constants to OZConstants - Fix OZSmartAccountEvents KDoc: CredentialCreated, TransactionSubmitted, removeAllListeners - Fix adapter bugs: IndexedDB deleteDatabase default, close() synchronization, JsWebAuthn CBOR bounds check, AppleWebAuthn unused variable, UserDefaults synchronize removal - Restore sortMapByKeyXdr public visibility for demo app Tests: - Add IndexerClientTest (44 tests) with MockEngine-based HTTP testing - Add RelayerClientTest (35 tests) with MockEngine-based HTTP testing - Consolidate and delete RelayerIndexerClientTest - 100% code path coverage for both clients
…atform guides - README.md: remove external SDK references from deployer and signer sections, remove MAX_CONTEXT_RULES claim, fix transfer amount comment (not XLM-specific) - onboarding.md: remove external SDK references, remove 15 context rules claim, fix spending limit description (token-generic) - webauthn-macos.md: rewrite presentation context section (property already exists), fix error code 1005 to 1004, fix iCloud sync claim on UserDefaults - webauthn-web.md: note that IndexedDBStorageAdapter.close() is suspend - webauthn-android.md: clarify API 28+ is for WebAuthn, API 24+ for storage
…dation bug New test files (9): - SmartAccountSignaturesTest (64 tests): signature types, XDR encoding, validation - SmartAccountAuthPayloadTest (55 tests): codec read/write, upsert, round-trips - SmartAccountUtilsTest (72 tests): key extraction, signature normalization, derivation - SmartAccountErrorsTest (175 tests): all factory methods, error codes, wrapError - ContextRuleParsingTest (57 tests): parseContextRule, toScVal, validation - PolicyInstallParamsTest (31 tests): threshold/spending limit ScVal, sortMapByKeyXdr - SignerTypesTest (67 tests): signer construction, equality, ScVal round-trips - TransactionOperationsValidationTest (43 tests): input validation, data classes - WalletOperationsValidationTest (62 tests): connection state, data classes, validation Updated test files (1): - EventSystemTest: 19 new tests for once(), edge cases, rapid emission Bug fix: - Add missing targetFn blank validation to executeAndSubmit (was present in contractCall but missing in executeAndSubmit) Source KDoc fixes: - OZSmartAccountConfig: add @throws for constructor validation - OZSmartAccountConfig.effectiveDeployer: document suspend rationale - WebAuthnProvider: remove unused import, fix attestationObject KDoc
… types, use constants - SmartAccountAuth: remove external SDK reference from buildAuthDigest KDoc - SmartAccountBuilders: fix createSpendingLimitParams @throws (IllegalArgumentException from amountToStroops, not ValidationException), use ED25519_PUBLIC_KEY_SIZE constant - SmartAccountSignatures: use ED25519_PUBLIC_KEY_SIZE constant in Ed25519Signature init - SmartAccountUtils: fix deriveContractAddress to throw ValidationException.InvalidInput for encoding failures instead of TransactionException.SigningFailed - SmartAccountErrors: add missing KDoc to IndexerException factory methods
Platform adapter fixes: - Fix CBOR integer overflow producing negative lengths (Android) - Fix Keychain SecItemUpdate missing kSecAttrAccessible attribute (Apple) - Fix fragile js() variable name captures with IIFE pattern (JS) - Fix AppleWebAuthnProvider reporting false instead of null for unknown flags - Fix UserDefaultsStorageAdapter bare return null in withLock lambda - Extract shared StoredCredential.applyUpdate() replacing 6x duplicated merge logic - Remove credential IDs from Android log messages - Add safe casts with descriptive errors for Android CredentialManager responses - Update copyright headers to 2026 New tests (58): - KeychainStorageAdapterTest: 32 tests against real macOS Keychain - AppleWebAuthnProviderTest: 11 tests for constructor validation and NSData conversion - JsWebAuthnGuardTest: 7 tests for Node.js environment guards - UserDefaultsStorageAdapterTest: 3 additional edge case tests - LocalStorageAdapterTest: 5 additional field update tests
Consolidate CBOR parsing, key extraction, and authenticator flags logic from all three platform WebAuthn providers into a shared utility in the OZ layer. Add tests covering every method.
Update demo contract addresses and WASM hash to latest OZ testnet deployment. Add mainnet indexer default URL for auto-configuration.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Prepares the smart account layer for release with API hardening, expanded test coverage, documentation improvements, and demo app features. Includes 645+ new unit tests, shared WebAuthn CBOR parsing, multi-signer support across all managers, generic contract call APIs, and new demo screens for token approval and context rule editing. All changes are verified against OZ stellar-contracts v0.7.0.
SDK features
contractCallandmultiSignerContractCallAPIs for arbitrary contract invocations with single or multi-signer authexecuteAndSubmitandmultiSignerExecuteAndSubmitfor smart-account-mediated contract calls with multi-signer authdeployPendingCredentialto retry or externally submit a deferred wallet deploymentremoveSigneroverload that accepts aSmartAccountSignervalue instead of numeric IDremovePolicyoverload that accepts a policy contract address instead of numeric IDselectedSigners+forceMethodparameters) to all state-changing methods across OZSignerManager, OZPolicyManager, and OZContextRuleManagerIndexerExceptionsealed class (RequestFailed, Timeout) for proper indexer error handlingSessionExceptionsealed class for session-related errorsExternalWalletAdapter.disconnectByAddressfor per-signer cleanup when removing external signersWebAuthnCborParseras shared pure-Kotlin CBOR parser for attestation data, eliminating duplicate logic across Android, JS, and Apple providersStoredCredential.applyUpdateextension for applying partial credential updatesisLocalhostUrlvalidation helper for stricter localhost URL matchingmaxContextRuleScanIdconfig parameter and builder methodsignatureExpirationLedgersconfig parameter (replaces hardcoded AUTH_ENTRY_EXPIRATION_BUFFER)timeoutInSecondsfor transaction timeouts (replaces hardcoded 300)CreateWalletResult.signedTransactionXdrfield (always populated, regardless of autoSubmit)DeployPendingResultdata class for pending deployment resultsforceMethodparameter tocreateWalletandfundWalletrelayerClientandindexerClientproperties public on OZSmartAccountKittransferandmultiSignerTransferto delegate to genericcontractCall/multiSignerContractCallinternallyUtil.getSdkVersion()in relayer and indexer client identification headersclose()effectiveIndexerUrl()fallback (auto-uses default for known networks)SDK bug fixes
executeAndSubmitto validate thattargetFnis not blank before building the invocationconnectWalletto markrestoredFromSession = truewhen restoring from a saved sessionValidationException.InvalidInputinstead ofTransactionException.SigningFailedSimpleThreshold.toScValandWeightedThreshold.toScValto reject threshold of zerocreateWalletto always build and sign the deploy transaction regardless ofautoSubmitcreateWalletto normalize and validate the public key from WebAuthn registration viaextractPublicKeyFromRegistrationisPrimaryto default to false; only set to true by the wallet creation flowwithLockreturn value inInMemoryStorageAdapter.getSessionfor expired sessionsAutoCloseableinstead of creating per-request clientsAutoCloseableOZSmartAccountConfigto validateaccountWasmHashis a 64-character hex stringAbstractTransaction.MIN_BASE_FEEconstant throughoutfundWalletto useLEDGERS_PER_HOURinstead of the config's signature expirationSDK code quality
SmartAccountVersionobject; useOZConstants.CLIENT_NAMEandUtil.getSdkVersion()insteadSmartAccountBuilders.parseSigner; useDelegatedSignerconstructor directlyOZCredentialManager.markDeployed; usedeleteCredentialinsteadOZConstants.MAX_CONTEXT_RULESandOZConstants.AUTH_ENTRY_EXPIRATION_BUFFEROZSmartAccountConfig.createIndexerClient; use factorycreate()method insteadOZSmartAccountConfig.getDeployer()toeffectiveDeployer()for clarityOZCredentialManager.markDeploymentFailed,updateCredential,updateLastUsed,setPrimarytointernalOZContextRuleManager.parseContextRuletointernal,buildInvocationContextTypesandcontextRuleTypeMatchestoprivate,resolveContextRuleIdsForEntrytointernalOZExternalSignerManager.InMemoryWalletConnectionStoragetointernal,hasWalletAdapter,hasSigners,gettointernalSelectedSigner.Passkeynow has properequals/hashCodefor ByteArray fieldsSmartAccountConstants.ED25519_PUBLIC_KEY_SIZEStrKey.isValidEd25519PublicKey,StrKey.isValidContract) in indexer client address checksprivate setto mutable DemoState properties (externalSignerManager,webauthnProvider,storage)_throughoutSDK tests
WebAuthnCborParserTest(1087 lines): CBOR parsing, public key extraction, authenticator data parsingSmartAccountErrorsTest(1176 lines): all error codes, exception types, factory methodsSmartAccountUtilsTest(985 lines): contract address derivation, public key extraction, hex codecSmartAccountAuthPayloadTest(888 lines): auth payload hash construction, context rule digestSmartAccountSignaturesTest(800 lines): signature types, normalization, XDR encodingIndexerClientTest(1032 lines): URL validation, all endpoints, error handling, health checkRelayerClientTest(821 lines): URL validation, mode 1/2 submission, timeout handling, AutoCloseableWalletOperationsValidationTest(814 lines): createWallet, connectWallet, deployPendingCredential validationTransactionOperationsValidationTest(785 lines): transfer, contractCall, executeAndSubmit, fundWallet validationSignerTypesTest(695 lines): signer equality, XDR encoding, DelegatedSigner/ExternalSigner validationPolicyInstallParamsTest(597 lines): SimpleThreshold, WeightedThreshold, SpendingLimit encoding and validationContextRuleParsingTest(1127 lines): context rule parsing, signer/policy extraction, context type matchingManagerSelectedSignersTest(537 lines): multi-signer parameter validation across all managersMultiSignerManagerTest(474 lines): SelectedSigner types, validation, equalityOZBuildersTest(105 lines): callContract, createContract context rule type buildersEventSystemTestexpansion (440+ lines): global listeners, removeAllListeners, concurrent accessKeychainStorageAdapterTest,AppleWebAuthnProviderTest,UserDefaultsStorageAdapterTest,JsWebAuthnGuardTest,LocalStorageAdapterTestRelayerIndexerClientTest,SmartAccountBuildersTest,SmartAccountContractAbiConfigValidationTest,ConnectedWalletTest,CredentialManagerTestfor API changesSDK documentation
ContractErrorCodes, config methods,ED25519_PUBLIC_KEY_SIZE, andaddListener@throwsdocumentation to all public methods across managersDemo app features
ContextRuleEditFlow,ContextRuleEditTypes) with step-by-step on-chain submissionretryPendingDeploy) with balance fetch and DEMO token mintingPolicyManagementSectionandSignerManagementSectionas extracted Compose componentsApproveScreen.swiftandApproveFlow.ktfor macOS demoexecuteAndSubmit/multiSignerExecuteAndSubmitfor simple threshold policy updates in demoDemo app fixes
Demo app infrastructure
isDeployedtracking and proper setter encapsulationContract compatibility