Skip to content

🐝 Alby support - #155

Open
louisinger wants to merge 26 commits into
fuji-money:mainfrom
louisinger:alby
Open

louisinger wants to merge 26 commits into
fuji-money:mainfrom
louisinger:alby

Conversation

@louisinger

@louisinger louisinger commented Jul 19, 2023

Copy link
Copy Markdown
Contributor

Multiple wallets X fuji-app

  • add an abstract Wallet interface layer + MarinaWallet & AlbyWallet implementations. This is only a liquid wallet related interface. webln should be handled in another part, this PR only works with window.liquid provider injected by Alby
  • WalletContext now returns a list of wallets (the connected wallets)
  • network is now an app variable (switch via settings button)
  • Dashboard shows aggregated wallets data (sum balances, concat contracts & activities).
  • Mint lets you choose the wallet to use via channel/liquid route. the selected wallet will provide collaterals and receive the fujis.
  • Close (redeem) allows you to select the wallet that will redeem the collateral. The selected wallet will provide fujis to burn and receive the collateral. Even if the collateral is initially locked by another wallet. (Thus, you can redeem a coin owned by Alby but using Marina - and vice versa)

Screenshots

Borrow form warning toasts:
image

Liquid channels with Alby & marina installed and connected:
image

Several wallets balances:
image

it closes #131

Please @tiero @easter-monolith review

@vercel

vercel Bot commented Jul 19, 2023

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 13, 2023 0:47am

@easter-monolith

Copy link
Copy Markdown
Collaborator

@louisinger there's some bug on connect:

Screen.Recording.2023-07-19.at.15.11.07.mov

@easter-monolith

Copy link
Copy Markdown
Collaborator

Apply this diff to fix building errors:

diff --git a/components/investments/index.tsx b/components/investments/index.tsx
index b8bda1d..ef7b3f4 100644
--- a/components/investments/index.tsx
+++ b/components/investments/index.tsx
@@ -8,18 +8,19 @@ import { WalletContext } from 'components/providers/wallet'
 import { ContractsContext } from 'components/providers/contracts'
 
 const Investments = () => {
-  const { wallet } = useContext(WalletContext)
+  const { wallets } = useContext(WalletContext)
   const { loading } = useContext(ContractsContext)
   const [investments, setInvestments] = useState<Investment[]>()
 
   useEffect(() => {
-    if (wallet) {
-      wallet
+    if (wallets.length) {
+      wallets[0]
         .getNetwork()
         .then(fetchInvestments)
         .then((data) => setInvestments(data))
     }
-  }, [wallet])
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [wallets.length])
 
   if (loading) return <Spinner />
   if (!investments) return <SomeError>Error fetching investments</SomeError>
diff --git a/components/investments/list.tsx b/components/investments/list.tsx
index 2b5abf0..4ca929a 100644
--- a/components/investments/list.tsx
+++ b/components/investments/list.tsx
@@ -8,15 +8,16 @@ import { WalletContext } from 'components/providers/wallet'
 import { ContractsContext } from 'components/providers/contracts'
 
 const InvestmentsList = () => {
-  const { wallet } = useContext(WalletContext)
+  const { wallets } = useContext(WalletContext)
   const { loading } = useContext(ContractsContext)
   const [investments, setInvestments] = useState<Investment[]>()
 
   useEffect(() => {
-    if (wallet) {
-      wallet.getNetwork().then(fetchInvestments).then(setInvestments)
+    if (wallets.length) {
+      wallets[0].getNetwork().then(fetchInvestments).then(setInvestments)
     }
-  }, [wallet])
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [wallets.length])
 
   if (loading) return <Spinner />
   if (!investments) return <SomeError>Error getting investments</SomeError>
diff --git a/components/multiply/deposit.tsx b/components/multiply/deposit.tsx
index 3a8147b..b10dbe2 100644
--- a/components/multiply/deposit.tsx
+++ b/components/multiply/deposit.tsx
@@ -41,14 +41,6 @@ const MultiplyDeposit = ({
   const handleLightning = async () => {} // TODO
   const handleMarina = () => {} // TODO
 
-  const handleAlby =
-    weblnProviderName === 'Alby'
-      ? async () => {
-          setUseWebln(true)
-          await handleLightning()
-        }
-      : undefined
-
   return (
     <>
       <div className="is-box has-pink-border p-6">
@@ -56,7 +48,6 @@ const MultiplyDeposit = ({
         {lightning && (
           <EnablersLightning
             contract={contract}
-            handleAlby={handleAlby}
             handleInvoice={handleLightning}
             task={Tasks.Multiply}
           />
diff --git a/components/navbar/index.tsx b/components/navbar/index.tsx
index 7fdeb05..f5fdf29 100644
--- a/components/navbar/index.tsx
+++ b/components/navbar/index.tsx
@@ -4,7 +4,6 @@ import { openModal } from 'lib/utils'
 import ConnectButton from 'components/buttons/connect'
 import Settings from 'components/settings'
 import { ModalIds } from 'components/modals/modal'
-import NetworkButton from 'components/buttons/network'
 
 export default function Navbar() {
   return (
diff --git a/components/providers/webln.tsx b/components/providers/webln.tsx
index 924c2f6..ab59b94 100644
--- a/components/providers/webln.tsx
+++ b/components/providers/webln.tsx
@@ -31,7 +31,7 @@ interface WeblnProviderProps {
   children: ReactNode
 }
 export const WeblnProvider = ({ children }: WeblnProviderProps) => {
-  const { wallet } = useContext(WalletContext)
+  const { wallets } = useContext(WalletContext)
 
   const [weblnCanEnable, setWeblnCanEnable] = useState(true)
   const [weblnIsEnabled, setweblnIsEnabled] = useState(false)
@@ -61,7 +61,7 @@ export const WeblnProvider = ({ children }: WeblnProviderProps) => {
 
   // if webln support detected, asks user to enable it
   useEffect(() => {
-    if (window.webln && wallet) {
+    if (window.webln && wallets.length) {
       setWeblnProvider(window.webln)
       if (window.webln.enabled) setweblnIsEnabled(true)
       else if (!alreadyAsk.current) {
@@ -69,7 +69,7 @@ export const WeblnProvider = ({ children }: WeblnProviderProps) => {
         alreadyAsk.current = true
       }
     }
-  }, [wallet])
+  }, [wallets.length])
 
   return (
     <WeblnContext.Provider
diff --git a/components/stocks/list.tsx b/components/stocks/list.tsx
index 61b08a6..103e040 100644
--- a/components/stocks/list.tsx
+++ b/components/stocks/list.tsx
@@ -8,15 +8,16 @@ import { WalletContext } from 'components/providers/wallet'
 import { ContractsContext } from 'components/providers/contracts'
 
 const StocksList = () => {
-  const { wallet } = useContext(WalletContext)
+  const { wallets } = useContext(WalletContext)
   const { loading } = useContext(ContractsContext)
   const [stocks, setStocks] = useState<Stock[]>()
 
   useEffect(() => {
-    if (wallet) {
-      wallet.getNetwork().then(fetchStocks).then(setStocks)
+    if (wallets.length) {
+      wallets[0].getNetwork().then(fetchStocks).then(setStocks)
     }
-  }, [wallet])
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [wallets.length])
 
   if (loading) return <Spinner />
   if (!stocks) return <SomeError>Error getting stocks</SomeError>
diff --git a/components/topup/button.tsx b/components/topup/button.tsx
index c554d61..2f72031 100644
--- a/components/topup/button.tsx
+++ b/components/topup/button.tsx
@@ -11,10 +11,10 @@ interface TopupButtonProps {
 }
 
 const TopupButton = ({ minRatio, oracles, ratio, topup }: TopupButtonProps) => {
-  const { wallet } = useContext(WalletContext)
+  const { wallets } = useContext(WalletContext)
 
   const enabled =
-    wallet?.isConnected &&
+    wallets?.[0]?.isConnected() &&
     topup > minDustLimit + feeAmount &&
     ratio > minRatio &&
     oracles.length > 0
     ```

@easter-monolith

Copy link
Copy Markdown
Collaborator

@louisinger there's some bug on connect:
Screen.Recording.2023-07-19.at.15.11.07.mov

Got it, the button is always saying "Connect", even after Marina is already connected.

@louisinger

Copy link
Copy Markdown
Contributor Author

@louisinger there's some bug on connect:
Screen.Recording.2023-07-19.at.15.11.07.mov

Got it, the button is always saying "Connect", even after Marina is already connected.

Yeah this is because Alby does have any "disconnect" behavior (you can disconnect an app but only from the extension settings) so Wallet interface doesn't have any disconnect method.

beside that, it raises some UX questions:

  1. connect button: should be disabled if all installed wallets are already connected ?
  2. wallet modals: should show a "connected ✔️" if wallet is connected ? or anything else ? maybe we should rethink the component with an optional disconnect btn enabled if the wallet handle it ?

@tiero

tiero commented Jul 20, 2023

Copy link
Copy Markdown
Contributor

Having a periodic check of the "wallet" connection could be helpful (ie. on component/page mount?)

@louisinger

Copy link
Copy Markdown
Contributor Author

Having a periodic check of the "wallet" connection could be helpful (ie. on component/page mount?)

it should be the case. we check the connected status in 3 cases:

  1. at each page reload (during ContractContext mount)
  2. each time we connect a new wallet
  3. each time we switch the network

FYI Alby has also an "auto-enable" behavior. Thus if the wallet is disable for any reasons and then the app calls the provider, Alby extension will first ask the user to enable the wallet (so will show two popups).

// Wallet could know about contracts that local storage doesn't
// This could happen if the user is using more than one device
// In this case, we will add the unknown contracts into storage
const syncContractsWithMarina = async () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tiero @easter-monolith I've commented that part because Alby is not persisting any scriptPubKey or contract parameters related to the covenant. So impossible to "recover contracts from wallet coins". Should be possible later if covenant parameters are on-chain

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could eventually address later a way to also import contract from the JSON backup file we allow to download

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2ea4f48 reverts sync with Marina using an optional Wallet method getContracts.

@easter-monolith

Copy link
Copy Markdown
Collaborator

When I reload the app without any wallet connected:

  1. the app tries to connect Marina without user intervention;
  2. the app tries to connect Marina twice, opening 2 popups at the same time.

@louisinger
louisinger marked this pull request as ready for review July 27, 2023 10:37
@tiero
tiero requested a review from easter-monolith August 7, 2023 12:30
@bitcoinuser

Copy link
Copy Markdown

@louisinger @bitcoinuser no matter what I do, the app isn't able to find Alby:

  • that weird error liquid call already executing always popping up
  • but window.liquid is enabled 😕

Using Alby 3.0.1 from nightly (includes @louisinger PR to Alby)

Screenshot 2023-08-15 at 16 19 08

Adendum:

  • Error doesn't happen the first time you run Alby
  • To see the error, just reload Fuji App and check the console
  • Extension (v3.0.1) was downloaded from chrome nightly

Alby was updated to version 3.1.1 on Firefox. Are you able to test on it? Thanks.

@louisinger

Copy link
Copy Markdown
Contributor Author

Alby was updated to version 3.1.1 on Firefox. Are you able to test on it? Thanks.

Tested on Firefox: it works fine ✔️

@bitcoinuser

Copy link
Copy Markdown

Alby was updated to version 3.1.1 on Firefox. Are you able to test on it? Thanks.

Tested on Firefox: it works fine ✔️

So time to merge?

@easter-monolith

Copy link
Copy Markdown
Collaborator

Can't connect Alby with Chrome.

Replicable on https://app-r7mz6ub4u-fuji-money.vercel.app/dashboard (preview deployment for this PR)

  • Firefox, v3.2.1 => works, tested mint and close with success
  • Chrome, v3.3.0 => error when connecting Alby (check console)

Not sure if the problem is on Fuji's side or Alby's

@bitcoinuser any big change on Liquid between these 2 versions?

Screen.Recording.2023-10-12.at.17.45.29.mov

@rolznz

rolznz commented Oct 13, 2023

Copy link
Copy Markdown

@louisinger any chance you are checking the internal ".enabled" property?

Ideally the flow should be: if await window.liquid.enable() does not throw an exception, then the liquid provider is ready to use. You can also now check await window.liquid.isEnabled() to see if liquid was ever enabled on the site without launching a popup

image

@easter-monolith

Copy link
Copy Markdown
Collaborator

tACK

  • Firefox with Alby 3.2.1 => connect, mint and close with success
  • Chrome with Alby 3.3.0 => connect, mint and close with success

@bitcoinuser

Copy link
Copy Markdown

When this will be merged? Thanks.

@tiero

tiero commented Dec 18, 2023

Copy link
Copy Markdown
Contributor

Using ALby worked, but using Marina didn't

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Alby as wallet beside Marina

5 participants