aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-24 13:47:11 -0700
committerAdam Soltys <[email protected]>2026-06-24 13:47:11 -0700
commiteb299830a2611a45e997bc729176ede81c5eead2 (patch)
treecffe8b1f2ddc1e8b0698262b128c4f5d83acf9e9 /src
parent7234a3de9e200f36accb754f62163f0bd5360832 (diff)
downloadcoinosv3-eb299830a2611a45e997bc729176ede81c5eead2.tar.gz
coinosv3-eb299830a2611a45e997bc729176ede81c5eead2.zip
Make gift Reclaim a real on-chain revoke
The old "Reclaim" only un-reserved the coin locally, so the gift link stayed claimable. Replace it with "Revoke": a confirmed action that sweeps the reserved coin back into the sender's own wallet at a high fee (wallet.revokeGift), double-spending the gift's presigned input so the link can't be claimed once it confirms. Races a simultaneous claimer; if the gift was already claimed the broadcast just fails. New strings translated across all 19 locales. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/app.js35
-rw-r--r--src/i18n.js4
-rw-r--r--src/locales/ar.json8
-rw-r--r--src/locales/bn.json8
-rw-r--r--src/locales/de.json8
-rw-r--r--src/locales/es.json8
-rw-r--r--src/locales/fr.json6
-rw-r--r--src/locales/hi.json8
-rw-r--r--src/locales/id.json8
-rw-r--r--src/locales/ja.json8
-rw-r--r--src/locales/ko.json6
-rw-r--r--src/locales/mr.json8
-rw-r--r--src/locales/pt.json6
-rw-r--r--src/locales/ru.json8
-rw-r--r--src/locales/sw.json8
-rw-r--r--src/locales/ta.json6
-rw-r--r--src/locales/te.json8
-rw-r--r--src/locales/tr.json6
-rw-r--r--src/locales/ur.json8
-rw-r--r--src/locales/vi.json8
-rw-r--r--src/locales/zh.json6
-rw-r--r--src/wallet.js11
22 files changed, 136 insertions, 54 deletions
diff --git a/src/app.js b/src/app.js
index 4ceebc0..b112f02 100644
--- a/src/app.js
+++ b/src/app.js
@@ -38,6 +38,7 @@ const ui = {
giftAmount: '', // gift-create amount input (Settings)
giftCode: null, // last-created gift PSBT code
giftError: '',
+ revokeId: null, // outpoint of a gift being revoked (confirm state)
claimCode: null, // gift code being claimed (opened from a #gift= link)
claimedAmount: 0,
claimError: '',
@@ -614,6 +615,7 @@ function lock() {
ui.giftAmount = '';
ui.giftCode = null;
ui.giftError = '';
+ ui.revokeId = null;
ui.receiveSeenIndex = null;
ui.txDetail = null;
ui.broadcastTx = null;
@@ -750,9 +752,21 @@ function giftCard() {
h('span', { class: 'small muted' }, t('giftReserved', { n: active.length })),
...active.map((id) => {
const u = wallet.utxos.find((x) => utxoId(x) === id);
+ const label = u ? fmtAmount(u.value) + ' ' + unitLabel() : id.slice(0, 12) + '…';
+ if (ui.revokeId === id) {
+ return h('div', { class: 'col gap6' },
+ h('span', { class: 'small muted' }, t('giftRevokeConfirm')),
+ h('div', { class: 'row gap6' },
+ ui.busy
+ ? h('button', { class: 'btn-primary grow', disabled: true }, h('span', { class: 'spinner' }))
+ : h('button', { class: 'btn-primary grow', onClick: () => doRevoke(id) }, t('giftRevoke')),
+ h('button', { class: 'btn-ghost grow', onClick: () => { ui.revokeId = null; render(); } }, t('back'))
+ )
+ );
+ }
return h('div', { class: 'row between' },
- h('span', { class: 'small mono' }, u ? fmtAmount(u.value) + ' ' + unitLabel() : id.slice(0, 12) + '…'),
- h('button', { class: 'btn-sm', onClick: () => { wallet.unreserve(id); render(); } }, t('giftReclaim'))
+ h('span', { class: 'small mono' }, label),
+ h('button', { class: 'btn-sm', onClick: () => { ui.revokeId = id; render(); } }, t('giftRevoke'))
);
})
)
@@ -760,6 +774,23 @@ function giftCard() {
);
}
+async function doRevoke(id) {
+ if (wallet.offline) { toast(t('scanOffline')); return; }
+ ui.busy = true;
+ render();
+ try {
+ const rate = (wallet.feeRates && wallet.feeRates.fastestFee) || 10;
+ await wallet.revokeGift(id, rate);
+ ui.revokeId = null;
+ toast(t('giftRevoked'));
+ wallet.scan().catch(() => {});
+ } catch (e) {
+ toast(e.message);
+ }
+ ui.busy = false;
+ render();
+}
+
// Block explorer / server selection: a preset (mempool.space, blockstream.info)
// or a custom Esplora/electrs REST URL (e.g. your own node).
function explorerCard() {
diff --git a/src/i18n.js b/src/i18n.js
index 017b6fa..b879a08 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -154,7 +154,9 @@ const STR = {
giftAmountInvalid: 'Enter a valid amount.',
giftAnother: 'Create another',
giftReserved: '{n} coin set aside for unclaimed gifts',
- giftReclaim: 'Reclaim',
+ giftRevoke: 'Revoke',
+ giftRevokeConfirm: 'Revoke this gift? This spends the coin back into your wallet and stops the link from working.',
+ giftRevoked: 'Gift revoked',
copyLink: 'Copy link',
claimBody: 'Claim it into a brand-new wallet that only you control.',
claimBtn: 'Claim it',
diff --git a/src/locales/ar.json b/src/locales/ar.json
index 57f2ea6..bbac720 100644
--- a/src/locales/ar.json
+++ b/src/locales/ar.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "أدخل مبلغاً صحيحاً.",
"giftAnother": "إنشاء آخر",
"giftReserved": "{n} عملة مخصّصة للهدايا غير المُطالَب بها",
- "giftReclaim": "استرجاع",
"claimBody": "طالب بها في محفظة جديدة تماماً تتحكم بها وحدك.",
"claimBtn": "طالب بها",
"claimFailed": "تمت المطالبة بهذه الهدية بالفعل أو لم تعد متاحة.",
"claimedTitle": "تمت المطالبة!",
"claimedBody": "عملات Bitcoin الخاصة بك في طريقها إليك. احتفظ بنسخة احتياطية من عبارة الاسترداد لإبقائها آمنة.",
"giftLinkReveal": "إنشاء رابط الإهداء",
- "copyLink": "نسخ الرابط"
-}
+ "copyLink": "نسخ الرابط",
+ "giftRevoke": "إلغاء",
+ "giftRevokeConfirm": "إلغاء هذه الهدية؟ يعيد ذلك العملة إلى محفظتك ويوقف عمل الرابط.",
+ "giftRevoked": "تم إلغاء الهدية"
+} \ No newline at end of file
diff --git a/src/locales/bn.json b/src/locales/bn.json
index 30b92a4..2c28359 100644
--- a/src/locales/bn.json
+++ b/src/locales/bn.json
@@ -158,10 +158,12 @@
"giftAmountInvalid": "একটি সঠিক পরিমাণ লিখুন।",
"giftAnother": "আরেকটি তৈরি করুন",
"giftReserved": "{n} কয়েন অদাবিকৃত উপহারের জন্য সরিয়ে রাখা হয়েছে",
- "giftReclaim": "ফেরত নিন",
"claimBody": "এটি একটি একদম নতুন ওয়ালেটে দাবি করুন, যা কেবল আপনিই নিয়ন্ত্রণ করেন।",
"claimBtn": "দাবি করুন",
"claimFailed": "এই উপহারটি আগেই দাবি করা হয়েছে অথবা আর পাওয়া যাচ্ছে না।",
"claimedTitle": "দাবি করা হয়েছে!",
- "claimedBody": "আপনার Bitcoin আসছে। এটি নিরাপদ রাখতে আপনার রিকভারি ফ্রেজ ব্যাকআপ করে নিন।"
-}
+ "claimedBody": "আপনার Bitcoin আসছে। এটি নিরাপদ রাখতে আপনার রিকভারি ফ্রেজ ব্যাকআপ করে নিন।",
+ "giftRevoke": "বাতিল করুন",
+ "giftRevokeConfirm": "এই উপহার বাতিল করবেন? এটি কয়েনটি আপনার ওয়ালেটে ফেরত পাঠায় এবং লিঙ্কটি কাজ করা বন্ধ করে।",
+ "giftRevoked": "উপহার বাতিল হয়েছে"
+} \ No newline at end of file
diff --git a/src/locales/de.json b/src/locales/de.json
index 0b7b11e..8af72e0 100644
--- a/src/locales/de.json
+++ b/src/locales/de.json
@@ -160,10 +160,12 @@
"giftAmountInvalid": "Gib einen gültigen Betrag ein.",
"giftAnother": "Weiteres erstellen",
"giftReserved": "{n} Coin für unbeanspruchte Geschenke zurückgelegt",
- "giftReclaim": "Zurückfordern",
"claimBody": "Beanspruche es in einer brandneuen Wallet, die nur du selbst kontrollierst.",
"claimBtn": "Beanspruchen",
"claimFailed": "Dieses Geschenk wurde bereits beansprucht oder ist nicht mehr verfügbar.",
"claimedTitle": "Beansprucht!",
- "claimedBody": "Dein Bitcoin ist unterwegs. Sichere deine Wiederherstellungsphrase, um es zu schützen."
-}
+ "claimedBody": "Dein Bitcoin ist unterwegs. Sichere deine Wiederherstellungsphrase, um es zu schützen.",
+ "giftRevoke": "Widerrufen",
+ "giftRevokeConfirm": "Dieses Geschenk widerrufen? Die Münze geht zurück in deine Wallet und der Link funktioniert nicht mehr.",
+ "giftRevoked": "Geschenk widerrufen"
+} \ No newline at end of file
diff --git a/src/locales/es.json b/src/locales/es.json
index e1f1d43..5d4c3b2 100644
--- a/src/locales/es.json
+++ b/src/locales/es.json
@@ -160,10 +160,12 @@
"giftAmountInvalid": "Introduce un importe válido.",
"giftAnother": "Crear otro",
"giftReserved": "{n} de monedas reservadas para regalos sin reclamar",
- "giftReclaim": "Recuperar",
"claimBody": "Reclámalo en una billetera totalmente nueva que solo tú controlas.",
"claimBtn": "Reclamarlo",
"claimFailed": "Este regalo ya ha sido reclamado o ya no está disponible.",
"claimedTitle": "¡Reclamado!",
- "claimedBody": "Tu Bitcoin está en camino. Haz una copia de seguridad de tu frase de recuperación para mantenerlo a salvo."
-}
+ "claimedBody": "Tu Bitcoin está en camino. Haz una copia de seguridad de tu frase de recuperación para mantenerlo a salvo.",
+ "giftRevoke": "Revocar",
+ "giftRevokeConfirm": "¿Revocar este regalo? Esto devuelve la moneda a tu monedero y desactiva el enlace.",
+ "giftRevoked": "Regalo revocado"
+} \ No newline at end of file
diff --git a/src/locales/fr.json b/src/locales/fr.json
index 8754e3a..1cd7992 100644
--- a/src/locales/fr.json
+++ b/src/locales/fr.json
@@ -160,10 +160,12 @@
"giftAmountInvalid": "Saisissez un montant valide.",
"giftAnother": "En créer un autre",
"giftReserved": "{n} de fonds mis de côté pour des cadeaux non réclamés",
- "giftReclaim": "Récupérer",
"claimBody": "Récupérez-les dans un tout nouveau portefeuille que vous seul contrôlez.",
"claimBtn": "Récupérer",
"claimFailed": "Ce cadeau a déjà été réclamé ou n’est plus disponible.",
"claimedTitle": "Récupéré !",
- "claimedBody": "Vos Bitcoin sont en route. Sauvegardez votre phrase de récupération pour les garder en sécurité."
+ "claimedBody": "Vos Bitcoin sont en route. Sauvegardez votre phrase de récupération pour les garder en sécurité.",
+ "giftRevoke": "Révoquer",
+ "giftRevokeConfirm": "Révoquer ce cadeau ? La pièce revient dans votre portefeuille et le lien cesse de fonctionner.",
+ "giftRevoked": "Cadeau révoqué"
} \ No newline at end of file
diff --git a/src/locales/hi.json b/src/locales/hi.json
index b3b439f..10b548c 100644
--- a/src/locales/hi.json
+++ b/src/locales/hi.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "एक मान्य राशि दर्ज करें।",
"giftAnother": "एक और बनाएँ",
"giftReserved": "{n} सिक्का बिना दावे वाले उपहारों के लिए अलग रखा गया",
- "giftReclaim": "वापस लें",
"claimBody": "इसे एक बिल्कुल नए वॉलेट में प्राप्त करें जिसे केवल आप नियंत्रित करते हैं।",
"claimBtn": "इसे प्राप्त करें",
"claimFailed": "इस उपहार का दावा पहले ही किया जा चुका है या यह अब उपलब्ध नहीं है।",
"claimedTitle": "प्राप्त हो गया!",
"claimedBody": "आपका Bitcoin रास्ते में है। इसे सुरक्षित रखने के लिए अपने रिकवरी वाक्यांश का बैकअप लें।",
"giftLinkReveal": "उपहार लिंक बनाएँ",
- "copyLink": "लिंक कॉपी करें"
-}
+ "copyLink": "लिंक कॉपी करें",
+ "giftRevoke": "रद्द करें",
+ "giftRevokeConfirm": "यह उपहार रद्द करें? यह सिक्का आपके वॉलेट में वापस भेज देता है और लिंक काम करना बंद कर देता है।",
+ "giftRevoked": "उपहार रद्द किया गया"
+} \ No newline at end of file
diff --git a/src/locales/id.json b/src/locales/id.json
index 7255730..924cdd5 100644
--- a/src/locales/id.json
+++ b/src/locales/id.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "Masukkan jumlah yang valid.",
"giftAnother": "Buat lagi",
"giftReserved": "{n} koin disisihkan untuk hadiah yang belum diklaim",
- "giftReclaim": "Ambil kembali",
"claimBody": "Klaim ke dompet baru yang hanya Anda kendalikan.",
"claimBtn": "Klaim",
"claimFailed": "Hadiah ini sudah diklaim atau tidak lagi tersedia.",
"claimedTitle": "Diklaim!",
"claimedBody": "Bitcoin Anda sedang dalam perjalanan. Cadangkan frasa pemulihan Anda agar tetap aman.",
"giftLinkReveal": "Buat tautan hadiah",
- "copyLink": "Salin tautan"
-}
+ "copyLink": "Salin tautan",
+ "giftRevoke": "Cabut",
+ "giftRevokeConfirm": "Cabut hadiah ini? Ini mengembalikan koin ke dompet Anda dan menonaktifkan tautannya.",
+ "giftRevoked": "Hadiah dicabut"
+} \ No newline at end of file
diff --git a/src/locales/ja.json b/src/locales/ja.json
index 346f096..739bd4b 100644
--- a/src/locales/ja.json
+++ b/src/locales/ja.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "有効な金額を入力してください。",
"giftAnother": "もう一つ作成",
"giftReserved": "未受取のギフト用に {n} のコインを確保中",
- "giftReclaim": "回収",
"claimBody": "あなただけが管理できる真新しいウォレットに受け取りましょう。",
"claimBtn": "受け取る",
"claimFailed": "このギフトはすでに受け取られたか、現在利用できません。",
"claimedTitle": "受け取りました!",
"claimedBody": "Bitcoin が間もなく届きます。安全に保つため、復元フレーズをバックアップしてください。",
"giftLinkReveal": "ギフトリンクを作成",
- "copyLink": "リンクをコピー"
-}
+ "copyLink": "リンクをコピー",
+ "giftRevoke": "取り消す",
+ "giftRevokeConfirm": "このギフトを取り消しますか?コインがウォレットに戻り、リンクは無効になります。",
+ "giftRevoked": "ギフトを取り消しました"
+} \ No newline at end of file
diff --git a/src/locales/ko.json b/src/locales/ko.json
index 3d0face..265d55c 100644
--- a/src/locales/ko.json
+++ b/src/locales/ko.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "올바른 금액을 입력하세요.",
"giftAnother": "또 만들기",
"giftReserved": "받지 않은 선물을 위해 따로 둔 코인 {n}개",
- "giftReclaim": "되찾기",
"claimBody": "자신만 통제하는 완전히 새로운 지갑으로 받으세요.",
"claimBtn": "받기",
"claimFailed": "이 선물은 이미 수령되었거나 더 이상 이용할 수 없습니다.",
"claimedTitle": "수령 완료!",
"claimedBody": "Bitcoin이 전송되고 있습니다. 안전하게 보관하려면 복구 문구를 백업하세요.",
"giftLinkReveal": "선물 링크 만들기",
- "copyLink": "링크 복사"
+ "copyLink": "링크 복사",
+ "giftRevoke": "취소",
+ "giftRevokeConfirm": "이 선물을 취소할까요? 코인이 지갑으로 돌아가고 링크가 작동하지 않게 됩니다.",
+ "giftRevoked": "선물이 취소됨"
} \ No newline at end of file
diff --git a/src/locales/mr.json b/src/locales/mr.json
index f5f0e8e..748713e 100644
--- a/src/locales/mr.json
+++ b/src/locales/mr.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "वैध रक्कम टाका.",
"giftAnother": "आणखी एक तयार करा",
"giftReserved": "{n} नाणी न घेतलेल्या भेटींसाठी बाजूला ठेवली",
- "giftReclaim": "परत मिळवा",
"claimBody": "ते फक्त तुमच्याच नियंत्रणातील एका नव्या कोऱ्या वॉलेटमध्ये घ्या.",
"claimBtn": "ते घ्या",
"claimFailed": "ही भेट आधीच घेतली गेली आहे किंवा आता उपलब्ध नाही.",
"claimedTitle": "घेतले!",
"claimedBody": "तुमचे Bitcoin येत आहे. ते सुरक्षित ठेवण्यासाठी तुमच्या रिकव्हरी वाक्यांशाचा बॅकअप घ्या.",
"giftLinkReveal": "भेट लिंक तयार करा",
- "copyLink": "लिंक कॉपी करा"
-}
+ "copyLink": "लिंक कॉपी करा",
+ "giftRevoke": "रद्द करा",
+ "giftRevokeConfirm": "ही भेट रद्द करायची? हे नाणे तुमच्या वॉलेटमध्ये परत पाठवते आणि लिंक काम करणे थांबवते.",
+ "giftRevoked": "भेट रद्द केली"
+} \ No newline at end of file
diff --git a/src/locales/pt.json b/src/locales/pt.json
index b0b1093..db2d2f2 100644
--- a/src/locales/pt.json
+++ b/src/locales/pt.json
@@ -160,10 +160,12 @@
"giftAmountInvalid": "Digite um valor válido.",
"giftAnother": "Criar outro",
"giftReserved": "{n} de moeda reservada para presentes não resgatados",
- "giftReclaim": "Recuperar",
"claimBody": "Resgate para uma carteira novinha que só você controla.",
"claimBtn": "Resgatar",
"claimFailed": "Este presente já foi resgatado ou não está mais disponível.",
"claimedTitle": "Resgatado!",
- "claimedBody": "Seus Bitcoin estão a caminho. Faça backup da sua frase de recuperação para mantê-los seguros."
+ "claimedBody": "Seus Bitcoin estão a caminho. Faça backup da sua frase de recuperação para mantê-los seguros.",
+ "giftRevoke": "Revogar",
+ "giftRevokeConfirm": "Revogar este presente? Isso devolve a moeda à sua carteira e o link para de funcionar.",
+ "giftRevoked": "Presente revogado"
} \ No newline at end of file
diff --git a/src/locales/ru.json b/src/locales/ru.json
index 5ef7967..8673803 100644
--- a/src/locales/ru.json
+++ b/src/locales/ru.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "Введите корректную сумму.",
"giftAnother": "Создать ещё один",
"giftReserved": "{n} монет отложено для невостребованных подарков",
- "giftReclaim": "Вернуть",
"claimBody": "Получите его в совершенно новый кошелёк, которым управляете только вы.",
"claimBtn": "Получить",
"claimFailed": "Этот подарок уже получен или больше недоступен.",
"claimedTitle": "Получено!",
"claimedBody": "Ваш Bitcoin уже в пути. Сделайте резервную копию фразы восстановления, чтобы сохранить его в безопасности.",
"giftLinkReveal": "Создать ссылку-подарок",
- "copyLink": "Копировать ссылку"
-}
+ "copyLink": "Копировать ссылку",
+ "giftRevoke": "Отозвать",
+ "giftRevokeConfirm": "Отозвать этот подарок? Монета вернётся в ваш кошелёк, а ссылка перестанет работать.",
+ "giftRevoked": "Подарок отозван"
+} \ No newline at end of file
diff --git a/src/locales/sw.json b/src/locales/sw.json
index 1f5c9e5..5a53296 100644
--- a/src/locales/sw.json
+++ b/src/locales/sw.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "Ingiza kiasi sahihi.",
"giftAnother": "Tengeneza nyingine",
"giftReserved": "{n} sarafu imewekwa kando kwa zawadi ambazo hazijadaiwa",
- "giftReclaim": "Dai tena",
"claimBody": "Idai kwenye pochi mpya kabisa unayoidhibiti wewe pekee.",
"claimBtn": "Idai",
"claimFailed": "Zawadi hii tayari imedaiwa au haipatikani tena.",
"claimedTitle": "Imedaiwa!",
"claimedBody": "Bitcoin yako inakuja. Hifadhi kifungu chako cha kurejesha ili kuilinda.",
"giftLinkReveal": "Tengeneza kiungo cha zawadi",
- "copyLink": "Nakili kiungo"
-}
+ "copyLink": "Nakili kiungo",
+ "giftRevoke": "Batilisha",
+ "giftRevokeConfirm": "Batilisha zawadi hii? Hii inarudisha sarafu kwenye pochi yako na kiungo kinaacha kufanya kazi.",
+ "giftRevoked": "Zawadi imebatilishwa"
+} \ No newline at end of file
diff --git a/src/locales/ta.json b/src/locales/ta.json
index 6fce3fb..464bd9b 100644
--- a/src/locales/ta.json
+++ b/src/locales/ta.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "சரியான தொகையை உள்ளிடவும்.",
"giftAnother": "மற்றொன்றை உருவாக்கு",
"giftReserved": "உரிமை கொள்ளப்படாத பரிசுகளுக்காக {n} நாணயம் ஒதுக்கப்பட்டுள்ளது",
- "giftReclaim": "மீட்டெடு",
"claimBody": "நீங்கள் மட்டுமே கட்டுப்படுத்தும் புத்தம்புதிய வாலட்டிற்குள் இதை உரிமை கொள்ளுங்கள்.",
"claimBtn": "உரிமை கொள்",
"claimFailed": "இந்தப் பரிசு ஏற்கனவே உரிமை கொள்ளப்பட்டுவிட்டது அல்லது இனி கிடைக்கவில்லை.",
"claimedTitle": "உரிமை கொள்ளப்பட்டது!",
"claimedBody": "உங்கள் Bitcoin வந்துகொண்டிருக்கிறது. அதைப் பாதுகாப்பாக வைக்க உங்கள் மீட்பு சொற்றொடரைக் காப்புப்பிரதி எடுங்கள்.",
"giftLinkReveal": "பரிசு இணைப்பை உருவாக்கு",
- "copyLink": "இணைப்பை நகலெடு"
+ "copyLink": "இணைப்பை நகலெடு",
+ "giftRevoke": "திரும்பப் பெறு",
+ "giftRevokeConfirm": "இந்த பரிசை திரும்பப் பெறவா? இது நாணயத்தை உங்கள் வாலெட்டுக்குத் திருப்பி, இணைப்பு செயல்படுவதை நிறுத்தும்.",
+ "giftRevoked": "பரிசு திரும்பப் பெறப்பட்டது"
} \ No newline at end of file
diff --git a/src/locales/te.json b/src/locales/te.json
index 06dcd72..81bfa9a 100644
--- a/src/locales/te.json
+++ b/src/locales/te.json
@@ -158,10 +158,12 @@
"giftAmountInvalid": "సరైన మొత్తాన్ని నమోదు చేయండి.",
"giftAnother": "మరొకటి సృష్టించు",
"giftReserved": "క్లెయిమ్ చేయని బహుమతుల కోసం {n} నాణేలు పక్కన పెట్టబడ్డాయి",
- "giftReclaim": "తిరిగి పొందు",
"claimBody": "మీరు మాత్రమే నియంత్రించే సరికొత్త వాలెట్‌లోకి దాన్ని క్లెయిమ్ చేసుకోండి.",
"claimBtn": "క్లెయిమ్ చేసుకోండి",
"claimFailed": "ఈ బహుమతి ఇప్పటికే క్లెయిమ్ చేయబడింది లేదా ఇక అందుబాటులో లేదు.",
"claimedTitle": "క్లెయిమ్ అయింది!",
- "claimedBody": "మీ Bitcoin మీ వద్దకు వస్తోంది. దాన్ని సురక్షితంగా ఉంచడానికి మీ రికవరీ ఫ్రేజ్‌ను బ్యాకప్ చేయండి."
-}
+ "claimedBody": "మీ Bitcoin మీ వద్దకు వస్తోంది. దాన్ని సురక్షితంగా ఉంచడానికి మీ రికవరీ ఫ్రేజ్‌ను బ్యాకప్ చేయండి.",
+ "giftRevoke": "రద్దు చేయి",
+ "giftRevokeConfirm": "ఈ బహుమతిని రద్దు చేయాలా? ఇది నాణేన్ని మీ వాలెట్‌కు తిరిగి పంపి, లింక్ పనిచేయడం ఆపేస్తుంది.",
+ "giftRevoked": "బహుమతి రద్దు చేయబడింది"
+} \ No newline at end of file
diff --git a/src/locales/tr.json b/src/locales/tr.json
index 39eab0f..8956c9c 100644
--- a/src/locales/tr.json
+++ b/src/locales/tr.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "Geçerli bir tutar girin.",
"giftAnother": "Bir tane daha oluştur",
"giftReserved": "Talep edilmemiş hediyeler için {n} coin ayrıldı",
- "giftReclaim": "Geri al",
"claimBody": "Yalnızca kendi kontrolünüzdeki yepyeni bir cüzdana alın.",
"claimBtn": "Talep et",
"claimFailed": "Bu hediye zaten talep edilmiş veya artık kullanılamıyor.",
"claimedTitle": "Talep edildi!",
"claimedBody": "Bitcoin’iniz yolda. Güvende tutmak için kurtarma ifadenizi yedekleyin.",
"giftLinkReveal": "Hediye bağlantısı oluştur",
- "copyLink": "Bağlantıyı kopyala"
+ "copyLink": "Bağlantıyı kopyala",
+ "giftRevoke": "İptal et",
+ "giftRevokeConfirm": "Bu hediye iptal edilsin mi? Bu, parayı cüzdanınıza geri gönderir ve bağlantıyı devre dışı bırakır.",
+ "giftRevoked": "Hediye iptal edildi"
} \ No newline at end of file
diff --git a/src/locales/ur.json b/src/locales/ur.json
index 417f9f8..8bbf3e5 100644
--- a/src/locales/ur.json
+++ b/src/locales/ur.json
@@ -160,10 +160,12 @@
"giftAmountInvalid": "درست رقم درج کریں۔",
"giftAnother": "ایک اور بنائیں",
"giftReserved": "{n} سکے غیر وصول شدہ تحائف کے لیے الگ رکھے گئے",
- "giftReclaim": "واپس لیں",
"claimBody": "اسے ایک بالکل نئے والیٹ میں وصول کریں جو صرف آپ کے کنٹرول میں ہو۔",
"claimBtn": "وصول کریں",
"claimFailed": "اس تحفے کا پہلے ہی دعویٰ کیا جا چکا ہے یا یہ اب دستیاب نہیں۔",
"claimedTitle": "وصول ہو گیا!",
- "claimedBody": "آپ کا Bitcoin راستے میں ہے۔ اسے محفوظ رکھنے کے لیے اپنے بحالی فقرے کا بیک اپ بنا لیں۔"
-}
+ "claimedBody": "آپ کا Bitcoin راستے میں ہے۔ اسے محفوظ رکھنے کے لیے اپنے بحالی فقرے کا بیک اپ بنا لیں۔",
+ "giftRevoke": "منسوخ کریں",
+ "giftRevokeConfirm": "یہ تحفہ منسوخ کریں؟ یہ سکہ آپ کے والیٹ میں واپس بھیج دیتا ہے اور لنک کام کرنا بند کر دیتا ہے۔",
+ "giftRevoked": "تحفہ منسوخ ہو گیا"
+} \ No newline at end of file
diff --git a/src/locales/vi.json b/src/locales/vi.json
index 2c7786f..4de3cd0 100644
--- a/src/locales/vi.json
+++ b/src/locales/vi.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "Nhập một số tiền hợp lệ.",
"giftAnother": "Tạo cái khác",
"giftReserved": "{n} coin được để dành cho các món quà chưa nhận",
- "giftReclaim": "Lấy lại",
"claimBody": "Nhận nó vào một ví hoàn toàn mới mà chỉ riêng bạn kiểm soát.",
"claimBtn": "Nhận ngay",
"claimFailed": "Món quà này đã được nhận hoặc không còn khả dụng.",
"claimedTitle": "Đã nhận!",
"claimedBody": "Bitcoin của bạn đang trên đường tới. Hãy sao lưu cụm từ khôi phục để giữ an toàn.",
"giftLinkReveal": "Tạo liên kết tặng",
- "copyLink": "Sao chép liên kết"
-}
+ "copyLink": "Sao chép liên kết",
+ "giftRevoke": "Thu hồi",
+ "giftRevokeConfirm": "Thu hồi quà này? Việc này chuyển đồng coin về ví của bạn và khiến liên kết ngừng hoạt động.",
+ "giftRevoked": "Đã thu hồi quà"
+} \ No newline at end of file
diff --git a/src/locales/zh.json b/src/locales/zh.json
index 6de1544..2e990ba 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -158,12 +158,14 @@
"giftAmountInvalid": "请输入有效金额。",
"giftAnother": "再创建一个",
"giftReserved": "{n} 枚币已预留给未领取的礼物",
- "giftReclaim": "收回",
"claimBody": "将它领取到一个仅由你自己掌控的全新钱包中。",
"claimBtn": "领取",
"claimFailed": "此礼物已被领取或不再可用。",
"claimedTitle": "已领取!",
"claimedBody": "你的 Bitcoin 正在到账。请备份你的恢复助记词以妥善保管。",
"giftLinkReveal": "创建赠送链接",
- "copyLink": "复制链接"
+ "copyLink": "复制链接",
+ "giftRevoke": "撤销",
+ "giftRevokeConfirm": "撤销此礼物?这会将这笔币退回你的钱包,并使链接失效。",
+ "giftRevoked": "礼物已撤销"
} \ No newline at end of file
diff --git a/src/wallet.js b/src/wallet.js
index 06af3dc..b5945ff 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -787,6 +787,17 @@ export class Wallet {
this.reservedSet().delete(id);
this._saveReserved();
}
+
+ // Truly revoke an unclaimed gift: spend its coin back into our own wallet,
+ // which double-spends the gift's presigned input so the link can't be claimed
+ // once this confirms. Uses a high fee to win any race with a claimer.
+ async revokeGift(id, feeRate) {
+ const draft = this.buildTx({ recipients: [{ address: this.freshChange().address }], feeRate, coinIds: [id], sendMax: true });
+ const hexTx = this.sign(draft.tx);
+ const txid = await this.broadcast(hexTx);
+ this.unreserve(id);
+ return txid;
+ }
// Active gifts whose coin is still unspent (drops claimed/spent ones).
activeGifts() {
const live = new Set(this.utxos.map((u) => utxoId(u)));