11// Copyright (c). Gem Wallet. All rights reserved.
22
3- import Foundation
4- import BigInt
53import Foundation
64import Primitives
75
86import struct Gemstone. SwapperQuote
7+ import struct Gemstone. SwapperProviderType
98
109public protocol SwapQuotesProvidable : Sendable {
1110 func supportedAssets( for assetId: AssetId ) -> ( [ Primitives . Chain ] , [ Primitives . AssetId ] )
12- func fetchQuotes( wallet: Wallet , fromAsset : Asset , toAsset : Asset , amount : BigInt , useMaxAmount : Bool ) async throws -> [ Gemstone . SwapperQuote ]
11+ func fetchQuotes( wallet: Wallet , input : SwapQuoteInput ) -> AsyncStream < Result < SwapperQuote , Error > >
1312}
1413
1514public struct SwapQuotesProvider : SwapQuotesProvidable {
@@ -23,17 +22,44 @@ public struct SwapQuotesProvider: SwapQuotesProvidable {
2322 swapService. supportedAssets ( for: assetId)
2423 }
2524
26- public func fetchQuotes( wallet: Wallet , fromAsset: Asset , toAsset: Asset , amount: BigInt , useMaxAmount: Bool ) async throws -> [ Gemstone . SwapperQuote ] {
27- let walletAddress = try wallet. account ( for: fromAsset. chain) . address
28- let destinationAddress = try wallet. account ( for: toAsset. chain) . address
29- let quotes = try await swapService. getQuotes (
30- fromAsset: fromAsset,
31- toAsset: toAsset,
32- value: amount. description,
33- walletAddress: walletAddress,
34- destinationAddress: destinationAddress,
35- useMaxAmount: useMaxAmount
36- )
37- return try quotes. sorted { try BigInt . from ( string: $0. toValue) > BigInt . from ( string: $1. toValue) }
25+ public func fetchQuotes( wallet: Wallet , input: SwapQuoteInput ) -> AsyncStream < Result < SwapperQuote , Error > > {
26+ AsyncStream { continuation in
27+ let task = Task {
28+ do {
29+ let walletAddress = try wallet. account ( for: input. fromAsset. chain) . address
30+ let destinationAddress = try wallet. account ( for: input. toAsset. chain) . address
31+ let providers = try swapService. getProvidersForQuote ( input: input, walletAddress: walletAddress, destinationAddress: destinationAddress)
32+ await fetchFromProviders ( providers, input: input, walletAddress: walletAddress, destinationAddress: destinationAddress, continuation: continuation)
33+ } catch {
34+ continuation. yield ( . failure( error) )
35+ }
36+ continuation. finish ( )
37+ }
38+ continuation. onTermination = { _ in
39+ task. cancel ( )
40+ }
41+ }
42+ }
43+
44+ private func fetchFromProviders( _ providers: [ SwapperProviderType ] , input: SwapQuoteInput , walletAddress: String , destinationAddress: String , continuation: AsyncStream < Result < SwapperQuote , Error > > . Continuation ) async {
45+ await withTaskGroup ( of: Result< SwapperQuote, Error>? . self ) { group in
46+ for provider in providers {
47+ group. addTask { [ swapService] in
48+ guard !Task. isCancelled else { return nil }
49+ do {
50+ let quote = try await swapService. getQuoteByProvider ( provider: provider. id, input: input, walletAddress: walletAddress, destinationAddress: destinationAddress)
51+ return . success( quote)
52+ } catch {
53+ guard !Task. isCancelled else { return nil }
54+ return . failure( error)
55+ }
56+ }
57+ }
58+ for await result in group {
59+ if let result {
60+ continuation. yield ( result)
61+ }
62+ }
63+ }
3864 }
3965}
0 commit comments