Skip to content

Commit

Permalink
Ledger Live new API updates (#780)
Browse files Browse the repository at this point in the history
This PR moves the implementation of the Ledger Live Bitcoin provider and
connector from Orangekit to the Acre dapp. We decided to keep this
implementation on the Acre side because there are many implementation
details specified for Acre. Here we also use new functions from the new
Ledger Live Wallet API.
  • Loading branch information
nkuba authored Oct 31, 2024
2 parents aadf666 + 5de537c commit 5540871
Show file tree
Hide file tree
Showing 26 changed files with 1,109 additions and 323 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@
"permissions": [
"account.request",
"account.list",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast",
"bitcoin.getXPub",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
"custom.acre.messageSign"
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
"domains": ["http://*"],
"type": "walletApp"
Expand Down
7 changes: 2 additions & 5 deletions dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@
"permissions": [
"account.request",
"account.list",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast",
"bitcoin.getXPub",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
"custom.acre.messageSign"
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
"domains": ["http://*"],
"type": "walletApp"
Expand Down
7 changes: 2 additions & 5 deletions dapp/manifests/ledger-live/ledger-live-manifest-testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@
"permissions": [
"account.request",
"account.list",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast",
"bitcoin.getXPub",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
"custom.acre.messageSign"
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
"domains": ["http://*"],
"type": "walletApp"
Expand Down
7 changes: 2 additions & 5 deletions dapp/manifests/ledger-live/ledger-manifest-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@
"permissions": [
"account.request",
"account.list",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast",
"bitcoin.getXPub",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
"custom.acre.messageSign"
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
"domains": ["http://*"],
"type": "walletApp"
Expand Down
8 changes: 5 additions & 3 deletions dapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@
"lint:js:fix": "eslint . --fix",
"lint:config": "prettier -c '**/*.@(json|yaml|toml)'",
"lint:config:fix": "prettier -w '**/*.@(json|yaml|toml)'",
"test": "vitest",
"test": "vitest --reporter=verbose",
"generate:manifests": "for env in development testnet mainnet; do mustache config/$env.json ./manifests/ledger-live/ledger-manifest-template.json > ./manifests/ledger-live/ledger-live-manifest-$env.json; done"
},
"dependencies": {
"@acre-btc/sdk": "workspace:*",
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@orangekit/react": "1.0.0-beta.33-dev.7",
"@orangekit/sign-in-with-wallet": "1.0.0-beta.6",
"@ledgerhq/wallet-api-acre-module": "0.1.0-nightly.0",
"@ledgerhq/wallet-api-client": "1.6.0",
"@orangekit/react": "1.0.0-beta.33",
"@orangekit/sign-in-with-wallet": "1.0.0-beta.6",
"@reduxjs/toolkit": "^2.2.0",
"@rehooks/local-storage": "^2.4.5",
"@safe-global/safe-core-sdk-types": "^5.0.1",
Expand All @@ -33,6 +34,7 @@
"@tanstack/react-query": "^5.40.1",
"@tanstack/react-query-devtools": "^5.49.2",
"axios": "^1.6.7",
"bignumber.js": "^9.1.2",
"ethers": "^6.10.0",
"formik": "^2.4.5",
"framer-motion": "^10.16.5",
Expand Down
7 changes: 3 additions & 4 deletions dapp/src/acre-react/contexts/AcreSdkContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useCallback, useMemo, useState } from "react"
import { Acre } from "@acre-btc/sdk"
import { BitcoinProvider } from "@acre-btc/sdk/dist/src/lib/bitcoin/providers"
import { Acre, AcreBitcoinProvider } from "@acre-btc/sdk"
import { BITCOIN_NETWORK, env } from "#/constants"

const { TBTC_API_ENDPOINT, SUBGRAPH_API_KEY } = env
Expand All @@ -9,7 +8,7 @@ const GELATO_API_KEY = env.GELATO_RELAY_API_KEY

type AcreSdkContextValue = {
acre?: Acre
init: (bitcoinProvider?: BitcoinProvider) => Promise<void>
init: (bitcoinProvider?: AcreBitcoinProvider) => Promise<void>
isInitialized: boolean
isConnected: boolean
}
Expand All @@ -27,7 +26,7 @@ export function AcreSdkProvider({ children }: { children: React.ReactNode }) {
const [isConnected, setIsConnected] = useState(false)

const init = useCallback<AcreSdkContextValue["init"]>(
async (bitcoinProvider?: BitcoinProvider) => {
async (bitcoinProvider?: AcreBitcoinProvider) => {
let sdk = await Acre.initialize(
BITCOIN_NETWORK,
TBTC_API_ENDPOINT,
Expand Down
4 changes: 2 additions & 2 deletions dapp/src/hooks/sdk/useInitializeAcreSdk.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect } from "react"
import { logPromiseFailure } from "#/utils"
import { useAcreContext } from "#/acre-react/hooks"
import { BitcoinProvider } from "@acre-btc/sdk"
import { AcreBitcoinProvider } from "@acre-btc/sdk"
import { useBitcoinProvider } from "../orangeKit/useBitcoinProvider"
import { useWallet } from "../useWallet"

Expand All @@ -11,7 +11,7 @@ export function useInitializeAcreSdk() {
const { address } = useWallet()

useEffect(() => {
const initSDK = async (provider?: BitcoinProvider) => {
const initSDK = async (provider?: AcreBitcoinProvider) => {
await init(provider)
}

Expand Down
2 changes: 1 addition & 1 deletion dapp/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export * from "./json"
export * from "./activities"
export * from "./type-check"
export { default as eip1193 } from "./eip1193"
export { default as orangeKit } from "./orangeKit"
export { default as orangeKit } from "./orangekit"
export { default as userAgent } from "./userAgent"
export { default as referralProgram } from "./referralProgram"
export { default as acreApi } from "./acreApi"
Expand Down
101 changes: 2 additions & 99 deletions dapp/src/utils/orangeKit.ts → dapp/src/utils/orangekit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,8 @@ import {
} from "@orangekit/react"
import { Connector } from "wagmi"
import { SignInWithWalletMessage } from "@orangekit/sign-in-with-wallet"
import LedgerLiveWalletApiBitcoinProvider, {
LedgerLiveWalletApiBitcoinProviderOptions,
} from "@orangekit/react/dist/src/wallet/ledger-live/provider"
import LedgerLiveConnectorIcon from "@orangekit/react/dist/src/wallet/ledger-live/icon"
import {
AcreMessageType,
AcreModule,
AcreWithdrawalData,
} from "@ledgerhq/wallet-api-acre-module"
import { BitcoinProvider } from "@acre-btc/sdk"
import {
ConnectorConfig,
createOrangeKitConnector,
} from "@orangekit/react/dist/src/wallet/connector"
import { getExpirationDate } from "./time"
import { getExpirationDate } from "../time"
import { getOrangeKitLedgerLiveConnector } from "./ledger-live"

const getWalletInfo = (connector: OrangeKitConnector) => {
switch (connector.id) {
Expand Down Expand Up @@ -120,90 +107,6 @@ async function verifySignInWithWalletMessage(
return result.data
}

type Client = (client: unknown) => {
acre: AcreModule
}

export class AcreLedgerLiveBitcoinProvider
extends LedgerLiveWalletApiBitcoinProvider<Client>
implements BitcoinProvider
{
constructor(
network: "mainnet" | "testnet",
options?: LedgerLiveWalletApiBitcoinProviderOptions,
) {
super(network, {
tryConnectToAddress: options?.tryConnectToAddress,
// @ts-expect-error we do not have an access to the `WalletApiClient`
// type.
getCustomModule: (client) => ({ acre: new AcreModule(client) }),
})
}

async signWithdrawMessage(
message: string,
data: Omit<AcreWithdrawalData, "operation" | "nonce"> & {
operation: number
nonce: number
},
) {
if (!this.account) throw new Error("Connect first")

const signature = await this.walletApiClient.custom.acre.messageSign(
this.account.id,
{
type: AcreMessageType.Withdraw,
message: {
...data,
operation: data.operation.toString(),
nonce: data.nonce.toString(),
},
},
"0/0",
)

return signature.toString("hex")
}

async signMessage(message: string): Promise<string> {
if (!this.account) throw new Error("Connect first")

const signature = await this.walletApiClient.custom.acre.messageSign(
this.account.id,
{
type: AcreMessageType.SignIn,
message,
},
"0/0",
)

return this.normalizeV(this.account.address, signature)
}
}

function getOrangeKitLedgerLiveConnector({
rpcUrl,
chainId,
relayApiKey,
options,
}: ConnectorConfig<LedgerLiveWalletApiBitcoinProviderOptions>) {
const bitcoinWalletProvider = new AcreLedgerLiveBitcoinProvider(
chainId === 1 ? "mainnet" : "testnet",
options,
)

return () =>
createOrangeKitConnector(
"orangekit-ledger-live",
"Ledger Live",
LedgerLiveConnectorIcon,
rpcUrl,
chainId,
bitcoinWalletProvider,
relayApiKey,
)
}

export default {
getWalletInfo,
isWalletInstalled,
Expand Down
Loading

0 comments on commit 5540871

Please sign in to comment.