Skip to content

Commit

Permalink
feat: migrate lot of dependencies. Use ExchangeSDK in dev mode
Browse files Browse the repository at this point in the history
Signed-off-by: Stéphane Prohaszka <stephane.prohaszka@ledger.fr>
  • Loading branch information
sprohaszka-ledger committed Feb 7, 2024
1 parent c8022fa commit a36cb9b
Show file tree
Hide file tree
Showing 10 changed files with 1,984 additions and 2,079 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"import",
"@typescript-eslint",
"react-hooks",
"react"
"react",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"extends": [
"airbnb-typescript/base",
Expand Down
1 change: 0 additions & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
Expand Down
6 changes: 4 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// next.config.js
module.exports = {
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
Expand All @@ -22,3 +22,5 @@ module.exports = {
];
},
};

module.exports = nextConfig;
35 changes: 20 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,45 +1,50 @@
{
"name": "platform-app-coinify",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"clean": "rm -rf node_modules",
"format:check": "prettier --check 'src/**' 'pages/**'",
"format:fix": "prettier --write 'src/**' 'pages/**'",
"lint:check": "eslint --cache src/** pages/**",
"lint:fix": "eslint --cache --fix src/** pages/**"
},
"dependencies": {
"@ledgerhq/live-app-sdk": "0.6.0",
"@ledgerhq/react-ui": "^0.7.2",
"@babel/core": "^7.23.9",
"@ledgerhq/exchange-sdk": "file:./../exchange-sdk/lib",
"@ledgerhq/react-ui": "^0.14.14",
"@ledgerhq/wallet-api-client": "^1.5.0",
"@types/react-transition-group": "^4.4.3",
"bignumber.js": "^9.0.1",
"bignumber.js": "^9.1.2",
"color": "^4.0.1",
"modern-normalize": "^1.1.0",
"next": "11.1.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"next": "^14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-transition-group": "^4.4.2",
"styled-components": "^5.2.3"
"styled-components": "^6.1.8"
},
"devDependencies": {
"@types/color": "^3.0.2",
"@types/react": "17.0.30",
"@types/node": "20.11.16",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@types/styled-components": "^5.1.15",
"@typescript-eslint/eslint-plugin": "^5.1.0",
"@typescript-eslint/parser": "^5.1.0",
"babel-plugin-styled-components": "^1.13.3",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"babel-plugin-styled-components": "^2.1.4",
"eslint": "^8.9.0",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-next": "11.1.2",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-next": "^14.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"prettier": "^2.4.1",
"typescript": "4.4.4"
"typescript": "^4.8.3"
}
}
4 changes: 2 additions & 2 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useRouter } from "next/router";
import { useApi } from "../src/providers/LedgerLiveSDKProvider";

import Coinify from "../src/Coinify";
import { Account, Currency } from "@ledgerhq/live-app-sdk";
import { Account, Currency } from "@ledgerhq/wallet-api-client";

type QueryParams = {
accountId?: string;
Expand Down Expand Up @@ -35,7 +35,7 @@ const Page = () => {
const api = useApi();

useEffect(() => {
Promise.all([api.listAccounts(), api.listCurrencies()])
Promise.all([api.walletAPI.account.list(), api.walletAPI.currency.list()])
.then(([accounts, currencies]) => {
setState({
data: { accounts, currencies },
Expand Down
98 changes: 42 additions & 56 deletions src/Coinify/CoinifyWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
// @flow

import React, { useState, useEffect, useRef, useCallback } from "react";
import { BigNumber } from "bignumber.js";
import styled from "styled-components";
import querystring from "querystring";
import {
BitcoinTransaction,
ExchangeType,
FAMILIES,
FeesLevel,
} from "@ledgerhq/live-app-sdk";
import type { Account, Unit } from "@ledgerhq/live-app-sdk";
import type { Account } from "@ledgerhq/wallet-api-client";
import { useApi } from "../providers/LedgerLiveSDKProvider";
import { ExchangeSDK } from "@ledgerhq/exchange-sdk";
import BigNumber from "bignumber.js";

const parseCurrencyUnit = (unit: Unit, valueString: string): BigNumber => {
const str = valueString.replace(/,/g, ".");
const value = new BigNumber(str);
if (value.isNaN()) return new BigNumber(0);
return value.times(new BigNumber(10).pow(unit.magnitude)).integerValue();
};
// const parseCurrencyUnit = (unit: Unit, valueString: string): BigNumber => {
// const str = valueString.replace(/,/g, ".");
// const value = new BigNumber(str);
// if (value.isNaN()) return new BigNumber(0);
// return value.times(new BigNumber(10).pow(unit.magnitude)).integerValue();
// };

type CoinifyConfig = {
host: string;
Expand Down Expand Up @@ -83,7 +78,7 @@ const CoinifyWidget = ({
cryptoAmount,
primaryColor,
}: Props) => {
const api = useApi();
const api: ExchangeSDK = useApi();

const env = new URLSearchParams(window.location.search).get("env") || "prod";

Expand Down Expand Up @@ -230,7 +225,14 @@ const CoinifyWidget = ({
}, [coinifyConfig.host, account, mode]);

const setTransactionId = useCallback(
(txId) => {
(txId: string): Promise<{
inAmount: number;
transferIn: unknown;
providerSig: {
payload: string;
signature: string;
}
}> => {
return new Promise((resolve) => {
const onReply = (e: any) => {
if (!e.isTrusted || e.origin !== coinifyConfig.host || !e.data)
Expand All @@ -241,7 +243,9 @@ const CoinifyWidget = ({
resolve(context);
}
};

window.addEventListener("message", onReply, { once: true });

if (widgetRef.current?.contentWindow) {
widgetRef.current.contentWindow.postMessage(
{
Expand All @@ -255,8 +259,7 @@ const CoinifyWidget = ({
},
coinifyConfig.host
);
}
if (widgetRef.current?.contentWindow) {

widgetRef.current.contentWindow.postMessage(
{
type: "event",
Expand All @@ -274,45 +277,28 @@ const CoinifyWidget = ({
);

const initSellFlow = useCallback(async () => {
const nonce = await api
.startExchange({
exchangeType: ExchangeType.SELL,
})
.catch((e) => {
throw e;
});

const coinifyContext: any = await setTransactionId(nonce);

const tx: BitcoinTransaction = {
family: FAMILIES.BITCOIN,
amount: parseCurrencyUnit(
{
magnitude: 8,
name: "bitcoin",
code: "BTC",
},
coinifyContext.inAmount.toString(10)
),
recipient: coinifyContext.transferIn.details.account,
const getSellPayload = async (nonce: string) => {
const coinifyContext = await setTransactionId(nonce);

return {
recipientAddress: (coinifyContext.transferIn as any).details.account,
amount: new BigNumber(coinifyContext.inAmount.toString(10)),
binaryPayload: Buffer.from(
coinifyContext.providerSig.payload,
"ascii"
),
signature: Buffer.from(
coinifyContext.providerSig.signature,
"base64"
),
};
};

const signedTx = await api
.completeExchange({
provider: "coinify",
fromAccountId: account.id,
transaction: tx,
binaryPayload: Buffer.from(coinifyContext.providerSig.payload, "ascii"),
signature: Buffer.from(coinifyContext.providerSig.signature, "base64"),
feesStrategy: FeesLevel.Medium,
exchangeType: ExchangeType.SELL,
})
.catch((e) => {
throw e;
await api.sell({
accountId: account.id,
amount: new BigNumber(0),
feeStrategy: "MEDIUM",
getSellPayload,
});

// signedTx is not actually used by the widget
return signedTx;
}, [account.id, api, setTransactionId]);

useEffect(() => {
Expand Down Expand Up @@ -350,7 +336,7 @@ const CoinifyWidget = ({
// FIXME: VERIFY ADDRESS

// FIXME: handle cancel / error
api
api.walletAPI.account
.receive(account.id)
.then((verifiedAddress) => handleOnResultBuy(verifiedAddress))
.catch((error: unknown) => console.error(error));
Expand Down
11 changes: 5 additions & 6 deletions src/Coinify/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import React, { useState, useCallback, useEffect, useRef } from "react";

import styled from "styled-components";

import type { Account, Currency } from "@ledgerhq/live-app-sdk";
import type { Account, Currency } from "@ledgerhq/wallet-api-client";

import CoinifyWidget from "./CoinifyWidget";
import { Button, Icon, Text } from "@ledgerhq/react-ui";
import { Button, Icon, Text, Chip } from "@ledgerhq/react-ui";

import { Chip } from "@ledgerhq/react-ui/components/tabs";
import { useApi } from "../providers/LedgerLiveSDKProvider";

const Layout = styled.div`
Expand Down Expand Up @@ -135,10 +134,10 @@ const Coinify = ({
return;
}

const account = await api
.requestAccount({
const account = await api.walletAPI.account
.request({
// FIXME: use a 'getSelectableCurrencies' function instead of ternarry
currencies:
currencyIds:
selectedMode === "onRamp"
? SELECTABLE_CURRENCIES_ONRAMP
: SELECTABLE_CURRENCIES_OFFRAMP,
Expand Down
14 changes: 6 additions & 8 deletions src/providers/LedgerLiveSDKProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { createContext, useState, useEffect, useContext } from "react";
import LedgerLiveApi, { WindowMessageTransport } from "@ledgerhq/live-app-sdk";
import { ExchangeSDK } from "@ledgerhq/exchange-sdk";

type LedgerLiveSDKContextType = {
api?: LedgerLiveApi;
api?: ExchangeSDK;
};

const defaultContext: LedgerLiveSDKContextType = { api: undefined };
Expand All @@ -15,18 +15,16 @@ const LedgerLiveSDKProvider = ({
}: {
children: React.ReactNode;
}): React.ReactElement => {
const [api, setApi] = useState<LedgerLiveApi | null>(null);
const [api, setApi] = useState<ExchangeSDK | null>(null);

useEffect(() => {
const llapi = new LedgerLiveApi(new WindowMessageTransport());
const llapi = new ExchangeSDK("coinify");

setApi(llapi);

llapi.connect();

return () => {
setApi(null);
void llapi.disconnect();
llapi.disconnect();
};
}, []);

Expand All @@ -41,7 +39,7 @@ const LedgerLiveSDKProvider = ({
);
};

export const useApi = () => {
export const useApi = (): ExchangeSDK => {
const { api } = useContext(LedgerLiveSDKContext);

// This should theoretically never happen
Expand Down
19 changes: 15 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"target": "esnext",
"module": "esnext",
"jsx": "preserve",
"lib": ["dom", "es2017"],
"lib": [
"dom",
"es2017"
],
"moduleResolution": "node",
"allowJs": true,
"noEmit": true,
Expand All @@ -18,8 +21,16 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true
"isolatedModules": true,
"incremental": true
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"src/**/*.tsx"
]
}
Loading

0 comments on commit a36cb9b

Please sign in to comment.