Skip to content

Split DefaultSmartWalletService into domain services#81

Open
tomas-martins-crossmint wants to merge 13 commits into
mainfrom
tomas/wal-9975-create-services-for-each-domain
Open

Split DefaultSmartWalletService into domain services#81
tomas-martins-crossmint wants to merge 13 commits into
mainfrom
tomas/wal-9975-create-services-for-each-domain

Conversation

@tomas-martins-crossmint
Copy link
Copy Markdown
Contributor

@tomas-martins-crossmint tomas-martins-crossmint commented May 6, 2026

DefaultSmartWalletService was a single class implementing all wallet operations across every domain. It now delegates to six standalone services, each owning one domain, and SmartWalletService becomes a protocol composition.

Changes

  • SmartWalletService — now a protocol composition of WalletService, TransactionService, TransferService, BalanceService, NFTService, and SignatureService; previously a single flat protocol with all methods
  • DefaultSmartWalletService — thin facade holding one instance of each domain service and delegating every method; contains no logic of its own
  • DefaultWalletService, DefaultTransactionService, DefaultTransferService, DefaultBalanceService, DefaultNFTService, DefaultSignatureService — new standalone service structs, each responsible for one domain, grouped under Sources/Wallet/Data/Services/<Domain>/
  • AuthManagerProviding — internal protocol with a default authHeaders implementation, adopted by all six services to remove the duplication
  • TransactionRequestExecuting — internal protocol with a default executeTransactionRequest implementation, adopted by the three services that dispatch on-chain transactions
  • CreateSignatureRequest.Body — replaces SignatureRequestProtocol existential and the old ResponseType enum; each case carries its associated request value directly
  • TransferTokenRequest — replaces the six-parameter transferToken method signature with a params struct
  • Endpoints.swift — centralises all URL path construction into static Endpoint factory methods; previously built inline in each service method

@tomas-martins-crossmint tomas-martins-crossmint marked this pull request as draft May 6, 2026 21:28
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
Sources/Wallet/Data/Services/DefaultTransferService.swift:6-10
The synthesized `Encodable` for `TransferBody` encodes `nil` optionals as `"signer": null`, whereas the original hand-rolled implementation used `encodeIfPresent`, which omits the key entirely. If the transfer API rejects an explicit `null` for `signer`, every call without a signer will fail after this refactor.

```suggestion
private struct TransferBody: Encodable {
    let recipient: String
    let amount: String
    let signer: String?

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(recipient, forKey: .recipient)
        try container.encode(amount, forKey: .amount)
        try container.encodeIfPresent(signer, forKey: .signer)
    }

    private enum CodingKeys: String, CodingKey { case recipient, amount, signer }
}
```

### Issue 2 of 2
Sources/CrossmintService/JSONCoder.swift:26-35
`try?` silently discards the original `DecodingError`, so all failures surface only as the generic caller-supplied error. Logging the underlying error before throwing preserves debuggability without changing the public API.

```suggestion
    func decodeOrThrow<T: Decodable, E: Error>(
        _ type: T.Type,
        from data: Data,
        onFailure: @autoclosure () -> E
    ) throws(E) -> T {
        do {
            return try decode(type, from: data)
        } catch {
            print("[JSONCoder.decodeOrThrow] Failed to decode \(T.self): \(error)")
            throw onFailure()
        }
    }
```

Reviews (1): Last reviewed commit: "Address afeight-review: extract Endpoint..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
Sources/Wallet/Data/Services/DefaultTransferService.swift:6-10
The new `TransferBody` struct loses the `encodeIfPresent` behavior that the old inline `Body` had for the optional `signer` field. Swift's synthesised `Encodable` encodes `nil` optionals as `"signer": null` in JSON, whereas the original code used `encodeIfPresent` which omitted the key entirely. If the API treats a missing key differently from `null` — for example rejecting the request or routing it differently — this silent change will cause failures for every transfer call where `signer` is not provided.

```suggestion
private struct TransferBody: Encodable {
    let recipient: String
    let amount: String
    let signer: String?

    private enum CodingKeys: String, CodingKey { case recipient, amount, signer }

    func encode(to encoder: Encoder) throws {
        var c = encoder.container(keyedBy: CodingKeys.self)
        try c.encode(recipient, forKey: .recipient)
        try c.encode(amount, forKey: .amount)
        try c.encodeIfPresent(signer, forKey: .signer)
    }
}
```

### Issue 2 of 2
Sources/CrossmintService/JSONCoder.swift:26-35
`decodeOrThrow` silently discards the underlying decode error via `try?`, replacing it with the generic `onFailure` value. This makes it impossible to tell from crash reports or logs which field failed to decode and why. Consider logging or wrapping the original error before discarding it, or at minimum keeping the `CrossmintServiceError` available for internal diagnostics while still surfacing the domain-specific error to callers.

Reviews (1): Last reviewed commit: "Address afeight-review: extract Endpoint..." | Re-trigger Greptile

@tomas-martins-crossmint tomas-martins-crossmint force-pushed the tomas/wal-9975-create-services-for-each-domain branch from 1700579 to fa239c8 Compare May 7, 2026 14:30
@tomas-martins-crossmint tomas-martins-crossmint changed the title Tomas/wal 9975 create services for each domain Split DefaultSmartWalletService into domain services May 7, 2026
@tomas-martins-crossmint tomas-martins-crossmint marked this pull request as ready for review May 7, 2026 22:17
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 7, 2026

Reviews (2): Last reviewed commit: "extract executeTransactionRequest into T..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant