@ledgerhq/live-common 34.40.0 → 34.41.0-nightly.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__tests__/test-helpers/bridge.d.ts.map +1 -1
- package/lib/__tests__/test-helpers/bridge.js +0 -4
- package/lib/__tests__/test-helpers/bridge.js.map +1 -1
- package/lib/bridge/impl.d.ts.map +1 -1
- package/lib/bridge/impl.js +45 -4
- package/lib/bridge/impl.js.map +1 -1
- package/lib/bridge/useBridgeTransaction.test.js +9 -0
- package/lib/bridge/useBridgeTransaction.test.js.map +1 -1
- package/lib/e2e/enum/Account.d.ts +1 -0
- package/lib/e2e/enum/Account.d.ts.map +1 -1
- package/lib/e2e/enum/Account.js +1 -0
- package/lib/e2e/enum/Account.js.map +1 -1
- package/lib/e2e/enum/Provider.d.ts +3 -0
- package/lib/e2e/enum/Provider.d.ts.map +1 -1
- package/lib/e2e/enum/Provider.js +3 -0
- package/lib/e2e/enum/Provider.js.map +1 -1
- package/lib/e2e/index.d.ts +1 -2
- package/lib/e2e/index.d.ts.map +1 -1
- package/lib/e2e/speculos.d.ts.map +1 -1
- package/lib/e2e/speculos.js +2 -0
- package/lib/e2e/speculos.js.map +1 -1
- package/lib/env.react.d.ts +1 -1
- package/lib/env.react.d.ts.map +1 -1
- package/lib/exchange/error.d.ts +1 -0
- package/lib/exchange/error.d.ts.map +1 -1
- package/lib/exchange/error.js +11 -1
- package/lib/exchange/error.js.map +1 -1
- package/lib/exchange/swap/api/v5/actions.d.ts +3 -0
- package/lib/exchange/swap/api/v5/actions.d.ts.map +1 -0
- package/lib/exchange/swap/api/v5/actions.js +36 -0
- package/lib/exchange/swap/api/v5/actions.js.map +1 -0
- package/lib/exchange/swap/completeExchange.d.ts.map +1 -1
- package/lib/exchange/swap/completeExchange.js +13 -0
- package/lib/exchange/swap/completeExchange.js.map +1 -1
- package/lib/exchange/swap/getCompleteSwapHistory.js +1 -1
- package/lib/exchange/swap/getCompleteSwapHistory.js.map +1 -1
- package/lib/exchange/swap/postSwapState.d.ts.map +1 -1
- package/lib/exchange/swap/postSwapState.js +19 -9
- package/lib/exchange/swap/postSwapState.js.map +1 -1
- package/lib/exchange/swap/setBroadcastTransaction.d.ts +3 -2
- package/lib/exchange/swap/setBroadcastTransaction.d.ts.map +1 -1
- package/lib/exchange/swap/setBroadcastTransaction.js +4 -2
- package/lib/exchange/swap/setBroadcastTransaction.js.map +1 -1
- package/lib/exchange/swap/transactionStrategies.d.ts +25 -0
- package/lib/exchange/swap/transactionStrategies.d.ts.map +1 -0
- package/lib/exchange/swap/transactionStrategies.js +152 -0
- package/lib/exchange/swap/transactionStrategies.js.map +1 -0
- package/lib/exchange/swap/types.d.ts +59 -0
- package/lib/exchange/swap/types.d.ts.map +1 -1
- package/lib/families/cardano/signerSerializer.js +4 -2
- package/lib/families/cardano/signerSerializer.js.map +1 -1
- package/lib/families/evm/bridge/mock.js +2 -2
- package/lib/families/evm/platformAdapter.js +2 -2
- package/lib/families/evm/platformAdapter.js.map +1 -1
- package/lib/families/evm/platformAdapter.test.js +4 -4
- package/lib/families/evm/platformAdapter.test.js.map +1 -1
- package/lib/families/evm/react.js +1 -1
- package/lib/families/evm/react.js.map +1 -1
- package/lib/families/evm/react.test.js +2 -2
- package/lib/families/evm/react.test.js.map +1 -1
- package/lib/families/evm/walletApiAdapter.js +1 -1
- package/lib/families/evm/walletApiAdapter.js.map +1 -1
- package/lib/featureFlags/defaultFeatures.js +1 -1
- package/lib/featureFlags/defaultFeatures.js.map +1 -1
- package/lib/featureFlags/useFeature.d.ts +1 -1
- package/lib/featureFlags/useFeature.d.ts.map +1 -1
- package/lib/hw/extractOnboardingState.d.ts.map +1 -1
- package/lib/hw/extractOnboardingState.js +8 -6
- package/lib/hw/extractOnboardingState.js.map +1 -1
- package/lib/hw/extractOnboardingState.test.js +7 -0
- package/lib/hw/extractOnboardingState.test.js.map +1 -1
- package/lib/mock/account.d.ts.map +1 -1
- package/lib/mock/account.js +1 -0
- package/lib/mock/account.js.map +1 -1
- package/lib/wallet-api/Exchange/server.d.ts +29 -10
- package/lib/wallet-api/Exchange/server.d.ts.map +1 -1
- package/lib/wallet-api/Exchange/server.js +204 -7
- package/lib/wallet-api/Exchange/server.js.map +1 -1
- package/lib/wallet-api/Exchange/server.test.js +3 -1
- package/lib/wallet-api/Exchange/server.test.js.map +1 -1
- package/lib/wallet-api/useDappLogic.js +2 -2
- package/lib-es/__tests__/test-helpers/bridge.d.ts.map +1 -1
- package/lib-es/__tests__/test-helpers/bridge.js +0 -4
- package/lib-es/__tests__/test-helpers/bridge.js.map +1 -1
- package/lib-es/bridge/impl.d.ts.map +1 -1
- package/lib-es/bridge/impl.js +43 -2
- package/lib-es/bridge/impl.js.map +1 -1
- package/lib-es/bridge/useBridgeTransaction.test.js +9 -0
- package/lib-es/bridge/useBridgeTransaction.test.js.map +1 -1
- package/lib-es/e2e/enum/Account.d.ts +1 -0
- package/lib-es/e2e/enum/Account.d.ts.map +1 -1
- package/lib-es/e2e/enum/Account.js +1 -0
- package/lib-es/e2e/enum/Account.js.map +1 -1
- package/lib-es/e2e/enum/Provider.d.ts +3 -0
- package/lib-es/e2e/enum/Provider.d.ts.map +1 -1
- package/lib-es/e2e/enum/Provider.js +3 -0
- package/lib-es/e2e/enum/Provider.js.map +1 -1
- package/lib-es/e2e/index.d.ts +1 -2
- package/lib-es/e2e/index.d.ts.map +1 -1
- package/lib-es/e2e/speculos.d.ts.map +1 -1
- package/lib-es/e2e/speculos.js +2 -0
- package/lib-es/e2e/speculos.js.map +1 -1
- package/lib-es/env.react.d.ts +1 -1
- package/lib-es/env.react.d.ts.map +1 -1
- package/lib-es/exchange/error.d.ts +1 -0
- package/lib-es/exchange/error.d.ts.map +1 -1
- package/lib-es/exchange/error.js +9 -0
- package/lib-es/exchange/error.js.map +1 -1
- package/lib-es/exchange/swap/api/v5/actions.d.ts +3 -0
- package/lib-es/exchange/swap/api/v5/actions.d.ts.map +1 -0
- package/lib-es/exchange/swap/api/v5/actions.js +29 -0
- package/lib-es/exchange/swap/api/v5/actions.js.map +1 -0
- package/lib-es/exchange/swap/completeExchange.d.ts.map +1 -1
- package/lib-es/exchange/swap/completeExchange.js +13 -0
- package/lib-es/exchange/swap/completeExchange.js.map +1 -1
- package/lib-es/exchange/swap/getCompleteSwapHistory.js +1 -1
- package/lib-es/exchange/swap/getCompleteSwapHistory.js.map +1 -1
- package/lib-es/exchange/swap/postSwapState.d.ts.map +1 -1
- package/lib-es/exchange/swap/postSwapState.js +17 -7
- package/lib-es/exchange/swap/postSwapState.js.map +1 -1
- package/lib-es/exchange/swap/setBroadcastTransaction.d.ts +3 -2
- package/lib-es/exchange/swap/setBroadcastTransaction.d.ts.map +1 -1
- package/lib-es/exchange/swap/setBroadcastTransaction.js +4 -2
- package/lib-es/exchange/swap/setBroadcastTransaction.js.map +1 -1
- package/lib-es/exchange/swap/transactionStrategies.d.ts +25 -0
- package/lib-es/exchange/swap/transactionStrategies.d.ts.map +1 -0
- package/lib-es/exchange/swap/transactionStrategies.js +140 -0
- package/lib-es/exchange/swap/transactionStrategies.js.map +1 -0
- package/lib-es/exchange/swap/types.d.ts +59 -0
- package/lib-es/exchange/swap/types.d.ts.map +1 -1
- package/lib-es/families/cardano/signerSerializer.js +4 -2
- package/lib-es/families/cardano/signerSerializer.js.map +1 -1
- package/lib-es/families/evm/bridge/mock.js +1 -1
- package/lib-es/families/evm/platformAdapter.js +1 -1
- package/lib-es/families/evm/platformAdapter.js.map +1 -1
- package/lib-es/families/evm/platformAdapter.test.js +1 -1
- package/lib-es/families/evm/platformAdapter.test.js.map +1 -1
- package/lib-es/families/evm/react.js +1 -1
- package/lib-es/families/evm/react.js.map +1 -1
- package/lib-es/families/evm/react.test.js +2 -2
- package/lib-es/families/evm/react.test.js.map +1 -1
- package/lib-es/families/evm/walletApiAdapter.js +1 -1
- package/lib-es/families/evm/walletApiAdapter.js.map +1 -1
- package/lib-es/featureFlags/defaultFeatures.js +1 -1
- package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
- package/lib-es/featureFlags/useFeature.d.ts +1 -1
- package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
- package/lib-es/hw/extractOnboardingState.d.ts.map +1 -1
- package/lib-es/hw/extractOnboardingState.js +8 -6
- package/lib-es/hw/extractOnboardingState.js.map +1 -1
- package/lib-es/hw/extractOnboardingState.test.js +7 -0
- package/lib-es/hw/extractOnboardingState.test.js.map +1 -1
- package/lib-es/mock/account.d.ts.map +1 -1
- package/lib-es/mock/account.js +1 -0
- package/lib-es/mock/account.js.map +1 -1
- package/lib-es/wallet-api/Exchange/server.d.ts +29 -10
- package/lib-es/wallet-api/Exchange/server.d.ts.map +1 -1
- package/lib-es/wallet-api/Exchange/server.js +206 -9
- package/lib-es/wallet-api/Exchange/server.js.map +1 -1
- package/lib-es/wallet-api/Exchange/server.test.js +3 -1
- package/lib-es/wallet-api/Exchange/server.test.js.map +1 -1
- package/lib-es/wallet-api/useDappLogic.js +1 -1
- package/package.json +40 -40
- package/src/__tests__/test-helpers/bridge.ts +0 -4
- package/src/bridge/impl.ts +70 -3
- package/src/bridge/useBridgeTransaction.test.ts +10 -0
- package/src/e2e/enum/Account.ts +6 -0
- package/src/e2e/enum/Provider.ts +3 -0
- package/src/e2e/speculos.ts +2 -0
- package/src/exchange/error.ts +10 -0
- package/src/exchange/swap/api/v5/actions.ts +36 -0
- package/src/exchange/swap/completeExchange.ts +14 -0
- package/src/exchange/swap/getCompleteSwapHistory.ts +1 -1
- package/src/exchange/swap/postSwapState.ts +24 -6
- package/src/exchange/swap/setBroadcastTransaction.ts +6 -2
- package/src/exchange/swap/transactionStrategies.ts +234 -0
- package/src/exchange/swap/types.ts +64 -0
- package/src/families/cardano/__snapshots__/bridge.integration.test.ts.snap +1 -0
- package/src/families/cardano/signerSerializer.ts +4 -2
- package/src/families/evm/bridge/mock.ts +1 -1
- package/src/families/evm/platformAdapter.test.ts +1 -1
- package/src/families/evm/platformAdapter.ts +1 -1
- package/src/families/evm/react.test.ts +3 -3
- package/src/families/evm/react.ts +1 -1
- package/src/families/evm/walletApiAdapter.ts +1 -1
- package/src/featureFlags/defaultFeatures.ts +1 -1
- package/src/hw/extractOnboardingState.test.ts +9 -0
- package/src/hw/extractOnboardingState.ts +12 -8
- package/src/mock/account.ts +1 -0
- package/src/wallet-api/Exchange/server.test.ts +7 -5
- package/src/wallet-api/Exchange/server.ts +344 -32
- package/src/wallet-api/useDappLogic.ts +1 -1
@@ -137,6 +137,14 @@ export const extractOnboardingState = (
|
|
137
137
|
|
138
138
|
const currentSeedWordIndex = flagsBytes[2] & currentSeedWordIndexMask;
|
139
139
|
|
140
|
+
const charonSupported = charonState !== undefined && charonState.length > 0;
|
141
|
+
const charonOnboardingBits = charonSupported ? charonState[0] & 0xf : 0;
|
142
|
+
//const charonUpdateBits = charonSupported ? (charonState[0] & 0x30) >> 4 : 0;
|
143
|
+
const charonStatus =
|
144
|
+
charonSupported && fromBitsToCharonStatusMap.has(charonOnboardingBits)
|
145
|
+
? fromBitsToCharonStatusMap.get(charonOnboardingBits)!
|
146
|
+
: null;
|
147
|
+
|
140
148
|
/*
|
141
149
|
* Once the device is seeded, there are some additional states for backing up with Charon (for devices that support it)
|
142
150
|
* There are 2 scenarios:
|
@@ -148,9 +156,11 @@ export const extractOnboardingState = (
|
|
148
156
|
if (
|
149
157
|
isOnboarded &&
|
150
158
|
[OnboardingStep.Ready, OnboardingStep.WelcomeScreen1].includes(currentOnboardingStep) &&
|
151
|
-
|
159
|
+
charonSupported
|
152
160
|
) {
|
153
|
-
currentOnboardingStep = fromBitsToOnboardingStep.get(
|
161
|
+
currentOnboardingStep = fromBitsToOnboardingStep.get(
|
162
|
+
charonOnboardingBits + CHARON_STEP_BIT_MASK,
|
163
|
+
);
|
154
164
|
|
155
165
|
if (!currentOnboardingStep) {
|
156
166
|
throw new DeviceExtractOnboardingStateError(
|
@@ -159,12 +169,6 @@ export const extractOnboardingState = (
|
|
159
169
|
}
|
160
170
|
}
|
161
171
|
|
162
|
-
const charonSupported = charonState !== undefined && charonState.length > 0;
|
163
|
-
const charonStatus =
|
164
|
-
charonSupported && fromBitsToCharonStatusMap.has(charonState[0])
|
165
|
-
? fromBitsToCharonStatusMap.get(charonState[0])!
|
166
|
-
: null;
|
167
|
-
|
168
172
|
return {
|
169
173
|
isOnboarded,
|
170
174
|
isInRecoveryMode,
|
package/src/mock/account.ts
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
import {
|
2
|
-
import { AppBranch, AppPlatform, Visibility } from "../types";
|
3
|
-
import { of } from "rxjs";
|
1
|
+
import { RpcRequest } from "@ledgerhq/wallet-api-core";
|
4
2
|
import {
|
5
3
|
ExchangeStartParams,
|
6
4
|
ExchangeStartSellParams,
|
7
5
|
ExchangeStartSwapParams,
|
8
6
|
} from "@ledgerhq/wallet-api-exchange-module";
|
9
|
-
import { RpcRequest } from "@ledgerhq/wallet-api-core";
|
10
|
-
import { genAccount } from "../../mock/account";
|
11
7
|
import { WalletContext, WalletHandlers } from "@ledgerhq/wallet-api-server";
|
8
|
+
import { of } from "rxjs";
|
9
|
+
import { genAccount } from "../../mock/account";
|
10
|
+
import { AppBranch, AppPlatform, Visibility } from "../types";
|
11
|
+
import { handlers } from "./server";
|
12
12
|
|
13
13
|
const mockTracking = {
|
14
14
|
startExchangeRequested: jest.fn(),
|
@@ -46,6 +46,7 @@ const testAppManifest = {
|
|
46
46
|
|
47
47
|
const mockUiStartExchange = jest.fn();
|
48
48
|
const mockUiCompleteExchange = jest.fn();
|
49
|
+
const mockUiSwap = jest.fn();
|
49
50
|
const mockUiError = jest.fn();
|
50
51
|
const mockIsReady = jest.fn();
|
51
52
|
|
@@ -54,6 +55,7 @@ const mockUiHooks = {
|
|
54
55
|
"custom.exchange.complete": mockUiCompleteExchange,
|
55
56
|
"custom.exchange.error": mockUiError,
|
56
57
|
"custom.isReady": mockIsReady,
|
58
|
+
"custom.exchange.swap": mockUiSwap,
|
57
59
|
};
|
58
60
|
|
59
61
|
// Mock converter id to send back the id received in params.
|
@@ -1,48 +1,58 @@
|
|
1
1
|
/* eslint-disable no-console */
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
getMainAccount,
|
4
|
+
getParentAccount,
|
5
|
+
makeEmptyTokenAccount,
|
6
|
+
} from "@ledgerhq/coin-framework/account/index";
|
7
|
+
import { findTokenById, listTokensForCryptoCurrency } from "@ledgerhq/cryptoassets";
|
8
|
+
import { decodeSwapPayload } from "@ledgerhq/hw-app-exchange";
|
9
|
+
import { CryptoOrTokenCurrency } from "@ledgerhq/types-cryptoassets";
|
10
|
+
import { Account, AccountLike, getCurrencyForAccount, TokenAccount } from "@ledgerhq/types-live";
|
3
11
|
import {
|
4
12
|
createAccountNotFound,
|
5
13
|
createCurrencyNotFound,
|
14
|
+
createUnknownError,
|
6
15
|
deserializeTransaction,
|
7
16
|
ServerError,
|
8
17
|
} from "@ledgerhq/wallet-api-core";
|
9
|
-
import {
|
10
|
-
getParentAccount,
|
11
|
-
getMainAccount,
|
12
|
-
makeEmptyTokenAccount,
|
13
|
-
} from "@ledgerhq/coin-framework/account/index";
|
14
|
-
import { CryptoOrTokenCurrency } from "@ledgerhq/types-cryptoassets";
|
15
|
-
import { AccountLike, getCurrencyForAccount, TokenAccount } from "@ledgerhq/types-live";
|
16
|
-
import { findTokenById, listTokensForCryptoCurrency } from "@ledgerhq/cryptoassets";
|
17
18
|
import {
|
18
19
|
ExchangeCompleteParams,
|
19
20
|
ExchangeCompleteResult,
|
20
21
|
ExchangeStartParams,
|
21
|
-
ExchangeStartSwapParams,
|
22
22
|
ExchangeStartResult,
|
23
|
-
ExchangeType,
|
24
23
|
ExchangeStartSellParams,
|
24
|
+
ExchangeStartSwapParams,
|
25
|
+
ExchangeSwapParams,
|
26
|
+
ExchangeType,
|
25
27
|
SwapLiveError,
|
28
|
+
SwapResult,
|
26
29
|
} from "@ledgerhq/wallet-api-exchange-module";
|
27
|
-
import {
|
28
|
-
import {
|
29
|
-
import {
|
30
|
+
import { customWrapper, RPCHandler } from "@ledgerhq/wallet-api-server";
|
31
|
+
import { BigNumber } from "bignumber.js";
|
32
|
+
import { getAccountBridge } from "../../bridge";
|
33
|
+
import { retrieveSwapPayload } from "../../exchange/swap/api/v5/actions";
|
34
|
+
import { transactionStrategy } from "../../exchange/swap/transactionStrategies";
|
35
|
+
import { ExchangeSwap } from "../../exchange/swap/types";
|
36
|
+
import { Exchange } from "../../exchange/types";
|
37
|
+
import { Transaction } from "../../generated/types";
|
30
38
|
import {
|
31
39
|
getAccountIdFromWalletAccountId,
|
32
40
|
getWalletAPITransactionSignFlowInfos,
|
33
41
|
} from "../converters";
|
34
|
-
import {
|
35
|
-
import { Exchange } from "../../exchange/types";
|
36
|
-
import { Transaction } from "../../generated/types";
|
42
|
+
import { AppManifest } from "../types";
|
37
43
|
import {
|
38
|
-
ExchangeError,
|
39
44
|
createAccounIdNotFound,
|
40
45
|
createWrongSellParams,
|
41
46
|
createWrongSwapParams,
|
47
|
+
ExchangeError,
|
42
48
|
} from "./error";
|
49
|
+
import { TrackingAPI } from "./tracking";
|
50
|
+
import { getSwapStepFromError } from "../../exchange/error";
|
51
|
+
import { postSwapCancelled } from "../../exchange/swap";
|
52
|
+
import { DeviceModelId } from "@ledgerhq/types-devices";
|
53
|
+
import { setBroadcastTransaction } from "../../exchange/swap/setBroadcastTransaction";
|
43
54
|
|
44
55
|
export { ExchangeType };
|
45
|
-
import { BigNumber } from "bignumber.js";
|
46
56
|
|
47
57
|
type Handlers = {
|
48
58
|
"custom.exchange.start": RPCHandler<
|
@@ -52,6 +62,7 @@ type Handlers = {
|
|
52
62
|
"custom.exchange.complete": RPCHandler<ExchangeCompleteResult, ExchangeCompleteParams>;
|
53
63
|
"custom.exchange.error": RPCHandler<void, SwapLiveError>;
|
54
64
|
"custom.isReady": RPCHandler<void, void>;
|
65
|
+
"custom.exchange.swap": RPCHandler<SwapResult, ExchangeSwapParams>;
|
55
66
|
};
|
56
67
|
|
57
68
|
export type CompleteExchangeUiRequest = {
|
@@ -68,21 +79,33 @@ export type CompleteExchangeUiRequest = {
|
|
68
79
|
refundAddress?: string;
|
69
80
|
payoutAddress?: string;
|
70
81
|
};
|
82
|
+
type FundStartParamsUiRequest = {
|
83
|
+
exchangeType: "FUND";
|
84
|
+
};
|
85
|
+
|
86
|
+
type SellStartParamsUiRequest = {
|
87
|
+
exchangeType: "SELL";
|
88
|
+
provider: string;
|
89
|
+
exchange: Partial<Exchange> | undefined;
|
90
|
+
};
|
91
|
+
|
92
|
+
type SwapStartParamsUiRequest = {
|
93
|
+
exchangeType: "SWAP";
|
94
|
+
provider: string;
|
95
|
+
exchange: Partial<ExchangeSwap>;
|
96
|
+
};
|
71
97
|
|
72
98
|
type ExchangeStartParamsUiRequest =
|
73
|
-
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
provider: string;
|
84
|
-
exchange: Partial<Exchange>;
|
85
|
-
};
|
99
|
+
| FundStartParamsUiRequest
|
100
|
+
| SellStartParamsUiRequest
|
101
|
+
| SwapStartParamsUiRequest;
|
102
|
+
|
103
|
+
export type SwapUiRequest = CompleteExchangeUiRequest & {
|
104
|
+
provider?: string;
|
105
|
+
fromAccountId?: string;
|
106
|
+
toAccountId?: string;
|
107
|
+
tokenCurrency?: string;
|
108
|
+
};
|
86
109
|
|
87
110
|
type ExchangeUiHooks = {
|
88
111
|
"custom.exchange.start": (params: {
|
@@ -101,6 +124,11 @@ type ExchangeUiHooks = {
|
|
101
124
|
onCancel: () => void;
|
102
125
|
}) => void;
|
103
126
|
"custom.isReady": (params: { onSuccess: () => void; onCancel: () => void }) => void;
|
127
|
+
"custom.exchange.swap": (params: {
|
128
|
+
exchangeParams: SwapUiRequest;
|
129
|
+
onSuccess: ({ operationHash, swapId }: { operationHash: string; swapId: string }) => void;
|
130
|
+
onCancel: (error: Error) => void;
|
131
|
+
}) => void;
|
104
132
|
};
|
105
133
|
|
106
134
|
export const handlers = ({
|
@@ -112,6 +140,7 @@ export const handlers = ({
|
|
112
140
|
"custom.exchange.complete": uiExchangeComplete,
|
113
141
|
"custom.exchange.error": uiError,
|
114
142
|
"custom.isReady": uiIsReady,
|
143
|
+
"custom.exchange.swap": uiSwap,
|
115
144
|
},
|
116
145
|
}: {
|
117
146
|
accounts: AccountLike[];
|
@@ -343,6 +372,228 @@ export const handlers = ({
|
|
343
372
|
}),
|
344
373
|
);
|
345
374
|
}),
|
375
|
+
"custom.exchange.swap": customWrapper<ExchangeSwapParams, SwapResult>(async params => {
|
376
|
+
if (!params) {
|
377
|
+
tracking.startExchangeNoParams(manifest);
|
378
|
+
throw new ServerError(createUnknownError({ message: "params is undefined" }));
|
379
|
+
}
|
380
|
+
|
381
|
+
const {
|
382
|
+
provider,
|
383
|
+
fromAmount,
|
384
|
+
fromAmountAtomic,
|
385
|
+
quoteId,
|
386
|
+
toNewTokenId,
|
387
|
+
customFeeConfig,
|
388
|
+
swapAppVersion,
|
389
|
+
} = params;
|
390
|
+
|
391
|
+
const trackingParams = {
|
392
|
+
provider: params.provider,
|
393
|
+
exchangeType: params.exchangeType,
|
394
|
+
};
|
395
|
+
|
396
|
+
tracking.startExchangeRequested(trackingParams);
|
397
|
+
|
398
|
+
const exchangeStartParams: ExchangeStartParamsUiRequest = extractSwapStartParam(
|
399
|
+
params,
|
400
|
+
accounts,
|
401
|
+
) as SwapStartParamsUiRequest;
|
402
|
+
|
403
|
+
const {
|
404
|
+
fromCurrency,
|
405
|
+
fromAccount,
|
406
|
+
fromParentAccount,
|
407
|
+
toCurrency,
|
408
|
+
toAccount,
|
409
|
+
toParentAccount,
|
410
|
+
} = exchangeStartParams.exchange;
|
411
|
+
|
412
|
+
if (!fromAccount || !fromCurrency) {
|
413
|
+
throw new ServerError(createAccountNotFound(params.fromAccountId));
|
414
|
+
}
|
415
|
+
|
416
|
+
const fromAccountAddress = fromParentAccount
|
417
|
+
? fromParentAccount.freshAddress
|
418
|
+
: (fromAccount as Account).freshAddress;
|
419
|
+
|
420
|
+
const toAccountAddress = toParentAccount
|
421
|
+
? toParentAccount.freshAddress
|
422
|
+
: (toAccount as Account).freshAddress;
|
423
|
+
|
424
|
+
// Step 1: Open the drawer and open exchange app
|
425
|
+
const startExchange = async () => {
|
426
|
+
console.log("LLD custom.exchange.swap uiExchangeStart", exchangeStartParams);
|
427
|
+
|
428
|
+
return new Promise<{ transactionId: string; device?: ExchangeStartResult["device"] }>(
|
429
|
+
(resolve, reject) => {
|
430
|
+
uiExchangeStart({
|
431
|
+
exchangeParams: exchangeStartParams,
|
432
|
+
onSuccess: (nonce, device) => {
|
433
|
+
tracking.startExchangeSuccess(trackingParams);
|
434
|
+
resolve({ transactionId: nonce, device });
|
435
|
+
},
|
436
|
+
onCancel: error => {
|
437
|
+
tracking.startExchangeFail(trackingParams);
|
438
|
+
reject(error);
|
439
|
+
},
|
440
|
+
});
|
441
|
+
},
|
442
|
+
);
|
443
|
+
};
|
444
|
+
|
445
|
+
const { transactionId, device: deviceInfo } = await startExchange();
|
446
|
+
|
447
|
+
const {
|
448
|
+
binaryPayload,
|
449
|
+
signature,
|
450
|
+
payinAddress,
|
451
|
+
swapId,
|
452
|
+
payinExtraId,
|
453
|
+
extraTransactionParameters,
|
454
|
+
} = await retrieveSwapPayload({
|
455
|
+
provider,
|
456
|
+
deviceTransactionId: transactionId,
|
457
|
+
fromAccountAddress,
|
458
|
+
toAccountAddress,
|
459
|
+
fromAccountCurrency: fromCurrency!.id,
|
460
|
+
toAccountCurrency: toCurrency!.id,
|
461
|
+
amount: fromAmount,
|
462
|
+
amountInAtomicUnit: fromAmountAtomic,
|
463
|
+
quoteId,
|
464
|
+
toNewTokenId,
|
465
|
+
}).catch((error: Error) => {
|
466
|
+
throw error;
|
467
|
+
});
|
468
|
+
|
469
|
+
// Complete Swap
|
470
|
+
const trackingCompleteParams = {
|
471
|
+
provider: params.provider,
|
472
|
+
exchangeType: params.exchangeType,
|
473
|
+
};
|
474
|
+
tracking.completeExchangeRequested(trackingCompleteParams);
|
475
|
+
|
476
|
+
const strategyData = {
|
477
|
+
recipient: payinAddress,
|
478
|
+
amount: fromAmountAtomic,
|
479
|
+
currency: fromCurrency as CryptoOrTokenCurrency,
|
480
|
+
customFeeConfig: customFeeConfig ?? {},
|
481
|
+
payinExtraId,
|
482
|
+
extraTransactionParameters,
|
483
|
+
};
|
484
|
+
|
485
|
+
const transaction = await getStrategy(strategyData, "swap").catch(async error => {
|
486
|
+
throw error;
|
487
|
+
});
|
488
|
+
|
489
|
+
const mainFromAccount = getMainAccount(fromAccount, fromParentAccount);
|
490
|
+
const mainFromAccountFamily = mainFromAccount.currency.family;
|
491
|
+
|
492
|
+
if (transaction.family !== mainFromAccountFamily) {
|
493
|
+
return Promise.reject(
|
494
|
+
new Error(
|
495
|
+
`Account and transaction must be from the same family. Account family: ${mainFromAccountFamily}, Transaction family: ${transaction.family}`,
|
496
|
+
),
|
497
|
+
);
|
498
|
+
}
|
499
|
+
|
500
|
+
const accountBridge = getAccountBridge(fromAccount, fromParentAccount);
|
501
|
+
|
502
|
+
/**
|
503
|
+
* 'subAccountId' is used for ETH and it's ERC-20 tokens.
|
504
|
+
* This field is ignored for BTC
|
505
|
+
*/
|
506
|
+
const subAccountId =
|
507
|
+
fromParentAccount && fromParentAccount.id !== fromAccount.id ? fromAccount.id : undefined;
|
508
|
+
|
509
|
+
const bridgeTx = accountBridge.createTransaction(fromAccount);
|
510
|
+
/**
|
511
|
+
* We append the `recipient` to the tx created from `createTransaction`
|
512
|
+
* to avoid having userGasLimit reset to null for ETH txs
|
513
|
+
* cf. libs/ledger-live-common/src/families/ethereum/updateTransaction.ts
|
514
|
+
*/
|
515
|
+
const tx = accountBridge.updateTransaction(
|
516
|
+
{
|
517
|
+
...bridgeTx,
|
518
|
+
recipient: transaction.recipient,
|
519
|
+
},
|
520
|
+
{
|
521
|
+
...transaction,
|
522
|
+
feesStrategy: params.feeStrategy.toLowerCase(),
|
523
|
+
subAccountId,
|
524
|
+
},
|
525
|
+
);
|
526
|
+
|
527
|
+
// Get amountExpectedTo and magnitudeAwareRate from binary payload
|
528
|
+
const decodePayload = await decodeSwapPayload(binaryPayload);
|
529
|
+
const amountExpectedTo = new BigNumber(decodePayload.amountToWallet.toString());
|
530
|
+
const magnitudeAwareRate = tx.amount && amountExpectedTo.dividedBy(tx.amount);
|
531
|
+
const refundAddress = decodePayload.refundAddress;
|
532
|
+
const payoutAddress = decodePayload.payoutAddress;
|
533
|
+
|
534
|
+
// tx.amount should be BigNumber
|
535
|
+
tx.amount = new BigNumber(tx.amount);
|
536
|
+
|
537
|
+
return new Promise((resolve, reject) =>
|
538
|
+
uiSwap({
|
539
|
+
exchangeParams: {
|
540
|
+
exchangeType: ExchangeType.SWAP,
|
541
|
+
provider: params.provider,
|
542
|
+
transaction: tx,
|
543
|
+
signature: signature,
|
544
|
+
binaryPayload: binaryPayload,
|
545
|
+
exchange: {
|
546
|
+
fromAccount,
|
547
|
+
fromParentAccount,
|
548
|
+
toAccount,
|
549
|
+
toParentAccount,
|
550
|
+
fromCurrency: fromCurrency!,
|
551
|
+
toCurrency: toCurrency!,
|
552
|
+
},
|
553
|
+
feesStrategy: params.feeStrategy,
|
554
|
+
swapId: swapId,
|
555
|
+
amountExpectedTo: amountExpectedTo.toNumber(),
|
556
|
+
magnitudeAwareRate,
|
557
|
+
refundAddress,
|
558
|
+
payoutAddress,
|
559
|
+
},
|
560
|
+
onSuccess: ({ operationHash, swapId }: { operationHash: string; swapId: string }) => {
|
561
|
+
tracking.completeExchangeSuccess({
|
562
|
+
...trackingParams,
|
563
|
+
currency: transaction.family,
|
564
|
+
});
|
565
|
+
|
566
|
+
setBroadcastTransaction({
|
567
|
+
provider,
|
568
|
+
result: { operation: operationHash, swapId },
|
569
|
+
sourceCurrencyId: fromCurrency.id,
|
570
|
+
targetCurrencyId: toCurrency?.id,
|
571
|
+
hardwareWalletType: deviceInfo?.modelId as DeviceModelId,
|
572
|
+
swapAppVersion,
|
573
|
+
});
|
574
|
+
|
575
|
+
resolve({ operationHash, swapId });
|
576
|
+
},
|
577
|
+
onCancel: error => {
|
578
|
+
postSwapCancelled({
|
579
|
+
provider: provider,
|
580
|
+
swapId: swapId,
|
581
|
+
swapStep: getSwapStepFromError(error),
|
582
|
+
statusCode: error.name,
|
583
|
+
errorMessage: error.message,
|
584
|
+
sourceCurrencyId: fromCurrency.id,
|
585
|
+
targetCurrencyId: toCurrency?.id,
|
586
|
+
hardwareWalletType: deviceInfo?.modelId as DeviceModelId,
|
587
|
+
swapType: quoteId ? "fixed" : "float",
|
588
|
+
swapAppVersion,
|
589
|
+
});
|
590
|
+
|
591
|
+
reject(error);
|
592
|
+
},
|
593
|
+
}),
|
594
|
+
);
|
595
|
+
}),
|
596
|
+
|
346
597
|
"custom.isReady": customWrapper<void, void>(async () => {
|
347
598
|
return new Promise((resolve, reject) =>
|
348
599
|
uiIsReady({
|
@@ -402,8 +653,10 @@ function extractSwapStartParam(
|
|
402
653
|
exchange: {
|
403
654
|
fromAccount,
|
404
655
|
fromParentAccount,
|
656
|
+
fromCurrency: getCurrencyForAccount(fromAccount),
|
405
657
|
toAccount: newTokenAccount ? newTokenAccount : toAccount,
|
406
658
|
toParentAccount: newTokenAccount ? toAccount : toParentAccount,
|
659
|
+
toCurrency: getCurrencyForAccount(toAccount),
|
407
660
|
},
|
408
661
|
};
|
409
662
|
}
|
@@ -468,3 +721,62 @@ async function getToCurrency(
|
|
468
721
|
|
469
722
|
return newTokenAccount?.token ?? getCurrencyForAccount(toAccount);
|
470
723
|
}
|
724
|
+
|
725
|
+
interface StrategyParams {
|
726
|
+
recipient: string;
|
727
|
+
amount: BigNumber | number | string;
|
728
|
+
currency: CryptoOrTokenCurrency;
|
729
|
+
customFeeConfig?: Record<string, unknown>;
|
730
|
+
payinExtraId?: string;
|
731
|
+
extraTransactionParameters?: string;
|
732
|
+
}
|
733
|
+
|
734
|
+
async function getStrategy(
|
735
|
+
{
|
736
|
+
recipient,
|
737
|
+
amount,
|
738
|
+
currency,
|
739
|
+
customFeeConfig,
|
740
|
+
payinExtraId,
|
741
|
+
extraTransactionParameters,
|
742
|
+
}: StrategyParams,
|
743
|
+
customErrorType?: any,
|
744
|
+
): Promise<Transaction> {
|
745
|
+
const family =
|
746
|
+
currency.type === "TokenCurrency"
|
747
|
+
? (currency.parentCurrency?.family as Transaction["family"])
|
748
|
+
: (currency.family as Transaction["family"]);
|
749
|
+
|
750
|
+
if (!family) {
|
751
|
+
throw new Error(`TokenCurrency missing parentCurrency family: ${currency.id}`);
|
752
|
+
}
|
753
|
+
|
754
|
+
// Remove unsupported utxoStrategy for now
|
755
|
+
if (customFeeConfig?.utxoStrategy) {
|
756
|
+
delete customFeeConfig.utxoStrategy;
|
757
|
+
}
|
758
|
+
|
759
|
+
// Normalize family key for strategy lookup
|
760
|
+
const familyKey = family === "evm" ? "ethereum" : family;
|
761
|
+
const strategy = transactionStrategy?.[familyKey];
|
762
|
+
|
763
|
+
if (!strategy) {
|
764
|
+
throw new Error(`No transaction strategy found for family: ${familyKey}`);
|
765
|
+
}
|
766
|
+
|
767
|
+
try {
|
768
|
+
return await strategy({
|
769
|
+
family,
|
770
|
+
amount,
|
771
|
+
recipient,
|
772
|
+
customFeeConfig: customFeeConfig || {},
|
773
|
+
payinExtraId,
|
774
|
+
extraTransactionParameters,
|
775
|
+
customErrorType,
|
776
|
+
});
|
777
|
+
} catch (error) {
|
778
|
+
throw new Error(
|
779
|
+
`Failed to execute transaction strategy for family: ${familyKey}. Reason: ${(error as Error).message}`,
|
780
|
+
);
|
781
|
+
}
|
782
|
+
}
|
@@ -12,7 +12,7 @@ import { findTokenByAddress, getCryptoCurrencyById } from "@ledgerhq/cryptoasset
|
|
12
12
|
import { prepareMessageToSign } from "../hw/signMessage/index";
|
13
13
|
import { CurrentAccountHistDB, UiHook, usePermission } from "./react";
|
14
14
|
import BigNumber from "bignumber.js";
|
15
|
-
import { safeEncodeEIP55 } from "@ledgerhq/coin-evm/
|
15
|
+
import { safeEncodeEIP55 } from "@ledgerhq/coin-evm/utils";
|
16
16
|
import { SmartWebsocket } from "./SmartWebsocket";
|
17
17
|
import { stripHexPrefix } from "./helpers";
|
18
18
|
import { getTxType } from "./utils/txTrackingHelper";
|