Skip to content

Commit

Permalink
Merge pull request #316 from omnisat/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
hathbanger authored Feb 7, 2025
2 parents b447be5 + b6f0699 commit 7fc81a9
Show file tree
Hide file tree
Showing 25 changed files with 1,392 additions and 245 deletions.
172 changes: 160 additions & 12 deletions apps/demo.lasereyes.build/components/WalletCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
OP_NET,
ProviderType,
SPARROW,
SendArgs,
} from '@omnisat/lasereyes'
import {
Card,
Expand All @@ -42,6 +43,13 @@ import { ImNewTab } from 'react-icons/im'
import { cn } from '@/lib/utils'
import { useUtxos } from '@/hooks/useUtxos'
import { Input } from '@/components/ui/input'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"

const WalletCard = ({
wallet,
Expand All @@ -60,10 +68,10 @@ const WalletCard = ({
setSignedPsbt: (
psbt:
| {
signedPsbtHex: string
signedPsbtBase64: string
txId?: string
}
signedPsbtHex: string
signedPsbtBase64: string
txId?: string
}
| undefined
) => void
}) => {
Expand Down Expand Up @@ -94,8 +102,10 @@ const WalletCard = ({
signMessage,
signPsbt,
inscribe,
send,
pushPsbt,
switchNetwork,
getMetaBalances
} = useLaserEyes()

const [hasError, setHasError] = useState(false)
Expand All @@ -110,6 +120,19 @@ const WalletCard = ({
'Inscribed 100% clientside with Laser Eyes'
)

const [runes, setRunes] = useState<{
balance: string;
symbol: string;
name: string;
}[] | undefined>()
const [selectedRune, setSelectedRune] = useState<{
balance: string;
symbol: string;
name: string;
} | undefined>(undefined);
const [runeToAddress, setRuneToAddress] = useState<string>('')
const [runeAmount, setRuneAmount] = useState<string>('')

const hasWallet = {
unisat: hasUnisat,
xverse: hasXverse,
Expand Down Expand Up @@ -144,12 +167,12 @@ const WalletCard = ({
paymentAddress,
paymentPublicKey,
network as
| typeof MAINNET
| typeof TESTNET
| typeof TESTNET4
| typeof SIGNET
| typeof FRACTAL_MAINNET
| typeof FRACTAL_TESTNET
| typeof MAINNET
| typeof TESTNET
| typeof TESTNET4
| typeof SIGNET
| typeof FRACTAL_MAINNET
| typeof FRACTAL_TESTNET
)
.then((psbt) => {
if (psbt && psbt.toHex() !== unsigned) {
Expand Down Expand Up @@ -182,7 +205,14 @@ const WalletCard = ({
setUnsigned(undefined)
}, [network])

const send = async () => {
useEffect(() => {
if (address) {
getMetaBalances("runes").then(setRunes)
setRuneToAddress(address)
}
}, [address])

const sendBtc = async () => {
try {
if (balance! < 1500) {
throw new Error('Insufficient funds')
Expand Down Expand Up @@ -405,6 +435,42 @@ const WalletCard = ({
}
}, [inscribe, inscriptionText, network])


const sendRune = async () => {
try {
if (!selectedRune) throw new Error('No rune selected')
if (!address) throw new Error('No address available')
if (!runeToAddress) throw new Error('No destination address provided')
if (!runeAmount) throw new Error('No amount specified')

const txid = await send("runes", {
fromAddress: address,
toAddress: runeToAddress,
amount: Number(runeAmount),
runeId: selectedRune.name,
} as SendArgs)

toast.success(
<span className={'flex flex-col gap-1 items-center justify-center'}>
<span className={'font-black'}>View on mempool.space</span>
<a
target={'_blank'}
href={`${getMempoolSpaceUrl(
network as typeof MAINNET | typeof TESTNET
)}/tx/${txid}`}
className={'underline text-blue-600 text-xs'}
>
{txid}
</a>
</span>
)
} catch (error) {
if (error instanceof Error) {
toast.error(error.message)
}
}
}

return (
<Card
className={
Expand Down Expand Up @@ -500,7 +566,7 @@ const WalletCard = ({
className={'w-full bg-[#232225]'}
disabled={isMissingWallet || !isConnected}
variant={!isConnected ? 'secondary' : 'default'}
onClick={() => (!isConnected ? null : send())}
onClick={() => (!isConnected ? null : sendBtc())}
>
send BTC
</Button>
Expand Down Expand Up @@ -589,6 +655,88 @@ const WalletCard = ({
>
inscribe
</Button>

<div className={'border-b border-2 border-[#232225] w-full my-2'} />
<div className="flex flex-col w-full gap-2">

<Select
onValueChange={(value) => {
const rune = runes?.find((r) => r.symbol === value);
setSelectedRune(rune);
}}
disabled={
isMissingWallet ||
!isConnected
}
>
<SelectTrigger
disabled={
isMissingWallet ||
!isConnected
}
className={cn(
'w-full bg-[#232225] border-none disabled:text-[#737275] text-center',
''
)}
>
<SelectValue placeholder="Select a Rune" />
<div className="grow" />
<Badge variant={'success'} className={'text-gray-900'}>
beta
</Badge>
</SelectTrigger>
<SelectContent>
{runes?.map((rune, index) => (
<SelectItem key={index} value={rune.symbol}>
{rune.name} ({rune.balance})
</SelectItem>
))}
</SelectContent>
</Select>
<Input
disabled={
isMissingWallet ||
!isConnected ||
!selectedRune
}
className={cn(
'w-full bg-[#232225] border-none disabled:text-[#737275] text-center',
''
)}
placeholder="To Address"
value={runeToAddress}
onChange={(e) => setRuneToAddress(e.target.value)}
/>
<Input
disabled={
isMissingWallet ||
!isConnected ||
!selectedRune ||
!runeToAddress
}
type="number"
className={cn(
'w-full bg-[#232225] border-none disabled:text-[#737275] text-center',
''
)}
placeholder="Amount"
value={runeAmount}
onChange={(e) => setRuneAmount(e.target.value)}
/>
<Button
disabled={
isMissingWallet ||
!isConnected ||
!selectedRune ||
!runeToAddress ||
!runeAmount
}
className={'w-full bg-[#232225] disabled:text-[#737275]'}
onClick={sendRune}
>
Send Rune
</Button>
</div>
</div>
</div>
</CardContent>
Expand Down
3 changes: 2 additions & 1 deletion packages/lasereyes-core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@omnisat/lasereyes-core",
"private": false,
"version": "0.0.59",
"version": "0.0.60-rc.1",
"type": "module",
"main": "./dist/index.umd.cjs",
"module": "./dist/index.js",
Expand Down Expand Up @@ -31,6 +31,7 @@
"@bitcoinerlab/secp256k1": "^1.1.1",
"@cmdcode/crypto-utils": "^2.4.6",
"@cmdcode/tapscript": "^1.4.6",
"@magiceden-oss/runestone-lib": "^1.0.2",
"@nanostores/persistent": "^0.10.2",
"@orangecrypto/orange-connect": "^1.2.2",
"axios": "^1.7.7",
Expand Down
48 changes: 46 additions & 2 deletions packages/lasereyes-core/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { MapStore, WritableAtom, keepMount, listenKeys } from 'nanostores'

import { Config, ContentType, NetworkType, ProviderType } from '../types'
import { BTCSendArgs, Config, ContentType, NetworkType, Protocol, ProviderType, RuneSendArgs } from '../types'
import {
LEATHER,
MAGIC_EDEN,
Expand Down Expand Up @@ -340,6 +339,27 @@ export class LaserEyesClient {
}
}

async send(protocol: Protocol, sendArgs: BTCSendArgs | RuneSendArgs) {
if (!this.$store.get().provider) return
if (this.$providerMap[this.$store.get().provider!]) {
try {
return await this.$providerMap[this.$store.get().provider!]?.send(
protocol,
sendArgs
)
} catch (error) {
if (error instanceof Error) {
if (error.message.toLowerCase().includes('not implemented')) {
throw new Error(
"The connected wallet doesn't support sending stuff..."
)
}
}
throw error
}
}
}

async getPublicKey() {
if (!this.$store.get().provider) return
if (this.$providerMap[this.$store.get().provider!]) {
Expand Down Expand Up @@ -377,6 +397,30 @@ export class LaserEyesClient {
}
}

async getMetaBalances(protocol: Protocol) {
if (!this.$store.get().provider) return
if (this.$providerMap[this.$store.get().provider!]) {
try {
if (!protocol) {
throw new Error('No protocol provided')
}

const balances =
await this.$providerMap[this.$store.get().provider!]!.getMetaBalances(protocol)
// TODO: Decide if we want to store these balances
// this.$store.setKey(`${protocol}Balances`, JSON.stringify(balances))
return balances
} catch (error) {
if (error instanceof Error) {
if (error.message.toLowerCase().includes('not implemented')) {
throw new Error("The connected wallet doesn't support getBalance")
}
}
throw error
}
}
}

async getInscriptions(offset?: number, limit?: number) {
if (!this.$store.get().provider) return
if (this.$providerMap[this.$store.get().provider!]) {
Expand Down
Loading

0 comments on commit 7fc81a9

Please sign in to comment.