Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitcoin native experience #371

Merged
merged 53 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
2d624f4
Add `@orangekit/sdk` dependency
r-czajkowski Apr 18, 2024
7f7cbff
Init the OrangeKit SDK in Acre SDK
r-czajkowski Apr 18, 2024
37a58f8
Update the staking module
r-czajkowski Apr 18, 2024
c7733c9
Add unit test for integration with OrangeKit
r-czajkowski Apr 29, 2024
5b1d724
Merge branch 'main' into bitcoin-native-experience
r-czajkowski May 7, 2024
55ea425
Add `@swan-bitcoin/xpub-lib`
r-czajkowski May 7, 2024
d2027a8
Add `BitcoinProvider` interface
r-czajkowski May 7, 2024
0a80e29
Implement `LedgerLiveWalletApiBitcoinProvider`
r-czajkowski May 7, 2024
260877b
Update the `ethereum-signer` utils in SDK
r-czajkowski May 8, 2024
df7380c
Use `BitcoinProvider` to initialize the Acre SDK
r-czajkowski May 8, 2024
0965b4c
Update staking unit tests
r-czajkowski May 9, 2024
da302d8
Update docs
r-czajkowski May 9, 2024
aac6f6f
Rename variable
r-czajkowski May 9, 2024
d2f3a51
Remove @babel/preset-env
nkuba May 10, 2024
ddfaae4
Use JestConfigWithTsJest type in jest config file
nkuba May 10, 2024
553b5be
Fix Jest and @orangekit/sdk support
nkuba May 10, 2024
a3b16d1
Fix Jest and @orangekit/sdk support (#418)
r-czajkowski May 12, 2024
0614e45
Lock the version of `@swan-bitcoin/xpub-lib` lib
r-czajkowski May 14, 2024
6c2971c
Update constructo parameters names
r-czajkowski May 14, 2024
a48e63b
Update Acre SDK initialization fn
r-czajkowski May 14, 2024
769b1ba
Simplify custom ethereum signer utils
r-czajkowski May 14, 2024
c6dfc24
Avoid skipping `import/prefer-default-export` rule
r-czajkowski May 14, 2024
ce33d42
Add docs for bitcoin provider interfaces
r-czajkowski May 14, 2024
1a84644
Update the `Network` type in Ledger Live Provider
r-czajkowski May 14, 2024
14f572d
Update `@swan-bitcoin/xpub-lib` declaration types
r-czajkowski May 14, 2024
32ebcef
Rename variable
r-czajkowski May 14, 2024
4f0a13a
Merge branch 'main' into bitcoin-native-experience
r-czajkowski May 14, 2024
8bdb895
Fix linting errors
r-czajkowski May 14, 2024
855dc38
Update the docs in Ledger Live Bitcoin Provider
r-czajkowski May 14, 2024
3df3cf7
Update `getAddress` fn
r-czajkowski May 14, 2024
097cac2
Update `getAddress` fn in Ledger Live provider
r-czajkowski May 15, 2024
196b94f
Leave TODO in `LedgerLiveWalletApiBitcoinProvider`
r-czajkowski May 15, 2024
46ed33f
Remove Ethereum account from the wallet context
r-czajkowski Apr 24, 2024
315b545
Initialize the Acre SDK w/o Ethereum address
r-czajkowski Apr 24, 2024
bb91477
Init the Acre SDK in dapp w/o ethereum address
r-czajkowski May 8, 2024
9fb193c
Update Acre SDK initialization in dapp
r-czajkowski May 15, 2024
3cdb91e
Remove unused ethers signer for Ledger Live
r-czajkowski May 15, 2024
6499c9a
Mock `@orangekit/sdk` to run jest test
r-czajkowski May 15, 2024
4f05fe8
Fix formatting error
r-czajkowski May 15, 2024
c90a92d
Remove Ethereum account from wallet context (#379)
nkuba May 15, 2024
18170eb
Merge branch 'main' into bitcoin-native-experience
r-czajkowski May 15, 2024
30526c7
Fix `useInitializeAcreSdk` hook
r-czajkowski May 15, 2024
f351fa4
Rename variable
r-czajkowski May 16, 2024
a51688e
Update docs
r-czajkowski May 16, 2024
56aa212
Update `IEthereumSignerCompatibleWithEthersV5`
r-czajkowski May 16, 2024
c6228a7
Add unit tests for Ledger Live Wallet Api Provider
r-czajkowski May 21, 2024
34d8350
Merge branch 'main' into bitcoin-native-experience
r-czajkowski May 21, 2024
9c1c45b
Merge branch 'main' into bitcoin-native-experience
r-czajkowski May 29, 2024
37db599
Simplify the bitcoin network type in SDK
r-czajkowski May 29, 2024
60a2bf5
Simplify the the Acre initialization function
r-czajkowski May 29, 2024
219127e
Rename variables
r-czajkowski May 29, 2024
f0fecf0
Leave a `TODO` in the `BitcoinProvider` interface
r-czajkowski May 29, 2024
60c1231
Merge branch 'main' into bitcoin-native-experience
nkuba May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions dapp/.env
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ VITE_REFERRAL=123
VITE_DEFENDER_RELAYER_WEBHOOK_URL="https://api.defender.openzeppelin.com/actions/a0d6d2e2-ce9c-4619-aa2b-6c874fe97af7/runs/webhook/b1f17c89-8230-46e3-866f-a3213887974c/Sbddsy54cJ6sPg2bLPyuHJ"

VITE_ACRE_SUBGRAPH_URL="https://api.studio.thegraph.com/query/73600/acre/version/latest"

# TODO: Set this env variable in CI.
VITE_TBTC_API_ENDPOINT=""
3 changes: 2 additions & 1 deletion dapp/ledger-manifest-development.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"account.list",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast"
"transaction.signAndBroadcast",
"bitcoin.getXPub"
],
"domains": ["http://*"],
"type": "walletApp"
Expand Down
33 changes: 22 additions & 11 deletions dapp/src/acre-react/contexts/AcreSdkContext.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { useCallback, useMemo, useState } from "react"
import { LedgerLiveEthereumSigner } from "#/web3"
import { Acre, EthereumNetwork } from "@acre-btc/sdk"
import { Acre, BitcoinNetwork } from "@acre-btc/sdk"
import { BitcoinProvider } from "@acre-btc/sdk/dist/src/lib/bitcoin/providers"
import { BITCOIN_NETWORK } from "#/constants"

const TBTC_API_ENDPOINT = import.meta.env.VITE_TBTC_API_ENDPOINT
const ETH_RPC_URL = import.meta.env.VITE_ETH_HOSTNAME_HTTP

type AcreSdkContextValue = {
acre?: Acre
init: (ethereumAddress: string, network: EthereumNetwork) => Promise<void>
init: (bitcoinProvider: BitcoinProvider) => Promise<void>
isInitialized: boolean
}

Expand All @@ -21,14 +23,23 @@ export function AcreSdkProvider({ children }: { children: React.ReactNode }) {
const [isInitialized, setIsInitialized] = useState<boolean>(false)

const init = useCallback<AcreSdkContextValue["init"]>(
async (ethereumAddress: string, network: EthereumNetwork) => {
if (!ethereumAddress) throw new Error("Ethereum address not defined")

const sdk = await Acre.initializeEthereum(
await LedgerLiveEthereumSigner.fromAddress(ethereumAddress),
network,
TBTC_API_ENDPOINT,
)
async (bitcoinProvider: BitcoinProvider) => {
let sdk: Acre

if (BITCOIN_NETWORK === BitcoinNetwork.Mainnet) {
sdk = await Acre.initializeMainnet(
bitcoinProvider,
TBTC_API_ENDPOINT,
ETH_RPC_URL,
)
} else {
sdk = await Acre.initializeTestnet(
bitcoinProvider,
TBTC_API_ENDPOINT,
ETH_RPC_URL,
)
}

setAcre(sdk)
setIsInitialized(true)
},
Expand Down
20 changes: 5 additions & 15 deletions dapp/src/acre-react/hooks/useStakeFlow.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import { useCallback, useState } from "react"
import {
StakeInitialization,
EthereumAddress,
DepositReceipt,
} from "@acre-btc/sdk"
import { StakeInitialization, DepositReceipt } from "@acre-btc/sdk"
import { useAcreContext } from "./useAcreContext"

export type UseStakeFlowReturn = {
initStake: (
bitcoinRecoveryAddress: string,
ethereumAddress: string,
referral: number,
bitcoinRecoveryAddress?: string,
) => Promise<void>
btcAddress?: string
depositReceipt?: DepositReceipt
Expand All @@ -30,17 +25,12 @@ export function useStakeFlow(): UseStakeFlowReturn {
>(undefined)

const initStake = useCallback(
async (
bitcoinRecoveryAddress: string,
ethereumAddress: string,
referral: number,
) => {
async (referral: number, bitcoinRecoveryAddress?: string) => {
if (!acre || !isInitialized) throw new Error("Acre SDK not defined")

const initializedStakeFlow = await acre.staking.initializeStake(
bitcoinRecoveryAddress,
EthereumAddress.from(ethereumAddress),
referral,
bitcoinRecoveryAddress,
)

const btcDepositAddress = await initializedStakeFlow.getBitcoinAddress()
Expand All @@ -58,7 +48,7 @@ export function useStakeFlow(): UseStakeFlowReturn {
const signMessage = useCallback(async () => {
if (!stakeFlow) throw new Error("Initialize stake first")

await stakeFlow.signMessage()
await Promise.resolve(stakeFlow.signMessage())
nkuba marked this conversation as resolved.
Show resolved Hide resolved
}, [stakeFlow])

const stake = useCallback(async () => {
Expand Down
12 changes: 3 additions & 9 deletions dapp/src/components/TransactionModal/ActionFormModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { ReactNode, useCallback, useState } from "react"
import { Box, ModalBody, ModalCloseButton, ModalHeader } from "@chakra-ui/react"
import { useAppDispatch, useStakeFlowContext, useWalletContext } from "#/hooks"
import { useAppDispatch, useStakeFlowContext } from "#/hooks"
import { ACTION_FLOW_TYPES, ActionFlowType, BaseFormProps } from "#/types"
import { TokenAmountFormValues } from "#/components/shared/TokenAmountForm/TokenAmountFormBase"
import { logPromiseFailure } from "#/utils"
Expand All @@ -26,7 +26,6 @@ const FORM_DATA: Record<
}

function ActionFormModal({ type }: { type: ActionFlowType }) {
const { btcAccount, ethAccount } = useWalletContext()
const { initStake } = useStakeFlowContext()
const dispatch = useAppDispatch()

Expand All @@ -35,13 +34,8 @@ function ActionFormModal({ type }: { type: ActionFlowType }) {
const { heading, renderComponent } = FORM_DATA[type]

const handleInitStake = useCallback(async () => {
const btcAddress = btcAccount?.address
const ethAddress = ethAccount?.address

if (btcAddress && ethAddress) {
await initStake(btcAddress, ethAddress)
}
}, [btcAccount?.address, ethAccount?.address, initStake])
await initStake()
}, [initStake])

const handleSubmitForm = useCallback(
async (values: TokenAmountFormValues) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default function DepositBTCModal() {
const response = await depositTelemetry(
depositReceipt,
btcAddress,
ethAccount.address,
ethAccount,
)

if (response.verificationStatus === "valid") {
Expand Down
15 changes: 2 additions & 13 deletions dapp/src/components/TransactionModal/ModalContentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import {
useActionFlowTokenAmount,
useActionFlowType,
useRequestBitcoinAccount,
useRequestEthereumAccount,
useWalletContext,
} from "#/hooks"
import { BitcoinIcon, EthereumIcon } from "#/assets/icons"
import { BitcoinIcon } from "#/assets/icons"
import { PROCESS_STATUSES } from "#/types"
import { isSupportedBTCAddressType } from "#/utils"
import ActionFormModal from "./ActionFormModal"
Expand All @@ -21,9 +20,8 @@ export default function ModalContentWrapper({
}: {
children: React.ReactNode
}) {
const { btcAccount, ethAccount } = useWalletContext()
const { btcAccount } = useWalletContext()
const { requestAccount: requestBitcoinAccount } = useRequestBitcoinAccount()
const { requestAccount: requestEthereumAccount } = useRequestEthereumAccount()
const status = useActionFlowStatus()
const type = useActionFlowType()
const tokenAmount = useActionFlowTokenAmount()
Expand All @@ -37,15 +35,6 @@ export default function ModalContentWrapper({
/>
)

if (!ethAccount)
return (
<MissingAccountModal
currency="ethereum"
icon={EthereumIcon}
requestAccount={requestEthereumAccount}
/>
)

if (!tokenAmount) return <ActionFormModal type={type} />

if (status === PROCESS_STATUSES.LOADING) return <LoadingModal />
Expand Down
14 changes: 11 additions & 3 deletions dapp/src/constants/chains.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Chain } from "#/types"
import { EthereumNetwork, BitcoinNetwork } from "@acre-btc/sdk"
import {
EthereumNetwork,
BitcoinNetwork as AcreSDKBitcoinNetwork,
} from "@acre-btc/sdk"

export type BitcoinNetwork = Exclude<
AcreSDKBitcoinNetwork,
AcreSDKBitcoinNetwork.Unknown
>
nkuba marked this conversation as resolved.
Show resolved Hide resolved

const BLOCK_EXPLORER_TESTNET = {
ethereum: { title: "Etherscan", url: "https://sepolia.etherscan.io" },
Expand All @@ -21,5 +29,5 @@ export const ETHEREUM_NETWORK: EthereumNetwork =

export const BITCOIN_NETWORK: BitcoinNetwork =
import.meta.env.VITE_USE_TESTNET === "true"
? BitcoinNetwork.Testnet
: BitcoinNetwork.Mainnet
? AcreSDKBitcoinNetwork.Testnet
: AcreSDKBitcoinNetwork.Mainnet
16 changes: 5 additions & 11 deletions dapp/src/contexts/StakeFlowContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import {
import { REFERRAL } from "#/constants"

type StakeFlowContextValue = Omit<UseStakeFlowReturn, "initStake"> & {
initStake: (
bitcoinRecoveryAddress: string,
ethereumAddress: string,
) => Promise<void>
initStake: () => Promise<void>
}

export const StakeFlowContext = React.createContext<StakeFlowContextValue>({
Expand All @@ -29,14 +26,11 @@ export function StakeFlowProvider({ children }: { children: React.ReactNode }) {
stake,
} = useStakeFlow()

const initStake = useCallback(
async (bitcoinRecoveryAddress: string, ethereumAddress: string) => {
if (!acre) throw new Error("Acre SDK not defined")
const initStake = useCallback(async () => {
if (!acre) throw new Error("Acre SDK not defined")

await acreInitStake(bitcoinRecoveryAddress, ethereumAddress, REFERRAL)
},
[acreInitStake, acre],
)
await acreInitStake(REFERRAL)
}, [acreInitStake, acre])

const context = useMemo(
() => ({
Expand Down
6 changes: 3 additions & 3 deletions dapp/src/contexts/WalletContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import React, { createContext, useEffect, useMemo, useState } from "react"
type WalletContextValue = {
btcAccount: Account | undefined
setBtcAccount: React.Dispatch<React.SetStateAction<Account | undefined>>
ethAccount: Account | undefined
setEthAccount: React.Dispatch<React.SetStateAction<Account | undefined>>
ethAccount: string | undefined
setEthAccount: React.Dispatch<React.SetStateAction<string | undefined>>
isConnected: boolean
}

Expand All @@ -23,7 +23,7 @@ export function WalletContextProvider({
children: React.ReactNode
}): React.ReactElement {
const [btcAccount, setBtcAccount] = useState<Account | undefined>(undefined)
const [ethAccount, setEthAccount] = useState<Account | undefined>(undefined)
const [ethAccount, setEthAccount] = useState<string | undefined>(undefined)
const [isConnected, setIsConnected] = useState<boolean>(false)

useEffect(() => {
Expand Down
1 change: 0 additions & 1 deletion dapp/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export * from "./sdk"
export * from "./subgraph"
export * from "./useDetectThemeMode"
export * from "./useRequestBitcoinAccount"
export * from "./useRequestEthereumAccount"
export * from "./useWalletContext"
export * from "./useSidebar"
export * from "./useDocsDrawer"
Expand Down
2 changes: 1 addition & 1 deletion dapp/src/hooks/sdk/useFetchBTCBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function useFetchBTCBalance() {
const getBtcBalance = async () => {
if (!isInitialized || !ethAccount || !acre) return

const chainIdentifier = EthereumAddress.from(ethAccount.address)
const chainIdentifier = EthereumAddress.from(ethAccount)
const sharesBalance = await acre.staking.sharesBalance(chainIdentifier)
const estimatedBitcoinBalance =
await acre.staking.estimatedBitcoinBalance(chainIdentifier)
Expand Down
19 changes: 12 additions & 7 deletions dapp/src/hooks/sdk/useInitializeAcreSdk.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { useEffect } from "react"
import { ETHEREUM_NETWORK } from "#/constants"
import { BITCOIN_NETWORK } from "#/constants"
import { logPromiseFailure } from "#/utils"
import { useAcreContext } from "#/acre-react/hooks"
import { LedgerLiveWalletApiBitcoinProvider } from "@acre-btc/sdk/dist/src/lib/bitcoin/providers"
import { useWalletContext } from "../useWalletContext"

export function useInitializeAcreSdk() {
const { ethAccount } = useWalletContext()
const { btcAccount } = useWalletContext()
const { init } = useAcreContext()

useEffect(() => {
if (!ethAccount?.address) return
if (!btcAccount?.id) return

const initSDK = async (ethAddress: string) => {
await init(ethAddress, ETHEREUM_NETWORK)
const initSDK = async (bitcoinAccountId: string) => {
const bitcoinProvider = await LedgerLiveWalletApiBitcoinProvider.init(
bitcoinAccountId,
BITCOIN_NETWORK,
)
await init(bitcoinProvider)
}
logPromiseFailure(initSDK(ethAccount.address))
}, [ethAccount?.address, init])
logPromiseFailure(initSDK(btcAccount.id))
}, [btcAccount?.id, init])
}
1 change: 0 additions & 1 deletion dapp/src/hooks/toasts/useInitGlobalToasts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useShowWalletErrorToast } from "./useShowWalletErrorToast"

export function useInitGlobalToasts() {
useShowWalletErrorToast("ethereum")
useShowWalletErrorToast("bitcoin")
}
8 changes: 2 additions & 6 deletions dapp/src/hooks/toasts/useShowWalletErrorToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,17 @@ import { useToast } from "./useToast"
import { useWallet } from "../useWallet"
import { useTimeout } from "../useTimeout"

const { BITCOIN_WALLET_ERROR, ETHEREUM_WALLET_ERROR } = TOAST_IDS
const { BITCOIN_WALLET_ERROR } = TOAST_IDS

const WALLET_ERROR_TOAST_ID = {
bitcoin: {
id: BITCOIN_WALLET_ERROR,
Component: TOASTS[BITCOIN_WALLET_ERROR],
},
ethereum: {
id: ETHEREUM_WALLET_ERROR,
Component: TOASTS[ETHEREUM_WALLET_ERROR],
},
}

export function useShowWalletErrorToast(
type: "bitcoin" | "ethereum",
type: "bitcoin",
delay = ONE_SEC_IN_MILLISECONDS,
) {
const {
Expand Down
26 changes: 0 additions & 26 deletions dapp/src/hooks/useRequestEthereumAccount.ts

This file was deleted.

Loading
Loading