2026-07-29 13:54:34 +02:00
|
|
|
// A single shared libauth for the whole page.
|
|
|
|
|
//
|
|
|
|
|
// WHY THIS FILE EXISTS
|
|
|
|
|
// libauth initialises its WASM crypto (secp256k1, sha256, ripemd160, …) with a
|
|
|
|
|
// TOP-LEVEL AWAIT. If two bundles each carry their own copy, each has its own
|
|
|
|
|
// unsettled init, and esbuild's inlined dynamic imports can hand out a bundle's
|
|
|
|
|
// exports before that init completes. Symptom, observed on cold load:
|
|
|
|
|
//
|
|
|
|
|
// TypeError: Cannot read properties of undefined
|
|
|
|
|
// (reading 'derivePublicKeyCompressed')
|
|
|
|
|
// at deriveNostrPublicKey (wizardconnect.js)
|
|
|
|
|
// at generateKeyExchangeCredentials
|
|
|
|
|
// at initiateDappRelay
|
|
|
|
|
//
|
|
|
|
|
// — failing 65 ms in, then "working" on every retry once the WASM had warmed.
|
|
|
|
|
// A bug that disappears when you look at it twice is exactly the kind that
|
|
|
|
|
// ships.
|
|
|
|
|
//
|
|
|
|
|
// So libauth becomes a real, separate ES module that every other bundle imports
|
|
|
|
|
// by bare specifier, resolved through the import map in register.html. The
|
|
|
|
|
// browser's module loader guarantees a dependency's top-level await settles
|
|
|
|
|
// before any importer evaluates — the ordering we need — and the page downloads
|
|
|
|
|
// libauth once instead of three times.
|
|
|
|
|
//
|
|
|
|
|
// WHY THE EXPORTS ARE LISTED BY HAND
|
|
|
|
|
// `export *` would defeat tree-shaking and ship all ~1 MB of libauth. This list
|
|
|
|
|
// is the union of what our own modules use and what @wizardconnect/core and
|
|
|
|
|
// /dapp import (they resolve to this module too, via the import map). Missing a
|
|
|
|
|
// name would be a runtime failure in a path we cannot unit-test, so
|
|
|
|
|
// build-web.mjs verifies this list against the imports every other bundle
|
|
|
|
|
// actually emits, and fails the build if anything is absent. Add freely; the
|
|
|
|
|
// check will tell you if you remove something still in use.
|
|
|
|
|
|
|
|
|
|
export {
|
|
|
|
|
// ---- used by @wizardconnect/core and @wizardconnect/dapp ----
|
|
|
|
|
bech32PaddedToBin,
|
|
|
|
|
binToBech32Padded,
|
|
|
|
|
decodeHdPublicKey,
|
|
|
|
|
deriveHdPublicNodeChild,
|
|
|
|
|
generatePrivateKey,
|
|
|
|
|
hash256,
|
|
|
|
|
secp256k1,
|
|
|
|
|
|
|
|
|
|
// ---- encoding ----
|
|
|
|
|
binToHex,
|
|
|
|
|
hexToBin,
|
|
|
|
|
utf8ToBin,
|
|
|
|
|
binToUtf8,
|
|
|
|
|
binToBase64,
|
|
|
|
|
base64ToBin,
|
|
|
|
|
// The WalletConnect / WizardConnect wire format: "<Uint8Array: 0x..>" and
|
|
|
|
|
// "<bigint: ..n>". Wallets validate these strictly.
|
|
|
|
|
stringify,
|
|
|
|
|
|
|
|
|
|
// ---- addresses ----
|
|
|
|
|
cashAddressToLockingBytecode,
|
|
|
|
|
lockingBytecodeToCashAddress,
|
|
|
|
|
encodeCashAddress,
|
|
|
|
|
decodeCashAddress,
|
|
|
|
|
|
|
|
|
|
// ---- hashing ----
|
|
|
|
|
sha256,
|
|
|
|
|
hash160,
|
|
|
|
|
ripemd160,
|
feat(market): names can be priced in US dollars — a covenant holds the certificate, a gateway-signed oracle sets the BCH amount
A BCH-priced offer is a signed transaction with a fixed amount, so a
seller who wants "$500" had to relist whenever the rate moved. The new
USD mode moves the certificate into a small CashScript covenant
(contracts/usd-listing.cash). Anyone may buy it by paying the seller
target_cents / price, where the price comes from a message signed by the
gateway's oracle key — the median of five exchanges the site already
uses. The payout is clamped to a floor/ceiling band the seller sets, and
the seller can reclaim the certificate at any time.
What the chain can and cannot enforce, stated plainly in the contract and
the UI: script can require a transaction to be mined no earlier than a
time, never no later, so a quote cannot expire on-chain. The band is the
guarantee, and quotes are bound to the listing's outpoint so cancelling
and relisting voids every quote ever issued. An offline libauth VM test
covers list, buy, underpayment, foreign-listing quotes, forged quotes,
band clamping, cancel and a non-seller cancel; on chipnet aloevera.test
was listed at $0.30, bought by a second wallet for 119,090 sat at
$251.91, listed again by the new owner and cancelled.
Gateway: GET /api/price/oracle[?txid=] serves the oracle public key and
per-listing signed quotes; the key lives in oracle.key beside the
gateway, never in the repo. POST /api/market accepts kind "usd" after
reproducing the redeem script from the stated terms and finding the
certificate in that covenant; such listings are pruned once the covenant
output is spent; DELETE accepts the listing's seller while the index
shows the covenant as holder.
Dashboard: the Sell tab has "Price is fixed in: US dollars / BCH", a
band control with the resulting BCH range, and cancel through the
covenant. Market: USD listings show the dollar price, today's BCH
equivalent and the band; buying fetches a quote and completes the
covenant spend. Studio no longer sends a needless UPD when the registry
view is stale, and missing files on a name now get a real 404 page.
2026-09-20 19:20:46 +02:00
|
|
|
// ---- covenants (market-usd.js) ----
|
|
|
|
|
encodeDataPush,
|
|
|
|
|
bigIntToVmNumber,
|
|
|
|
|
encodeLockingBytecodeP2sh32,
|
|
|
|
|
encodeLockingBytecodeP2pkh,
|
|
|
|
|
OpcodesBCH,
|
|
|
|
|
numberToBinUint32LE,
|
|
|
|
|
binToNumberUint32LE,
|
|
|
|
|
flattenBinArray,
|
2026-07-29 13:54:34 +02:00
|
|
|
|
|
|
|
|
// ---- transactions ----
|
|
|
|
|
encodeTransaction,
|
|
|
|
|
decodeTransaction,
|
|
|
|
|
generateSigningSerializationBCH,
|
|
|
|
|
|
|
|
|
|
// ---- keys / HD wallets (the built-in wallet) ----
|
|
|
|
|
generateBip39Mnemonic,
|
|
|
|
|
deriveSeedFromBip39Mnemonic,
|
|
|
|
|
deriveHdPrivateNodeFromSeed,
|
|
|
|
|
deriveHdPath,
|
|
|
|
|
deriveHdPublicNode,
|
|
|
|
|
} from "@bitauth/libauth";
|