From 90a04c97b72bdac1d239c41b7d67189692e2bf5c Mon Sep 17 00:00:00 2001 From: joundy Date: Mon, 26 Feb 2024 17:24:16 +0700 Subject: [PATCH] feat(wallet): leather wallet integration (#219) * feat(wallet): leather wallet * fix(wallet): unisat connect should be use unisat wallet * comment(wallet-modal): remove & update leather comment * fix(leather): use address format on signMessage function * fix(signMessage): validate address & format * fix(selectModal): variable naming & separate error * Update packages/ord-connect/src/components/SelectWalletModal/index.tsx Co-authored-by: Benedict Pak <10258208+Nanosync@users.noreply.github.com> * Update packages/ord-connect/src/components/SelectWalletModal/index.tsx Co-authored-by: Benedict Pak <10258208+Nanosync@users.noreply.github.com> * docs(preview): update preview image * docs(preview): update preview image --------- Co-authored-by: Benedict Pak <10258208+Nanosync@users.noreply.github.com> --- README.md | 1 + packages/ord-connect/package.json | 3 +- .../ord-connect/src/assets/leather-wallet.svg | 9 +++ .../components/PostConnectButton/index.tsx | 2 + .../SelectWalletModal/WalletButton.tsx | 1 + .../components/SelectWalletModal/index.tsx | 68 ++++++++++++++++++ .../ord-connect/src/hooks/useSignMessage.tsx | 22 +++++- packages/ord-connect/src/lib/signMessage.ts | 28 ++++++++ packages/ord-connect/src/lib/signPsbt.ts | 12 ++++ .../src/providers/OrdConnectProvider.tsx | 5 +- pnpm-lock.yaml | 8 +-- preview.png | Bin 16198 -> 19388 bytes 12 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 packages/ord-connect/src/assets/leather-wallet.svg diff --git a/README.md b/README.md index aeddac63..932cc3ad 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ | Unisat | ✅ | ✅ | | Xverse | ✅ | ✅ | | Magic Eden | ✅ | ✅ | +| Leather | ✅ | ✅ | ## Quick Start diff --git a/packages/ord-connect/package.json b/packages/ord-connect/package.json index d91f1743..f94e83e9 100644 --- a/packages/ord-connect/package.json +++ b/packages/ord-connect/package.json @@ -47,7 +47,6 @@ }, "dependencies": { "@headlessui/react": "^1.7.18", - "@ordzaar/ordit-sdk": "1.3.1", "bitcoinjs-lib": "6.1.5", "boring-avatars": "^1.10.1" }, @@ -60,7 +59,7 @@ ] }, "peerDependencies": { - "@ordzaar/ordit-sdk": "1.3.1", + "@ordzaar/ordit-sdk": "1.4.0", "react": "^18.2.0", "react-dom": "^18.2.0" } diff --git a/packages/ord-connect/src/assets/leather-wallet.svg b/packages/ord-connect/src/assets/leather-wallet.svg new file mode 100644 index 00000000..89f481d5 --- /dev/null +++ b/packages/ord-connect/src/assets/leather-wallet.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/ord-connect/src/components/PostConnectButton/index.tsx b/packages/ord-connect/src/components/PostConnectButton/index.tsx index 35f2e6f2..0caa7de9 100644 --- a/packages/ord-connect/src/components/PostConnectButton/index.tsx +++ b/packages/ord-connect/src/components/PostConnectButton/index.tsx @@ -3,6 +3,7 @@ import Avatar from "boring-avatars"; import { Menu, Transition } from "@headlessui/react"; import ChevronDownIcon from "../../assets/chevron-down.svg"; +import LeatherWalletIcon from "../../assets/leather-wallet.svg"; import LogoutIcon from "../../assets/logout.svg"; import MagicEdenIcon from "../../assets/magiceden-wallet.svg"; import UnisatWalletIcon from "../../assets/unisat-wallet.svg"; @@ -14,6 +15,7 @@ const WALLET_TO_ICON: Record = { [Wallet.MAGICEDEN]: MagicEdenIcon, [Wallet.UNISAT]: UnisatWalletIcon, [Wallet.XVERSE]: XverseWalletIcon, + [Wallet.LEATHER]: LeatherWalletIcon, } as const; interface PostConnectButtonProp { diff --git a/packages/ord-connect/src/components/SelectWalletModal/WalletButton.tsx b/packages/ord-connect/src/components/SelectWalletModal/WalletButton.tsx index e7892903..714ea093 100644 --- a/packages/ord-connect/src/components/SelectWalletModal/WalletButton.tsx +++ b/packages/ord-connect/src/components/SelectWalletModal/WalletButton.tsx @@ -10,6 +10,7 @@ const WALLET_TO_NAME: Record = { [Wallet.MAGICEDEN]: "Magic Eden", [Wallet.UNISAT]: "UniSat", [Wallet.XVERSE]: "Xverse", + [Wallet.LEATHER]: "Leather", } as const; interface WalletButtonProp { diff --git a/packages/ord-connect/src/components/SelectWalletModal/index.tsx b/packages/ord-connect/src/components/SelectWalletModal/index.tsx index d3f38e87..06570c35 100644 --- a/packages/ord-connect/src/components/SelectWalletModal/index.tsx +++ b/packages/ord-connect/src/components/SelectWalletModal/index.tsx @@ -4,11 +4,13 @@ import { BrowserWalletNotInstalledError, BrowserWalletRequestCancelledByUserError, } from "@ordzaar/ordit-sdk"; +import { getAddresses as getLeatherAddresses } from "@ordzaar/ordit-sdk/leather"; import { getAddresses as getMagicEdenAddress } from "@ordzaar/ordit-sdk/magiceden"; import { getAddresses as getUnisatAddresses } from "@ordzaar/ordit-sdk/unisat"; import { getAddresses as getXverseAddresses } from "@ordzaar/ordit-sdk/xverse"; import CloseModalIcon from "../../assets/close-modal.svg"; +import LeatherWalletIcon from "../../assets/leather-wallet.svg"; import MagicEdenWalletIcon from "../../assets/magiceden-wallet.svg"; import UnisatWalletIcon from "../../assets/unisat-wallet.svg"; import XverseWalletIcon from "../../assets/xverse-wallet.svg"; @@ -29,6 +31,7 @@ const WALLET_CHROME_EXTENSION_URL: Record = { [Wallet.MAGICEDEN]: "https://wallet.magiceden.io/", [Wallet.UNISAT]: "https://unisat.io/download", // their www subdomain doesn't work [Wallet.XVERSE]: "https://www.xverse.app/download", + [Wallet.LEATHER]: "https://leather.io/install-extension", }; export function SelectWalletModal({ @@ -245,6 +248,58 @@ export function SelectWalletModal({ updatePublicKey, updateWallet, ]); + const onConnectLeatherWallet = useCallback(async () => { + try { + setErrorMessage(""); + const leather = await getLeatherAddresses(network); + if (!leather || leather.length < 1) { + disconnectWallet(); + throw new Error("Leather via Ordit returned no addresses."); + } + + const paymentAddress = leather.find( + (walletAddress) => walletAddress.format === "segwit", + ); + if (!paymentAddress) { + throw new Error("Leather via Ordit did not return a Segwit address."); + } + + const ordinalAddress = leather.find( + (walletAddress) => walletAddress.format === "taproot", + ); + if (!ordinalAddress) { + throw new Error("Leather via Ordit did not return a Taproot address."); + } + + updateAddress({ + ordinals: ordinalAddress.address, + payments: paymentAddress.address, + }); + updatePublicKey({ + ordinals: ordinalAddress.publicKey, + payments: paymentAddress.publicKey, + }); + updateWallet(Wallet.LEATHER); + updateFormat({ + ordinals: ordinalAddress.format, + payments: paymentAddress.format, + }); + closeModal(); + return true; + } catch (err) { + onError(Wallet.LEATHER, err as Error); + return false; + } + }, [ + closeModal, + disconnectWallet, + network, + onError, + updateAddress, + updateFormat, + updatePublicKey, + updateWallet, + ]); // Reconnect address change listener if there there is already a connected wallet useEffect(() => { @@ -372,6 +427,19 @@ export function SelectWalletModal({ renderAvatar={renderAvatar} /> )} +
+ {!isMobile && ( + + )} ) : ( diff --git a/packages/ord-connect/src/hooks/useSignMessage.tsx b/packages/ord-connect/src/hooks/useSignMessage.tsx index 6b892191..388da12f 100644 --- a/packages/ord-connect/src/hooks/useSignMessage.tsx +++ b/packages/ord-connect/src/hooks/useSignMessage.tsx @@ -8,24 +8,42 @@ export function useSignMessage(): { signMsg: (address: string, message: string) => Promise; error: string | null; } { - const { network, wallet, publicKey, format } = useOrdConnect(); + const { + network, + wallet, + publicKey, + format, + address: walletAddresses, + } = useOrdConnect(); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); const signMsg = useCallback( async (address: string, message: string) => { setIsLoading(true); + try { setError(null); if (!format || !publicKey || !wallet) { throw new Error("No wallet is connected"); } + if ( + walletAddresses.ordinals !== address && + walletAddresses.payments !== address + ) { + throw new Error("Address supplied is not connected address"); + } + const signedMessage = await signMessage({ address, wallet, message, network, + format: + walletAddresses.ordinals === address + ? format.ordinals! + : format.payments!, }); setIsLoading(false); @@ -36,7 +54,7 @@ export function useSignMessage(): { throw err; } }, - [format, network, publicKey, wallet], + [format, network, publicKey, wallet, walletAddresses], ); return { signMsg, error, isLoading }; diff --git a/packages/ord-connect/src/lib/signMessage.ts b/packages/ord-connect/src/lib/signMessage.ts index c3e2f40e..d19304b4 100644 --- a/packages/ord-connect/src/lib/signMessage.ts +++ b/packages/ord-connect/src/lib/signMessage.ts @@ -1,3 +1,8 @@ +import { AddressFormat } from "@ordzaar/ordit-sdk"; +import { + LeatherAddressType, + signMessage as signLeatherMessage, +} from "@ordzaar/ordit-sdk/leather"; import { signMessage as signMagicEdenMessage } from "@ordzaar/ordit-sdk/magiceden"; import { signMessage as signUnisatMessage } from "@ordzaar/ordit-sdk/unisat"; import { signMessage as signXverseMessage } from "@ordzaar/ordit-sdk/xverse"; @@ -9,6 +14,19 @@ interface SignMessageParams { wallet: Wallet; address: string; network: Network; + format: AddressFormat; +} + +function leatherPaymentTypeFromFormat( + format: AddressFormat, +): LeatherAddressType { + if (format === "segwit") { + return LeatherAddressType.P2WPKH; + } + if (format === "taproot") { + return LeatherAddressType.P2TR; + } + throw new Error("Leather payment address format is not supported"); } /** @@ -22,6 +40,7 @@ export default async function signMessage({ wallet, address, network, + format, }: SignMessageParams): Promise { if (wallet === Wallet.MAGICEDEN) { const { base64 } = await signMagicEdenMessage(message, address, network); @@ -38,5 +57,14 @@ export default async function signMessage({ return base64; } + if (wallet === Wallet.LEATHER) { + const paymentType = leatherPaymentTypeFromFormat(format); + const { base64 } = await signLeatherMessage(message, { + paymentType, + network, + }); + return base64; + } + throw new Error("Invalid wallet selected"); } diff --git a/packages/ord-connect/src/lib/signPsbt.ts b/packages/ord-connect/src/lib/signPsbt.ts index 6bf648f6..1ab600fd 100644 --- a/packages/ord-connect/src/lib/signPsbt.ts +++ b/packages/ord-connect/src/lib/signPsbt.ts @@ -1,3 +1,4 @@ +import { signPsbt as signLeatherPsbt } from "@ordzaar/ordit-sdk/leather"; import { signPsbt as signMagicEdenPsbt } from "@ordzaar/ordit-sdk/magiceden"; import { signPsbt as signUnisatPsbt } from "@ordzaar/ordit-sdk/unisat"; import { signPsbt as signXversePsbt } from "@ordzaar/ordit-sdk/xverse"; @@ -83,6 +84,17 @@ export default async function signPsbt({ }); return signedXversePsbt; } + + if (wallet === Wallet.LEATHER) { + const signedLeatherPsbt = await signLeatherPsbt(psbt, { + network, + finalize, + extractTx, + allowedSighash: options?.sigHash ? [options?.sigHash] : [], + signAtIndexes: options?.signingIndexes ?? getAllInputIndices(), // If signingIndexes is not provided, just sign everything + }); + return signedLeatherPsbt; + } // else throw error throw new Error("Invalid wallet selected"); } diff --git a/packages/ord-connect/src/providers/OrdConnectProvider.tsx b/packages/ord-connect/src/providers/OrdConnectProvider.tsx index c623f444..26a7ca69 100644 --- a/packages/ord-connect/src/providers/OrdConnectProvider.tsx +++ b/packages/ord-connect/src/providers/OrdConnectProvider.tsx @@ -19,6 +19,7 @@ export enum Wallet { UNISAT = "unisat", XVERSE = "xverse", MAGICEDEN = "magiceden", + LEATHER = "leather", } export interface BiAddress { @@ -26,8 +27,8 @@ export interface BiAddress { ordinals: T | null; } -type BiAddressString = BiAddress; -type BiAddressFormat = BiAddress; +export type BiAddressString = BiAddress; +export type BiAddressFormat = BiAddress; const EMPTY_BIADDRESS_OBJECT = { payments: null, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ba07e5ee..27c6a7f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,8 +27,8 @@ importers: specifier: ^1.7.18 version: 1.7.18(react-dom@18.2.0)(react@18.2.0) '@ordzaar/ordit-sdk': - specifier: 1.3.1 - version: 1.3.1 + specifier: 1.4.0 + version: 1.4.0 bitcoinjs-lib: specifier: 6.1.5 version: 6.1.5 @@ -608,8 +608,8 @@ packages: fastq: 1.16.0 dev: true - /@ordzaar/ordit-sdk@1.3.1: - resolution: {integrity: sha512-HZZueY08wk4SjW0WRco9C2Jf2nRlmdTHxa1ulsoiJn+llHesjfSHE6O/6aHil4B3Cbn9oUVxnaj9NQi98L+mSg==} + /@ordzaar/ordit-sdk@1.4.0: + resolution: {integrity: sha512-EPg6rrVyg2JpZwlPlqNasWcVjk98WuRiW990G4sted2ZaSkGaoSZWjFeSmF7f8bERhilV2N+9CM00zI8+Qdoow==} dependencies: '@bitcoinerlab/secp256k1': 1.1.1 bignumber.js: 9.1.2 diff --git a/preview.png b/preview.png index 2a6e5437a2d3fea1e391154be1e1b6e3ad925491..cd26b60a032deca96abe36e0f0d3862b3e0c5e4c 100644 GIT binary patch literal 19388 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