Skip to content

Commit 06eac3d

Browse files
committed
[Issue-4078] feat: find first found process
1 parent 2d4d197 commit 06eac3d

File tree

4 files changed

+148
-9
lines changed

4 files changed

+148
-9
lines changed

packages/extension-base/src/koni/background/handlers/Extension.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/reques
4848
import { AuthUrls } from '@subwallet/extension-base/services/request-service/types';
4949
import { DEFAULT_AUTO_LOCK_TIME } from '@subwallet/extension-base/services/setting-service/constants';
5050
import { checkLiquidityForPool, estimateTokensForPool, getReserveForPool } from '@subwallet/extension-base/services/swap-service/handler/asset-hub/utils';
51+
import { generateAllDestinations } from '@subwallet/extension-base/services/swap-service/utils';
5152
import { SWPermitTransaction, SWTransaction, SWTransactionInput, SWTransactionResponse, SWTransactionResult, TransactionEmitter, TransactionEventResponse, ValidateTransactionResponseInput } from '@subwallet/extension-base/services/transaction-service/types';
52-
import { generateSwapPairs } from '@subwallet/extension-base/services/swap-service/utils';
5353
import { isProposalExpired, isSupportWalletConnectChain, isSupportWalletConnectNamespace } from '@subwallet/extension-base/services/wallet-connect-service/helpers';
5454
import { ResultApproveWalletConnectSession, WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types';
5555
import { SWStorage } from '@subwallet/extension-base/storage';
@@ -1345,7 +1345,8 @@ export default class KoniExtension {
13451345
const warnings: TransactionWarning[] = [];
13461346
const chainInfo = this.#koniState.getChainInfo(chain);
13471347

1348-
const test = generateSwapPairs(this.#koniState.getSubstrateApi(chain), this.#koniState.chainService, transferTokenInfo, 3).map((asset) => asset.slug);
1348+
// todo: remove test:
1349+
const test = generateAllDestinations(this.#koniState.getSubstrateApi(chain), this.#koniState.chainService, transferTokenInfo, 3).map((asset) => asset.slug);
13491350

13501351
console.log('test', test);
13511352

@@ -4069,6 +4070,16 @@ export default class KoniExtension {
40694070
}
40704071

40714072
private async handleSwapRequest (request: SwapRequest): Promise<SwapRequestResult> {
4073+
// todo: remove test:
4074+
const testSwapRequest = this.#koniState.swapService.handleSwapRequestV2({
4075+
address: '1BzDB5n2rfSJwvuCW9deKY9XnUyys8Gy44SoX8tRNDCFBhx',
4076+
fromAmount: '1',
4077+
fromToken: 'hydradx_main-LOCAL-PINK',
4078+
toToken: 'ethereum-NATIVE-ETH'
4079+
});
4080+
4081+
console.log('testSwapRequest', testSwapRequest);
4082+
40724083
return this.#koniState.swapService.handleSwapRequest(request);
40734084
}
40744085

packages/extension-base/src/services/swap-service/index.ts

+91-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
66
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
77
import { ServiceStatus, ServiceWithProcessInterface, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
88
import { ChainService } from '@subwallet/extension-base/services/chain-service';
9+
import { _getAssetPriceId, _getAssetSymbol, _getMultiChainAsset } from '@subwallet/extension-base/services/chain-service/utils';
910
import { EventService } from '@subwallet/extension-base/services/event-service';
1011
import { AssetHubSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/asset-hub';
1112
import { SwapBaseInterface } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
1213
import { ChainflipSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/chainflip-handler';
1314
import { HydradxHandler } from '@subwallet/extension-base/services/swap-service/handler/hydradx-handler';
14-
import { _PROVIDER_TO_SUPPORTED_PAIR_MAP, getSwapAltToken, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
15-
import { BasicTxErrorType } from '@subwallet/extension-base/types';
15+
import { _PROVIDER_TO_SUPPORTED_PAIR_MAP, findSwapDestinations, findXcmDestinations, getInitStep, getSwapAltToken, getSwapStep, getXcmStep, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
16+
import { BasicTxErrorType, SwapRequestV2 } from '@subwallet/extension-base/types';
1617
import { CommonOptimalPath, DEFAULT_FIRST_STEP, MOCK_STEP_FEE } from '@subwallet/extension-base/types/service-base';
1718
import { _SUPPORTED_SWAP_PROVIDERS, OptimalSwapPathParams, QuoteAskResponse, SwapErrorType, SwapPair, SwapProviderId, SwapQuote, SwapQuoteResponse, SwapRequest, SwapRequestResult, SwapStepType, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
1819
import { createPromiseHandler, PromiseHandler } from '@subwallet/extension-base/utils';
@@ -131,6 +132,94 @@ export class SwapService implements ServiceWithProcessInterface, StoppableServic
131132
} as SwapRequestResult;
132133
}
133134

135+
public handleSwapRequestV2 (request: SwapRequestV2) {
136+
const { fromToken, toToken } = request;
137+
const fromTokenInfo = this.chainService.getAssetBySlug(fromToken);
138+
const toTokenInfo = this.chainService.getAssetBySlug(toToken);
139+
const fromChain = fromTokenInfo.originChain;
140+
const toChain = toTokenInfo.originChain;
141+
142+
const firstSwapDes = findSwapDestinations(this.chainService, fromTokenInfo);
143+
const firstXcmDes = findXcmDestinations(this.chainService, fromTokenInfo);
144+
145+
if (!firstSwapDes.length && !firstXcmDes.length) {
146+
return [];
147+
}
148+
149+
const steps = [getInitStep(fromToken)];
150+
151+
// todo: try find swap
152+
if (fromChain === toChain) {
153+
if (firstSwapDes.includes(toTokenInfo)) {
154+
steps.push(getSwapStep(toToken));
155+
156+
return steps;
157+
}
158+
}
159+
160+
// todo: try find xcm
161+
if (_getMultiChainAsset(fromTokenInfo) === _getMultiChainAsset(toTokenInfo) || _getAssetPriceId(fromTokenInfo) === _getAssetPriceId(toTokenInfo) || _getAssetSymbol(fromTokenInfo) === _getAssetSymbol(toTokenInfo)) {
162+
if (firstXcmDes.includes(toTokenInfo)) {
163+
steps.push(getXcmStep(toToken));
164+
165+
return steps;
166+
}
167+
}
168+
169+
// todo: brute force find process
170+
for (const xcmAsset of firstXcmDes) {
171+
const swapDesChild = findSwapDestinations(this.chainService, xcmAsset);
172+
173+
if (!swapDesChild.length) {
174+
/* empty */
175+
} else if (swapDesChild.includes(toTokenInfo)) {
176+
steps.push(getXcmStep(xcmAsset.slug));
177+
steps.push(getSwapStep(toToken));
178+
179+
return steps;
180+
} else {
181+
for (const swapAsset of swapDesChild) {
182+
const xcmDesChild = findXcmDestinations(this.chainService, swapAsset);
183+
184+
if (xcmDesChild.includes(toTokenInfo)) {
185+
steps.push(getXcmStep(xcmAsset.slug));
186+
steps.push(getSwapStep(swapAsset.slug));
187+
steps.push(getXcmStep(toToken));
188+
189+
return steps;
190+
}
191+
}
192+
}
193+
}
194+
195+
for (const swapAsset of firstSwapDes) {
196+
const xcmDesChild = findXcmDestinations(this.chainService, swapAsset);
197+
198+
if (!xcmDesChild.length) {
199+
/* empty */
200+
} else if (xcmDesChild.includes(toTokenInfo)) {
201+
steps.push(getSwapStep(swapAsset.slug));
202+
steps.push(getXcmStep(toToken));
203+
204+
return steps;
205+
} else {
206+
for (const xcmAsset of xcmDesChild) {
207+
const swapDesChild = findSwapDestinations(this.chainService, xcmAsset);
208+
209+
if (swapDesChild.includes(toTokenInfo)) {
210+
steps.push(getSwapStep(swapAsset.slug));
211+
steps.push(getXcmStep(xcmAsset.slug));
212+
steps.push(getSwapStep(toToken));
213+
214+
return steps;
215+
}
216+
}
217+
}
218+
}
219+
220+
return [];
221+
}
222+
134223
public async getLatestQuotes (request: SwapRequest): Promise<SwapQuoteResponse> {
135224
request.pair.metadata = this.getSwapPairMetadata(request.pair.slug); // todo: improve this
136225
const quoteAskResponses = await this.askProvidersForQuote(request);

packages/extension-base/src/services/swap-service/utils.ts

+37-5
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function getChainflipSwap (isTestnet: boolean) {
103103
}
104104
}
105105

106-
export function generateSwapPairs (substrateApi: _SubstrateApi, chainService: ChainService, fromAsset: _ChainAsset, maxPathLength = 1) {
106+
export function generateAllDestinations (substrateApi: _SubstrateApi, chainService: ChainService, fromAsset: _ChainAsset, maxPathLength = 1) {
107107
if (maxPathLength < 1) {
108108
return [];
109109
}
@@ -138,7 +138,7 @@ function findDestinations (chainService: ChainService, chainAsset: _ChainAsset)
138138
return mergeWithoutDuplicate<_ChainAsset>(xcmTargets, swapTargets);
139139
}
140140

141-
function findXcmDestinations (chainService: ChainService, chainAsset: _ChainAsset) {
141+
export function findXcmDestinations (chainService: ChainService, chainAsset: _ChainAsset) {
142142
const xcmTargets: _ChainAsset[] = [];
143143
const multichainAssetSlug = _getMultiChainAsset(chainAsset);
144144

@@ -154,10 +154,10 @@ function findXcmDestinations (chainService: ChainService, chainAsset: _ChainAsse
154154
}
155155
}
156156

157-
return xcmTargets;
157+
return xcmTargets.filter((candidate) => candidate.slug !== chainAsset.slug);
158158
}
159159

160-
function findSwapDestinations (chainService: ChainService, chainAsset: _ChainAsset) {
160+
export function findSwapDestinations (chainService: ChainService, chainAsset: _ChainAsset) {
161161
const chain = chainAsset.originChain;
162162
const swapTargets: _ChainAsset[] = [];
163163

@@ -177,7 +177,7 @@ function findSwapDestinations (chainService: ChainService, chainAsset: _ChainAss
177177
swapTargets.push(...Object.values(assets));
178178
});
179179

180-
return swapTargets;
180+
return swapTargets.filter((candidate) => candidate.slug !== chainAsset.slug);
181181
}
182182

183183
// @ts-ignore
@@ -230,3 +230,35 @@ export async function getAllXcmChannelSubstrate (substrateApi: _SubstrateApi) {
230230
function mergeWithoutDuplicate<T> (arr1: T[], arr2: T[]): T[] {
231231
return Array.from(new Set([...arr1, ...arr2]));
232232
}
233+
234+
export enum transferTokenType {
235+
INIT = 'INIT',
236+
SWAP = 'SWAP',
237+
XCM = 'XCM' // todo: rename XCM to a better name to describe cross chain transfer action;
238+
}
239+
240+
export interface TransferTokenAction {
241+
action: transferTokenType;
242+
toToken: string;
243+
}
244+
245+
export function getInitStep (tokenSlug: string): TransferTokenAction {
246+
return {
247+
action: transferTokenType.INIT,
248+
toToken: tokenSlug
249+
};
250+
}
251+
252+
export function getXcmStep (tokenSlug: string): TransferTokenAction {
253+
return {
254+
action: transferTokenType.XCM,
255+
toToken: tokenSlug
256+
};
257+
}
258+
259+
export function getSwapStep (tokenSlug: string): TransferTokenAction {
260+
return {
261+
action: transferTokenType.SWAP,
262+
toToken: tokenSlug
263+
};
264+
}

packages/extension-base/src/types/swap/index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ export interface SwapRequest {
169169
currentQuote?: SwapProvider
170170
}
171171

172+
export interface SwapRequestV2 {
173+
address: string;
174+
fromAmount: string;
175+
fromToken: string;
176+
toToken: string;
177+
}
178+
172179
export interface SwapRequestResult {
173180
process: CommonOptimalPath;
174181
quote: SwapQuoteResponse;

0 commit comments

Comments
 (0)