Skip to content

Commit

Permalink
[SWAP] Integrate SPL Token extra calls for AppExchange (#8517)
Browse files Browse the repository at this point in the history
* feat: add trusted service calls

Signed-off-by: Stéphane Prohaszka <[email protected]>

* feat: add pki apdu calls

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: add more use case into test

Signed-off-by: Stéphane Prohaszka <[email protected]>

* feat: add spl token management in swap

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: add test url for services

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: rename integration test

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: move cal and trust services in their own package

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: reorg cal files

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: rename integ test files

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: extract loadPKI apdu to a bolos dedicated package

Signed-off-by: Stéphane Prohaszka <[email protected]>

* feat: expose different PKIError

Signed-off-by: Stéphane Prohaszka <[email protected]>

* feat: create dedicated error for loadPKI failure

Signed-off-by: Stéphane Prohaszka <[email protected]>

* fix: import issue

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: update lock file

Signed-off-by: Stéphane Prohaszka <[email protected]>

* fix: missing readme info and unit test failure

Signed-off-by: Stéphane Prohaszka <[email protected]>

* fix: remove unused function

Signed-off-by: Stéphane Prohaszka <[email protected]>

* fix: remove unused library

Signed-off-by: Stéphane Prohaszka <[email protected]>

* chore: feedback

Signed-off-by: Stéphane Prohaszka <[email protected]>

---------

Signed-off-by: Stéphane Prohaszka <[email protected]>
  • Loading branch information
sprohaszka-ledger authored Dec 2, 2024
1 parent 49bd68b commit 2673c1d
Show file tree
Hide file tree
Showing 47 changed files with 1,334 additions and 146 deletions.
8 changes: 8 additions & 0 deletions .changeset/shy-insects-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@ledgerhq/hw-bolos": minor
"@ledgerhq/ledger-trust-service": minor
"@ledgerhq/ledger-cal-service": minor
"@ledgerhq/live-common": minor
---

Extract Ledger services (CAL and Trust) calls and expose new BOLOS APDU
63 changes: 32 additions & 31 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -43,39 +43,40 @@ libs/ledgerjs/packages/hw-app-*/ @ledgerhq/live-blockcha
libs/ledgerjs/packages/types-cryptoassets/ @ledgerhq/live-blockchain-support
libs/live-config/ @ledgerhq/live-blockchain-support
libs/live-network/ @ledgerhq/live-blockchain-support
libs/live-services/ @ledgerhq/live-blockchain-support

# PTX team
apps/cli/src/commands/ptx @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/components/ProviderIcon/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/components/WebPTXPlayer/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/hooks/swap-migrations/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/modals/Platform/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/modals/StartStake/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/reducers/swap.ts @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/earn/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/exchange/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/stake/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/swapWeb/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal @ledgerhq/ptx
apps/cli/src/commands/ptx @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/components/ProviderIcon/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/components/WebPTXPlayer/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/hooks/swap-migrations/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/modals/Platform/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/modals/StartStake/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/reducers/swap.ts @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/earn/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/exchange/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/stake/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/screens/swapWeb/ @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal @ledgerhq/ptx
apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal_deprecated @ledgerhq/ptx
apps/ledger-live-mobile/src/families/evm/StakingDrawer/ @ledgerhq/ptx
apps/ledger-live-mobile/src/families/evm/StakingDrawer_deprecated/ @ledgerhq/ptx
apps/ledger-live-mobile/src/actions/earn.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/actions/swap.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/components/ProviderIcon/ @ledgerhq/ptx
apps/ledger-live-mobile/src/components/Stake/ @ledgerhq/ptx
apps/ledger-live-mobile/src/components/WebPTXPlayer/ @ledgerhq/ptx
apps/ledger-live-mobile/src/reducers/earn.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/reducers/swap.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/screens/Exchange/ @ledgerhq/ptx
apps/ledger-live-mobile/src/screens/PTX/ @ledgerhq/ptx
apps/ledger-live-mobile/src/screens/Swap/ @ledgerhq/ptx
libs/ledger-live-common/src/exchange/ @ledgerhq/ptx
libs/exchange-module/ @ledgerhq/ptx
libs/wallet-api-acre-module/ @ledgerhq/ptx
libs/ledgerjs/packages/hw-app-exchange/ @ledgerhq/ptx
libs/ledger-live-common/src/cal/partners*.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/families/evm/StakingDrawer/ @ledgerhq/ptx
apps/ledger-live-mobile/src/families/evm/StakingDrawer_deprecated/ @ledgerhq/ptx
apps/ledger-live-mobile/src/actions/earn.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/actions/swap.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/components/ProviderIcon/ @ledgerhq/ptx
apps/ledger-live-mobile/src/components/Stake/ @ledgerhq/ptx
apps/ledger-live-mobile/src/components/WebPTXPlayer/ @ledgerhq/ptx
apps/ledger-live-mobile/src/reducers/earn.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/reducers/swap.ts @ledgerhq/ptx
apps/ledger-live-mobile/src/screens/Exchange/ @ledgerhq/ptx
apps/ledger-live-mobile/src/screens/PTX/ @ledgerhq/ptx
apps/ledger-live-mobile/src/screens/Swap/ @ledgerhq/ptx
libs/ledger-live-common/src/exchange/ @ledgerhq/ptx
libs/exchange-module/ @ledgerhq/ptx
libs/wallet-api-acre-module/ @ledgerhq/ptx
libs/ledgerjs/packages/hw-app-exchange/ @ledgerhq/ptx
libs/live-services/cal/src/partners/ @ledgerhq/ptx


# Wallet API team
Expand All @@ -91,7 +92,7 @@ libs/ledger-live-common/src/wallet-api/ @ledgerhq/wallet-api
**/platformAdapter.ts @ledgerhq/wallet-api
**/walletApiAdapter.ts @ledgerhq/wallet-api
**/liveapp-sdk.spec.ts @ledgerhq/wallet-api
**/confirmTransaction.spec.ts @ledgerhq/wallet-api
**/confirmTransaction.spec.ts @ledgerhq/wallet-api
**/wallet-api.spec.ts @ledgerhq/wallet-api
**/wallet-api.spec.ts-snapshots/ @ledgerhq/wallet-api
**/dapp.spec.ts @ledgerhq/wallet-api
Expand Down
1 change: 1 addition & 0 deletions libs/ledger-live-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
"@ledgerhq/hw-app-xrp": "workspace:^",
"@ledgerhq/hw-transport": "workspace:^",
"@ledgerhq/hw-transport-mocker": "workspace:^",
"@ledgerhq/ledger-cal-service": "workspace:^",
"@ledgerhq/live-app-sdk": "^0.8.1",
"@ledgerhq/live-config": "workspace:^",
"@ledgerhq/live-countervalues": "workspace:^",
Expand Down
13 changes: 0 additions & 13 deletions libs/ledger-live-common/src/cal/index.ts

This file was deleted.

4 changes: 2 additions & 2 deletions libs/ledger-live-common/src/exchange/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { valid, gte } from "semver";
import type { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
import { getEnv } from "@ledgerhq/live-env";
import { findExchangeCurrencyConfig as findProdExchangeCurrencyConfig } from "@ledgerhq/cryptoassets";
import { findCurrencyData } from "../cal";
import calService from "@ledgerhq/ledger-cal-service";
// Minimum version of a currency app which has exchange capabilities, meaning it can be used
// for sell/swap, and do silent signing.
const exchangeSupportAppVersions = {
Expand Down Expand Up @@ -42,7 +42,7 @@ export const getCurrencyExchangeConfig = async (
let res;
try {
const env = getEnv("MOCK_EXCHANGE_TEST_CONFIG") ? "test" : "prod";
res = await findCurrencyData(currency.id, env);
res = await calService.findCurrencyData(currency.id, { env });

if (!res) {
throw new Error("Missing primary config");
Expand Down
4 changes: 2 additions & 2 deletions libs/ledger-live-common/src/exchange/providers/sell.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ExchangeProviderNameAndSignature } from ".";
import { getProvidersData } from "../../cal";
import calService from "@ledgerhq/ledger-cal-service";

const testSellProvider: ExchangeProviderNameAndSignature = {
name: "SELL_TEST",
Expand All @@ -19,7 +19,7 @@ const testSellProvider: ExchangeProviderNameAndSignature = {

export const fetchAndMergeProviderData = async env => {
try {
const sellProvidersData = await getProvidersData({
const sellProvidersData = await calService.getProvidersData({
type: "sell",
...env,
});
Expand Down
85 changes: 4 additions & 81 deletions libs/ledger-live-common/src/exchange/providers/swap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getEnv } from "@ledgerhq/live-env";
import { getTestProviderInfo, type ExchangeProviderNameAndSignature } from ".";
import { findCurrencyData, getProvidersCDNData, getProvidersData } from "../../cal";
import calService, { SWAP_DATA_CDN } from "@ledgerhq/ledger-cal-service";
import { isIntegrationTestEnv } from "../swap/utils/isIntegrationTestEnv";

export type SwapProviderConfig = {
Expand All @@ -22,83 +22,6 @@ export type AdditionalProviderConfig = SwapProviderConfig & { type: "DEX" | "CEX

export type ProviderConfig = CEXProviderConfig | DEXProviderConfig;

export const SWAP_DATA_CDN: Record<string, AdditionalProviderConfig> = {
exodus: {
type: "CEX",
useInExchangeApp: true,
displayName: "Exodus",
termsOfUseUrl: "https://www.exodus.com/terms/",
supportUrl: "mailto:[email protected]",
mainUrl: "https://www.exodus.com/",
needsKYC: false,
version: 2,
},
changelly: {
type: "CEX",
useInExchangeApp: true,
displayName: "Changelly",
termsOfUseUrl: "https://changelly.com/terms-of-use",
supportUrl: "https://support.changelly.com/en/support/home",
mainUrl: "https://changelly.com/",
needsKYC: false,
},
cic: {
needsKYC: false,
displayName: "CIC",
type: "CEX",
useInExchangeApp: true,
termsOfUseUrl: "https://criptointercambio.com/terms-of-use",
supportUrl: "https://criptointercambio.com/en/about",
mainUrl: "https://criptointercambio.com/",
},
moonpay: {
needsKYC: true,
displayName: "MoonPay",
type: "CEX",
useInExchangeApp: true,
termsOfUseUrl: "https://www.moonpay.com/legal/terms_of_use_row",
supportUrl: "https://support.moonpay.com/",
mainUrl: "https://www.moonpay.com/",
},
oneinch: {
type: "DEX",
needsKYC: false,
useInExchangeApp: false,
displayName: "1inch",
termsOfUseUrl: "https://1inch.io/assets/1inch_network_terms_of_use.pdf",
supportUrl: "https://help.1inch.io/en/",
mainUrl: "https://1inch.io/",
},
paraswap: {
type: "DEX",
needsKYC: false,
useInExchangeApp: false,
displayName: "Paraswap",
termsOfUseUrl: "https://files.paraswap.io/tos_v4.pdf",
supportUrl: "https://help.paraswap.io/en/",
mainUrl: "https://www.paraswap.io/",
},
thorswap: {
type: "DEX",
useInExchangeApp: true,
displayName: "THORChain",
termsOfUseUrl: "https://docs.thorswap.finance/thorswap/resources/terms-of-service",
supportUrl: "https://ledgerhelp.swapkit.dev/",
mainUrl: "https://www.thorswap.finance/",
needsKYC: false,
},
uniswap: {
type: "DEX",
useInExchangeApp: false,
displayName: "Uniswap",
termsOfUseUrl:
"https://support.uniswap.org/hc/en-us/articles/30935100859661-Uniswap-Labs-Terms-of-Service",
supportUrl: "mailto:[email protected]",
mainUrl: "https://uniswap.org/",
needsKYC: false,
},
};

const DEFAULT_SWAP_PROVIDERS: Record<string, ProviderConfig & Partial<AdditionalProviderConfig>> = {
changelly: {
name: "Changelly",
Expand Down Expand Up @@ -265,7 +188,7 @@ export const getSwapProvider = async (
* @deprecated Use cal module `findCurrencyData` method.
*/
export const findExchangeCurrencyData = async (currencyId: string): Promise<CurrencyData> =>
findCurrencyData(currencyId);
calService.findCurrencyData(currencyId);

export const fetchAndMergeProviderData = async env => {
if (providerDataCache) {
Expand All @@ -274,8 +197,8 @@ export const fetchAndMergeProviderData = async env => {

try {
const [providersData, providersExtraData] = await Promise.all([
getProvidersData({ type: "swap", ...env }),
getProvidersCDNData(),
calService.getProvidersData({ type: "swap", ...env }),
calService.getProvidersCDNData(),
]);
const finalProvidersData = mergeProviderData(providersData, providersExtraData);
providerDataCache = finalProvidersData;
Expand Down
30 changes: 30 additions & 0 deletions libs/ledger-live-common/src/exchange/swap/completeExchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const completeExchange = (
}

const exchange = createExchange(transport, exchangeType, rateType, providerConfig.version);

const refundAccount = getMainAccount(fromAccount, fromParentAccount);
const payoutAccount = getMainAccount(toAccount, toParentAccount);
const accountBridge = getAccountBridge(refundAccount);
Expand Down Expand Up @@ -136,6 +137,21 @@ const completeExchange = (
);
if (unsubscribed) return;

//-- Special case of SPLToken
//- NOT READY YET
// //TODO: generalize this case when another blockchain has the same requirement
// if (isSPLTokenAccount(fromAccount) || isSPLTokenAccount(toAccount)) {
// sendPKI(transport);
// }

// if (isSPLTokenAccount(fromAccount)) {
// //TODO Call AppExchange with TrustedService info
// }
// if (isSPLTokenAccount(toAccount)) {
// //TODO Call AppExchange with TrustedService info
// }

//-- CHECK_PAYOUT_ADDRESS
const { config: payoutAddressConfig, signature: payoutAddressConfigSignature } =
await getCurrencyExchangeConfig(payoutCurrency);

Expand Down Expand Up @@ -242,6 +258,20 @@ const completeExchange = (
});
};

// function isSPLTokenAccount(account: AccountLike): boolean {
// return account.type !== "TokenAccount" && account.currency.id === "solana";
// }

// async function sendPKI(transport: Transport) {
// // FIXME: version number hardcoded
// const { descriptor, signature } = await calService.getCertificate(
// transport.deviceModel!.id,
// "1.3.0",
// );

// await loadPKI(transport, "TRUSTED_NAME", descriptor, signature);
// }

function convertSignature(signature: string, exchangeType: ExchangeTypes): Buffer {
return exchangeType === ExchangeTypes.SwapNg
? Buffer.from(signature, "base64url")
Expand Down
3 changes: 2 additions & 1 deletion libs/ledger-live-common/src/exchange/swap/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { SWAP_DATA_CDN } from "@ledgerhq/ledger-cal-service";
import { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
import { Account, AccountLike, SubAccount } from "@ledgerhq/types-live";
import { getAccountCurrency, makeEmptyTokenAccount } from "../../../account";
import { getSwapProvider, SWAP_DATA_CDN } from "../../providers/swap";
import { getSwapProvider } from "../../providers/swap";

export const FILTER = {
centralised: "centralised",
Expand Down
20 changes: 20 additions & 0 deletions libs/ledger-services/cal/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
env: {
browser: true,
es6: true,
},
overrides: [
{
files: ["src/**/*.test.ts"],
env: {
"jest/globals": true,
},
plugins: ["jest"],
},
],
rules: {
"no-console": ["error", { allow: ["warn", "error"] }],
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "warn",
},
};
8 changes: 8 additions & 0 deletions libs/ledger-services/cal/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
// `workerThreads: true` is required for validating object with `bigint` values
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
testPathIgnorePatterns: ["lib/", "lib-es/", ".*\\.integ\\.test\\.[tj]s"],
workerThreads: true,
};
8 changes: 8 additions & 0 deletions libs/ledger-services/cal/jest.integ.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
testRegex: ".integ.test.ts$",
testPathIgnorePatterns: ["lib/", "lib-es/"],
setupFiles: ["dotenv/config"],
};
Loading

0 comments on commit 2673c1d

Please sign in to comment.