aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-01 21:08:01 -0700
committerAdam Soltys <[email protected]>2026-08-01 21:08:01 -0700
commit161e0ad3b205c1423aaa709377c128980336d3c1 (patch)
treeec165e8211f644f0ec48115f4310ed64189ba3a0 /src
parented1d996f9dbd6cedc18ec293daba0cfcd745ae2b (diff)
downloadcoinosv3-161e0ad3b205c1423aaa709377c128980336d3c1.tar.gz
coinosv3-161e0ad3b205c1423aaa709377c128980336d3c1.zip
Coinos v3: rebrand from Hal, payment addresses move to @coinos.io
The wallet is the next version of coinos, deployed at v3.coinos.io (same build as halwallet.app) ahead of an eventual migration of coinos.io itself. App name, manifest, notifications, and the NWC alias all say Coinos; the Hal Finney tribute stays. The registrar is multi-domain (per-domain Cloudflare zones; existing halwallet.app names keep working) and new claims default to @coinos.io. Names belonging to existing coinos users are reserved for them — the registrar checks the live coinos API before granting a claim — until the migration gives those users a way to claim their own. Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/features/names.js16
-rw-r--r--src/features/nwc.js2
-rw-r--r--src/i18n.js10
-rw-r--r--src/nwc-respond.js4
-rw-r--r--src/sw-nwc.js2
5 files changed, 17 insertions, 17 deletions
diff --git a/src/features/names.js b/src/features/names.js
index d932af7..f7efb89 100644
--- a/src/features/names.js
+++ b/src/features/names.js
@@ -16,8 +16,8 @@ import { isArkAddress } from './ark.js';
import { getNetwork } from '../api.js';
import { t } from '../i18n.js';
-const REGISTRAR = 'https://names.halwallet.app';
-const DOMAIN = 'halwallet.app';
+const REGISTRAR = 'https://names.coinos.io';
+const DOMAIN = 'coinos.io';
const AUTH_KIND = 21353;
export function namesFeature(ctx) {
@@ -39,7 +39,7 @@ export function namesFeature(ctx) {
if (!uri) throw new Error(t('namesNeedArk'));
const auth = wallet.nostrSign({
kind: AUTH_KIND, created_at: Math.floor(Date.now() / 1000), tags: [],
- content: JSON.stringify({ action: 'register', name, uri }),
+ content: JSON.stringify({ action: 'register', name, uri, domain: DOMAIN }),
});
if (!auth) throw new Error('wallet cannot sign');
const r = await fetch(`${REGISTRAR}/register`, {
@@ -48,7 +48,7 @@ export function namesFeature(ctx) {
});
const j = await r.json();
if (!r.ok || j.error) throw new Error(j.error || `registrar refused (${r.status})`);
- save({ name, uri, updated: Date.now() });
+ save({ name, domain: DOMAIN, uri, updated: Date.now() });
return j;
}
@@ -57,7 +57,7 @@ export function namesFeature(ctx) {
if (!st.name) return;
const auth = wallet.nostrSign({
kind: AUTH_KIND, created_at: Math.floor(Date.now() / 1000), tags: [],
- content: JSON.stringify({ action: 'delete', name: st.name }),
+ content: JSON.stringify({ action: 'delete', name: st.name, domain: st.domain || DOMAIN }),
});
await fetch(`${REGISTRAR}/register`, {
method: 'DELETE', headers: { 'content-type': 'application/json' },
@@ -126,12 +126,12 @@ export function namesFeature(ctx) {
if (!available()) return null;
const st = load();
if (st.name) {
- const addr = `${st.name}@${DOMAIN}`;
+ const addr = `${st.name}@${st.domain || DOMAIN}`;
return h('div', { class: 'card col' },
h('h3', {}, t('namesTitle')),
h('div', { class: 'addr-box break', style: 'font-size:14px' }, addr),
h('div', { class: 'row gap6' },
- copyBtn(`${st.name}@${DOMAIN}`, t('namesCopy')),
+ copyBtn(`${st.name}@${st.domain || DOMAIN}`, t('namesCopy')),
h('button', { class: 'btn-ghost btn-sm', onClick: async () => {
await release(); toast(t('namesReleased')); render();
} }, t('namesRelease'))),
@@ -147,7 +147,7 @@ export function namesFeature(ctx) {
h('summary', {}, t('namesOwnDomain')),
h('p', { style: 'margin:4px 0' }, t('namesOwnDomainHow')),
h('div', { class: 'addr-box break', style: 'font-size:11px' },
- `${st.name}.user._bitcoin-payment.yourdomain.com. CNAME ${st.name}.user._bitcoin-payment.${DOMAIN}.`)));
+ `${st.name}.user._bitcoin-payment.yourdomain.com. CNAME ${st.name}.user._bitcoin-payment.${st.domain || DOMAIN}.`)));
}
return h('div', { class: 'card col' },
h('h3', {}, t('namesTitle')),
diff --git a/src/features/nwc.js b/src/features/nwc.js
index 8ef9cb9..ec85463 100644
--- a/src/features/nwc.js
+++ b/src/features/nwc.js
@@ -326,7 +326,7 @@ export function nwcFeature(ctx) {
if (method === 'get_info') {
return {
result: {
- alias: 'Hal', color: '#f7931a', network: getNetwork() === 'mainnet' ? 'mainnet' : getNetwork(),
+ alias: 'Coinos', color: '#f7931a', network: getNetwork() === 'mainnet' ? 'mainnet' : getNetwork(),
block_height: 0, block_hash: '', methods: METHODS,
},
};
diff --git a/src/i18n.js b/src/i18n.js
index 62e7b07..14d5c8a 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -33,7 +33,7 @@ export const isRTL = (l) => RTL.has(l || lang);
const STR = {
en: {
- appTitle: 'Hal',
+ appTitle: 'Coinos',
home: 'Home',
logout: 'Logout',
accounts: 'Accounts',
@@ -139,7 +139,7 @@ const STR = {
hiwSp1: 'Your wallet also has a silent-payment address (sp1…) that never changes and is safe to share publicly — every payment to it lands at a fresh on-chain address nobody can link to you. Finding those payments uses an indexer service, configurable (or self-hostable) in Settings.',
hiwGiftsTitle: 'Gifts',
hiwGifts1: 'You can gift bitcoin with a link: whoever opens it claims the coins into their own wallet — no app, no signup. On-chain gifts lock the coins until claimed and can be cancelled or reclaimed; Ark gifts claim instantly and free, even into a brand-new empty wallet. A gift can also be locked to a specific nostr account so only they can claim it.',
- hiwTribute: 'The name Hal Wallet is a tribute to Hal Finney (1956–2014).',
+ hiwTribute: 'Built on the shoulders of Hal Finney (1956–2014).',
balance: 'Balance',
pending: 'Pending',
tabReceive: 'Receive',
@@ -340,7 +340,7 @@ const STR = {
autolock1h: 'After 1 hour',
autolock1d: 'After 1 day',
dataSource: 'Data source',
- dataSourceDesc: 'Where Hal reads the chain and how it learns about incoming payments.',
+ dataSourceDesc: 'Where Coinos reads the chain and how it learns about incoming payments.',
modeCoinos: 'coinos (instant)',
modeCoinosDesc: "The default. Chain data and instant payments come from coinos's own Bitcoin node, with public servers as automatic backup.",
modeExplorer: 'Block explorer',
@@ -429,7 +429,7 @@ const STR = {
arkLnRefunded: 'Payment failed — funds returned to your Ark balance.',
arkLnPaidTitle: 'Paid!',
namesTitle: 'Payment address',
- namesDesc: 'Claim your payment address — like [email protected]. People can pay you just by typing it, no codes to copy or QR to scan.',
+ namesDesc: 'Claim your payment address — like [email protected]. People can pay you just by typing it, no codes to copy or QR to scan.',
namesPlaceholder: 'username',
namesClaim: 'Claim',
namesClaimed: 'You are now {name}',
@@ -446,7 +446,7 @@ const STR = {
namesOwnDomainHow: 'Have your own domain? Add this line to its DNS records (DNSSEC must be enabled) and your address works there too:',
nwcTitle: 'Nostr Wallet Connect',
nwcDesc: 'Let another app pay from this wallet over nostr — it never sees your keys, only spends within the limits you set, and you can cut it off at any time. Payments go out over Ark.',
- nwcTabWarning: 'Only works while Hal is open in a tab — it is not an always-on service.',
+ nwcTabWarning: 'Works while Coinos is open — turn on background answering below to keep working when it isn’t.',
nwcAdd: 'Add a connection',
nwcBackground: 'Answer while closed',
nwcOn: 'On',
diff --git a/src/nwc-respond.js b/src/nwc-respond.js
index 83f23a0..6289b01 100644
--- a/src/nwc-respond.js
+++ b/src/nwc-respond.js
@@ -112,7 +112,7 @@ async function respondOffer(ev, rec, walletKey, { notifier, fetchFn, saveFn, log
await saveFn(walletKey, rec);
await publish({ bolt11: a.invoice });
log(`minted ${sat} sat offer invoice while closed`);
- return { notify: { title: 'Incoming payment', body: 'Someone is paying you — open Hal to receive it.' } };
+ return { notify: { title: 'Incoming payment', body: 'Someone is paying you — open Coinos to receive it.' } };
} catch (e) {
log('offer mint failed: ' + e.message);
await publish({ error: 'Temporary Failure', code: 2 }).catch(() => {});
@@ -181,7 +181,7 @@ export async function respondFromBg(data, {
await publish({
result_type: 'get_info',
result: {
- alias: 'Hal', color: '#f7931a',
+ alias: 'Coinos', color: '#f7931a',
network: rec.ark.network === 'mainnet' ? 'mainnet' : rec.ark.network,
block_height: 0, block_hash: '',
methods: ['get_info', 'get_balance', 'pay_invoice', 'list_transactions'],
diff --git a/src/sw-nwc.js b/src/sw-nwc.js
index 968be91..dcc0c9c 100644
--- a/src/sw-nwc.js
+++ b/src/sw-nwc.js
@@ -42,7 +42,7 @@ self.addEventListener('push', (e) => {
}
if (handled) return;
await self.registration.showNotification('Payment request', {
- body: 'An app is asking your wallet to pay. Open Hal to approve.',
+ body: 'An app is asking your wallet to pay. Open Coinos to approve.',
icon: 'icon-192.png', badge: 'icon-192.png',
tag: 'nwc-' + (data.servicePubkey || 'req'), renotify: false,
data: { url: './' },