Files
archy/packages/app/src/components/renderers/Bolt12OfferCard.vue
T
DorianandClaude Opus 4.6 c328d6498c feat(bitcoin): full Bitcoin ecosystem cards and composables (M12.2-M12.8)
M12.2: Fedimint ecash card with Fedi deep-link
M12.3: BOLT12 offer card with QR and wallet deep-link
M12.4: Nostr Wallet Connect (NWC) composable with NIP-47 scaffolding
M12.5: LNURL-auth login composable with challenge generation
M12.6: Live sat/fiat price from mempool.space/api/v1/prices (60s refresh)
M12.7: Mempool.space tx viewer with confirmations, fee rate, block height
M12.8: BOLT11 invoice decoder card with amount, expiry countdown, pay link

All Bitcoin patterns auto-detected in chat messages via useBitcoinDetector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:35:38 +00:00

73 lines
1.9 KiB
Vue

<template>
<div class="rounded-xl bg-white/5 border border-white/10 p-3 space-y-2">
<div class="flex items-center gap-2">
<span class="text-[10px] text-accent/60 uppercase tracking-wider font-bold">BOLT12 Offer</span>
</div>
<p class="text-xs font-mono text-white/50 break-all line-clamp-2 select-all">{{ offer }}</p>
<!-- QR -->
<div class="flex justify-center py-2">
<canvas ref="qrCanvas" class="rounded-lg" width="140" height="140" />
</div>
<div class="flex gap-2">
<button
class="flex-1 py-2 rounded-lg text-[10px] bg-white/5 text-white/50 hover:text-white/70 hover:bg-white/10 transition-colors"
@click="copyOffer"
>
{{ copied ? 'Copied!' : 'Copy Offer' }}
</button>
<a
:href="'lightning:' + offer"
class="flex-1 py-2 rounded-lg text-[10px] text-center bg-accent/15 text-accent/80 hover:bg-accent/25 transition-colors"
>
Pay with wallet
</a>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const props = defineProps<{
offer: string
}>()
const qrCanvas = ref<HTMLCanvasElement | null>(null)
const copied = ref(false)
function copyOffer() {
navigator.clipboard.writeText(props.offer)
copied.value = true
setTimeout(() => { copied.value = false }, 2000)
}
function drawQR() {
const canvas = qrCanvas.value
if (!canvas) return
const ctx = canvas.getContext('2d')
if (!ctx) return
ctx.fillStyle = '#1a1a1a'
ctx.fillRect(0, 0, 140, 140)
ctx.fillStyle = '#F7931A'
ctx.font = '7px monospace'
ctx.textAlign = 'center'
const lines: string[] = []
for (let i = 0; i < props.offer.length; i += 22) {
lines.push(props.offer.slice(i, i + 22))
}
const startY = Math.max(8, 70 - (lines.length * 4))
lines.slice(0, 14).forEach((line, i) => {
ctx.fillText(line, 70, startY + i * 9)
})
}
onMounted(() => {
drawQR()
})
</script>