From 83a99075eef2f4ec16e1473cf73d60f5d374e8f8 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Thu, 19 Dec 2024 16:08:01 +0100 Subject: [PATCH] zbd --- public/wallets/zbd-dark.svg | 1 + public/wallets/zbd.svg | 1 + wallets/zebedee/client.js | 21 +++++++++++---------- wallets/zebedee/index.js | 8 +++++--- wallets/zebedee/server.js | 13 ++++++------- 5 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 public/wallets/zbd-dark.svg create mode 100644 public/wallets/zbd.svg diff --git a/public/wallets/zbd-dark.svg b/public/wallets/zbd-dark.svg new file mode 100644 index 000000000..d2b03bd9a --- /dev/null +++ b/public/wallets/zbd-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/wallets/zbd.svg b/public/wallets/zbd.svg new file mode 100644 index 000000000..b92c3ff5c --- /dev/null +++ b/public/wallets/zbd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wallets/zebedee/client.js b/wallets/zebedee/client.js index ae3546f21..900a287c6 100644 --- a/wallets/zebedee/client.js +++ b/wallets/zebedee/client.js @@ -1,28 +1,28 @@ import { API_URL, PREIMAGE_AWAIT_TIMEOUT_MS } from '@/wallets/zebedee' import { assertContentTypeJson } from '@/lib/url' -import { withTimeout } from '@/lib/time' +import { callWithTimeout } from '@/lib/time' import { fetchWithTimeout } from '@/lib/fetch' export * from '@/wallets/zebedee' export async function testSendPayment ({ apiKey }, { signal }) { - const wallet = await apiCall('wallet', {}, { apiKey, method: 'GET' }) + const wallet = await apiCall('wallet', { apiKey, method: 'GET' }, { signal }) if (!wallet.data) throw new Error('wallet not found') } export async function sendPayment (bolt11, { apiKey }, { signal }) { - const res = await apiCall('payments', { invoice: bolt11 }, { apiKey }) + const res = await apiCall('payments', { body: { invoice: bolt11 }, apiKey }, { signal }) const { id, preimage } = res?.data if (preimage) return preimage // the api might return before the invoice is paid, so we'll wait for the preimage - return await waitForPreimage(id, { apiKey }) + return await waitForPreimage(id, { apiKey }, { signal }) } -async function waitForPreimage (id, { apiKey }) { - return await withTimeout(async () => { +async function waitForPreimage (id, { apiKey }, { signal }) { + return await callWithTimeout(async () => { let preimage while (true) { - const res = await apiCall('payments/{id}', { id }, { apiKey, method: 'GET' }) + const res = await apiCall('payments/{id}', { body: { id }, apiKey, method: 'GET' }, { signal }) preimage = res?.data?.preimage if (preimage) break await new Promise(resolve => setTimeout(resolve, 10)) @@ -31,12 +31,12 @@ async function waitForPreimage (id, { apiKey }) { }, PREIMAGE_AWAIT_TIMEOUT_MS) } -export async function apiCall (api, body, { apiKey, method = 'POST' }) { +export async function apiCall (api, { body, apiKey, method = 'POST' }, { signal }) { const headers = { apikey: apiKey, 'Content-Type': 'application/json' } - if (method === 'GET') { + if (method === 'GET' && body) { for (const [k, v] of Object.entries(body)) { api = api.replace('{' + k + '}', v) } @@ -44,6 +44,7 @@ export async function apiCall (api, body, { apiKey, method = 'POST' }) { const res = await fetchWithTimeout(API_URL + api, { method, headers, + signal, body: method === 'POST' ? JSON.stringify(body) : undefined }) // https://zbd.dev/api-reference/errors @@ -52,7 +53,7 @@ export async function apiCall (api, body, { apiKey, method = 'POST' }) { try { assertContentTypeJson(res) const json = await res.json() - if (json?.error) error = json.error + if (json?.message) error = json.message } catch (e) { error = res.statusText || 'error ' + res.status } diff --git a/wallets/zebedee/index.js b/wallets/zebedee/index.js index e70b2f72b..a88af1225 100644 --- a/wallets/zebedee/index.js +++ b/wallets/zebedee/index.js @@ -17,7 +17,7 @@ export const fields = [ label: 'api key', type: 'password', optional: 'for sending', - help: `you can get an API key from [Zebedee Dashboard](${DASHBOARD_URL}).`, + help: `you can get an API key from [Zebedee Dashboard](${DASHBOARD_URL}) from \n\`Project->API->Live\``, clientOnly: true, requiredWithout: 'gamerTagId', validate: string() @@ -27,7 +27,7 @@ export const fields = [ label: 'gamer tag or id', type: 'text', optional: 'for receiving', - help: `you can find your Gamertag in the [Zebedee Dashboard](${DASHBOARD_URL}) under 'Account' -> 'Gamertag' section, or in the Zebedee app on the Wallet card.\nNote: You can also use your @${ZEBEDEE_LNDOMAIN} Lightning address here.`, + help: `you can find your Gamertag in the [Zebedee Dashboard](${DASHBOARD_URL}) under \n\`Account->Gamertag\`\n section, or in the Zebedee app on the Wallet card.\nNote: You can also use your \`@${ZEBEDEE_LNDOMAIN}\` Lightning address here.`, serverOnly: true, requiredWithout: 'apiKey', validate: string() @@ -36,5 +36,7 @@ export const fields = [ export const card = { title: 'Zebedee', - subtitle: 'use [Zebedee](https://zebedee.io) for payments' + subtitle: 'use [Zebedee](https://zebedee.io) for payments', + image: { src: '/wallets/zbd.svg' } + } diff --git a/wallets/zebedee/server.js b/wallets/zebedee/server.js index d207bbeef..810b0576a 100644 --- a/wallets/zebedee/server.js +++ b/wallets/zebedee/server.js @@ -4,8 +4,8 @@ import { assertContentTypeJson } from '@/lib/url' export * from '@/wallets/zebedee' -async function fetchJson (url) { - let res = await fetchWithTimeout(url) +async function fetchJson (url, { signal }) { + let res = await fetchWithTimeout(url, { signal }) assertContentTypeJson(res) if (!res.ok) { res.text().catch(() => {}) @@ -23,13 +23,13 @@ function isGamerTag (value) { return value.length > 0 && value.length < 30 } -export async function fetchGamerId (value) { +export async function fetchGamerId (value, { signal }) { if (isGamerTag(value)) { const [gamerTag, domain] = value.split('@') if (domain && domain !== ZEBEDEE_LNDOMAIN) throw new Error(`invalid gamer tag: not a @${ZEBEDEE_LNDOMAIN} lightning address`) const url = GAMER_TAG_LNADDR_BASEURL + gamerTag try { - const res = await fetchJson(url) + const res = await fetchJson(url, { signal }) const callback = res.callback if (!callback) throw new Error('cannot fetch gamer id: ' + (res.statusText || 'error ' + res.status)) const gamerId = callback.substring(callback.lastIndexOf('/') + 1) @@ -42,16 +42,15 @@ export async function fetchGamerId (value) { } export async function testCreateInvoice (credentials, { signal }) { - credentials.gamerTagId = await fetchGamerId(credentials.gamerTagId) + credentials.gamerTagId = await fetchGamerId(credentials.gamerTagId, { signal }) return await createInvoice({ msats: 1000, expiry: 1 }, credentials, { signal }) } export async function createInvoice ({ msats, description, expiry }, { gamerTagId }, { signal }) { try { const url = STATIC_CHARGE_URL + gamerTagId + '?amount=' + msats + '&comment=' + description - const res = await fetchJson(url) + const res = await fetchJson(url, { signal }) if (!res.pr) throw new Error('cannot fetch invoice') - console.log('INVOICE', res.pr) return res.pr } catch (e) { throw new Error(e.message)