Snapshot commit rolling up ~255 files of coherent-but-multi-domain in-flight
work that had accumulated on this branch. Split by area:
Contracts + covenants
- New: AsmFxSwap, DeviantOpenMintNBA, DeviantTieredMintOracleFT,
TermCouponVault, UniformReserve, UniformReserveAggregate.
- Verify-artifact refresh (src/verify/artifacts/*.json + canonical.ts).
Wallet + shell (shells/app + src/wallet)
- App.tsx, MainScreen, ArtemisionScreen, AssetDetail, AgoraScreen,
SettingsScreen, Unlock, TokenImportModal, UniformFiat/DepositPanel,
KatalogosPanel (renamed from PinaxPanel), shell.css.
- src/wallet: wallet.ts, runtime.ts, index.ts. Core registry/chipnetFile.
- Deleted stale hook: useAllDevBalances.ts.
Cross-chain + correspondent (services/correspondent + scripts)
- Correspondent server/bch/config updates for PYUSD Solana, EURC Sepolia,
aggregate reserve flows.
- New scripts: PYUSD roundtrip, EURC onboarding, GMX game loop /
genesis / mint sanity, tiered mint fee, aggregate reserve, product2
shares dividends, product3 t-bond, uniform fiat cell tests.
Telegram order-book (P2PExchange bot)
- db.ts, index.ts, en/ru locales — updates upstream from the extracted
standalone repo at D:/Dev/P2PExchange.
Docs — Parameters (specs), wiki, snapshots, design mockups
- Parameters: FIATm/MBA_Shares/Potidaea/Anthemus refinements +
ASM_CrossChain/DebitCredit + UniformFiat + Anthemus DEX MVP prompt +
Artemision + Athenae Politeia + Philosophy + SSHkeyServer runbook +
new dApp/{Artemision,Katalogos,Pinax,Pari_escrow,SURFACES}.
- wiki: cross-chain, games-tote, glossary, governance/voting-systems,
infra, wallet, wallet-ui-design, decisions (ADR log).
- snapshots: catch-up entries and INDEX regeneration.
- design: mockups refreshed (agora, asset-detail, assets-tab, potidaea)
+ Potidaea assets + tote deploy notes.
Housekeeping
- .gitignore: exclude the new root test/session state files
(.sol-vault-keys.json, .football-tote-state.json,
.tote-platform-state.json, .redeem-roundtrip-state.json,
.eurc-onboard-state.json — some contain oracle privkeys / vault
secretKeyBase58; NEVER commit) + the .usdm-historical-chart.html
chart output + MS Office `~$*` lock files + scripts/bundle-surfaces
`build/` output. Also add scripts/bundle-surfaces.mjs.
- CLAUDE.md, WALLET-COORDINATION.md, snapshots/INDEX.md, design/README.md
refreshed.
- package.json / package-lock.json bumps.
Verified: sensitive files at repo root confirmed ignored (git check-ignore
each). No `.env`, no raw WIF/xprv/mnemonic/secretKey/oraclePriv strings in
the staged diff. MS Word autosave file (`Parameters/Philosophy/~$*.docx`)
excluded and gitignored.
The WizardConnect responder work landed separately in the previous commit
(6987591); this is everything else that had accumulated alongside it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
122 lines
9.6 KiB
JavaScript
122 lines
9.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* chipnet-mint-pyusd-solana.mjs — the BCH-mint half of PYUSD·Solana onboarding, against the ALREADY
|
|
* real-locked PYUSD on Solana devnet (see onboard-pyusd-solana-real.mjs; lock sig recorded below).
|
|
*
|
|
* Decoupled from the Solana leg (which is proven three times on devnet) so the chipnet mint runs on a
|
|
* fresh operator wallet (D) — the earlier all-in-one runs churned wallet C's UTXO set ("Missing
|
|
* inputs"). Mints 3 USD into the PYUSD.Solana cell of a Uniform USD aggregate basket, reconciling
|
|
* against the real 3 PYUSD in the operator vault. Run: node --import tsx scripts/chipnet-mint-pyusd-solana.mjs --yes
|
|
*/
|
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { TestNetWallet } from 'mainnet-js';
|
|
import { Contract as CashContract, ElectrumNetworkProvider, TransactionBuilder, SignatureTemplate } from 'cashscript';
|
|
import { secp256k1, sha256 as laSha256 } from '@bitauth/libauth';
|
|
import { codeOf } from '../services/uniform-registry/ledger.mjs';
|
|
import { buildLedger } from '../services/uniform-registry/registry.mjs';
|
|
import { safeUtxos, pickBch as pickSafe, eligibleVout0, sendWithRetry } from './lib/chipnet-safe.mjs';
|
|
|
|
const ROOT = join(import.meta.dirname, '..');
|
|
const ART = JSON.parse(readFileSync(join(ROOT, 'contracts/dist/UniformReserveAggregate.json'), 'utf8'));
|
|
// operator/funder wallet — configurable so we can validate the stale-UTXO fix on the CHURNED wallet C
|
|
const WALLET = (process.argv.find((a) => a.startsWith('--wallet=')) || '--wallet=c').split('=')[1];
|
|
const KEYS = { c: join(ROOT, '.chipnet-keys-c.json'), d: join(ROOT, '.chipnet-keys-d.json'), b: join(ROOT, '.chipnet-keys-b.json'), e: join(ROOT, '.chipnet-keys-e.json'), f: join(ROOT, '.chipnet-keys-f.json'), g: join(ROOT, '.chipnet-keys-g.json') };
|
|
const SOL_LOCK_SIG = '4fcMGdDhXbQ6rw9dvjey5NbPNMMMmvM1omFTwp4MjUDtyLUYvhThruVj62nsDwaKgazfVreMomuqELiXjjBf6PmN';
|
|
const LOCKED = 3_000_000n; // 3 PYUSD really locked in the Solana operator vault
|
|
const SUPPLY = 1_000_000_000n, FX_SCALE = 1_000_000n, FX_BAND = 0n;
|
|
const DUST = 1000n, MF = 12_000n;
|
|
|
|
const hexToBin = (h) => { const o = new Uint8Array(h.length / 2); for (let i = 0; i < o.length; i++) o[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16); return o; };
|
|
const binToHex = (b) => [...b].map((x) => x.toString(16).padStart(2, '0')).join('');
|
|
const txidLE = (h) => { const d = hexToBin(h); const o = new Uint8Array(d.length); for (let i = 0; i < d.length; i++) o[i] = d[d.length - 1 - i]; return o; };
|
|
const p2pkh = (pkh) => { const o = new Uint8Array(25); o[0] = 0x76; o[1] = 0xa9; o[2] = 0x14; o.set(pkh, 3); o[23] = 0x88; o[24] = 0xac; return o; };
|
|
const u32le = (n) => { const b = new Uint8Array(4); new DataView(b.buffer).setUint32(0, Number(n), true); return b; };
|
|
const u64le = (n) => { const b = new Uint8Array(8); new DataView(b.buffer).setBigUint64(0, BigInt(n), true); return b; };
|
|
const oSign = (priv, msg) => { const s = secp256k1.signMessageHashSchnorr(priv, laSha256.hash(msg)); if (typeof s === 'string') throw new Error(s); return s; };
|
|
const EMPTY = new Uint8Array(0);
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
const div = (c = '=') => console.log(c.repeat(84));
|
|
const step = (t) => { console.log(''); div(); console.log(t); div(); };
|
|
const txidOf = (s) => (typeof s === 'string' ? s : s?.txid ?? s?.txId);
|
|
const fmt = (n) => (Number(n) / 1e6).toFixed(2);
|
|
const commit = (agg, root) => binToHex(u64le(agg)) + binToHex(root);
|
|
const depositMsg = (lb, minted, root, ctrl) => { const m = new Uint8Array(101); m.set(lb, 0); m.set(u64le(minted), 25); m.set(root, 33); m.set(txidLE(ctrl.txid), 65); m.set(u32le(ctrl.vout), 97); return m; };
|
|
const pickBch = (u, need) => { const p = []; let t = 0n; for (const x of u) { p.push(x); t += BigInt(x.satoshis); if (t >= need) break; } return { p, t }; };
|
|
|
|
async function main() {
|
|
if (!process.argv.includes('--yes')) { console.log('Re-run with --yes to broadcast on chipnet.'); return; }
|
|
for (const k of ['e', 'f', 'g']) if (!existsSync(KEYS[k])) { const w = await TestNetWallet.newRandom(); writeFileSync(KEYS[k], JSON.stringify({ wif: w.privateKeyWif }, null, 2)); }
|
|
const D = await TestNetWallet.fromWIF(JSON.parse(readFileSync(KEYS[WALLET], 'utf8')).wif); // operator/funder
|
|
const ALICE = await TestNetWallet.fromWIF(JSON.parse(readFileSync(KEYS.b, 'utf8')).wif); // user/recipient
|
|
const [E, F, G] = await Promise.all(['e', 'f', 'g'].map(async (k) => TestNetWallet.fromWIF(JSON.parse(readFileSync(KEYS[k], 'utf8')).wif)));
|
|
const provider = new ElectrumNetworkProvider('chipnet');
|
|
const sigD = new SignatureTemplate(D.privateKey);
|
|
const quorum = (msg) => [oSign(E.privateKey, msg), oSign(F.privateKey, msg), EMPTY];
|
|
const instance = (cat) => new CashContract(ART, [txidLE(cat), E.publicKey, F.publicKey, G.publicKey, SUPPLY, FX_SCALE, FX_BAND], { provider });
|
|
const ftBal = async (w, cat) => (await provider.getUtxos(w.cashaddr)).filter((x) => x.token?.category === cat && !x.token?.nft).reduce((s, x) => s + BigInt(x.token.amount), 0n);
|
|
const ctrlOf = async (inst, cat) => (await provider.getUtxos(inst.tokenAddress)).find((x) => x.token?.category === cat && x.token?.nft);
|
|
// SAFE selection: reconcile the cashscript + mainnet-js views (the cashscript chipnet server lists
|
|
// stale/spent outpoints) → spend only confirmed outpoints both agree exist. See lib/chipnet-safe.mjs.
|
|
const pick = async (need) => pickSafe(await safeUtxos(provider, D), need);
|
|
|
|
const ledger = buildLedger('USD', { supply: SUPPLY });
|
|
console.log(`operator/funder ${D.cashaddr} (wallet ${WALLET})\nuser ${ALICE.cashaddr}`);
|
|
console.log(`backing: ${fmt(LOCKED)} PYUSD really locked on Solana devnet · lock sig ${SOL_LOCK_SIG.slice(0, 16)}…`);
|
|
|
|
step('1. Genesis a Uniform USD aggregate basket');
|
|
let cat, inst;
|
|
await sendWithRetry(async () => {
|
|
const u0 = await eligibleVout0(provider, D); cat = u0.txid; inst = instance(cat);
|
|
const uSat = BigInt(u0.satoshis); const need = DUST + MF + 1000n;
|
|
const safe = (await safeUtxos(provider, D)).filter((x) => !x.token && !(x.txid === u0.txid && x.vout === u0.vout));
|
|
const { p, t } = pickSafe(safe, need > uSat ? need - uSat : 0n); const total = uSat + t;
|
|
const tb = new TransactionBuilder({ provider });
|
|
tb.addInput(u0, sigD.unlockP2PKH()); for (const x of p) tb.addInput(x, sigD.unlockP2PKH());
|
|
tb.addOutput({ to: inst.tokenAddress, amount: DUST, token: { amount: SUPPLY, category: cat, nft: { capability: 'mutable', commitment: commit(0n, new Uint8Array(32)) } } });
|
|
tb.addOutput({ to: D.cashaddr, amount: total - DUST - MF });
|
|
console.log(` USD basket · category ${cat.slice(0, 16)}… · ${txidOf(await tb.send())}`);
|
|
}, { onRetry: (n, m) => console.log(` ↻ genesis retry ${n} — dropped a stale input (${m.slice(0, 32)}…)`) });
|
|
await sleep(16000);
|
|
|
|
step('2. MINT — deposit the locked PYUSD into the PYUSD.Solana cell (attestation backed by the real lock)');
|
|
{
|
|
let ctrl; for (let i = 0; i < 8 && !ctrl; i++) { ctrl = await ctrlOf(inst, cat); if (!ctrl) await sleep(5000); }
|
|
if (!ctrl) throw new Error('genesis controller not visible');
|
|
// deterministic once: the off-chain ledger mutation + the outpoint-bound attestation
|
|
const { aggregate, root } = ledger.deposit(codeOf('PYUSD', 'Solana'), LOCKED);
|
|
const msg = depositMsg(p2pkh(ALICE.publicKeyHash), LOCKED, root, ctrl);
|
|
const q = quorum(msg);
|
|
// retry only RE-FETCHES the funding inputs (that's where a stale outpoint would sneak in)
|
|
await sendWithRetry(async () => {
|
|
const { p, t } = await pick(DUST + MF + 1000n);
|
|
const tb = new TransactionBuilder({ provider });
|
|
tb.addInput(ctrl, inst.unlock.deposit(...q, msg)); for (const x of p) tb.addInput(x, sigD.unlockP2PKH());
|
|
tb.addOutput({ to: inst.tokenAddress, amount: BigInt(ctrl.satoshis), token: { amount: BigInt(ctrl.token.amount) - LOCKED, category: cat, nft: { capability: 'mutable', commitment: commit(aggregate, root) } } });
|
|
tb.addOutput({ to: ALICE.tokenaddr, amount: DUST, token: { amount: LOCKED, category: cat } });
|
|
tb.addOutput({ to: D.cashaddr, amount: t - DUST - MF });
|
|
console.log(` minted ${fmt(LOCKED)} USD into PYUSD.Solana cell · aggregate ${fmt(aggregate)} · ${txidOf(await tb.send())}`);
|
|
}, { onRetry: (n, m) => console.log(` ↻ mint retry ${n} — dropped a stale funding input (${m.slice(0, 32)}…)`) });
|
|
await sleep(9000);
|
|
}
|
|
|
|
step('VERDICT — Solana locked == BCH minted');
|
|
const ctrl = await ctrlOf(inst, cat);
|
|
const aggOnchain = BigInt('0x' + [...hexToBin(ctrl.token.nft.commitment.slice(0, 16))].reverse().map((x) => x.toString(16).padStart(2, '0')).join(''));
|
|
const aliceUsd = await ftBal(ALICE, cat);
|
|
const cellVal = ledger.cells.get(codeOf('PYUSD', 'Solana')).value;
|
|
const checks = [
|
|
['3 PYUSD really locked on Solana devnet (proven, sig above)', true],
|
|
['equal USD minted on BCH (locked == minted)', aliceUsd === LOCKED],
|
|
['credited the PYUSD.Solana cell', cellVal === LOCKED],
|
|
['on-chain aggregate == off-chain ledger aggregate', aggOnchain === ledger.aggregate],
|
|
];
|
|
for (const [l, ok] of checks) console.log(` ${ok ? '✅' : '❌'} ${l}`);
|
|
console.log(`\n BCH: Alice holds ${fmt(aliceUsd)} unified USD · PYUSD.Solana cell ${fmt(cellVal)} · category ${cat.slice(0, 16)}…`);
|
|
const ok = checks.every(([, c]) => c);
|
|
console.log(ok
|
|
? '\nPYUSD·SOLANA ONBOARDED FOR REAL — a genuine Solana devnet PYUSD lock backs the minted USD on BCH.\nPYUSD is now a TWO-CHAIN issuer, BOTH legs real. Solana correspondent rail: BUILT + VALIDATED.'
|
|
: '\nSOME CHECKS FAILED.');
|
|
process.exit(ok ? 0 : 1);
|
|
}
|
|
main().catch((e) => { console.error('FAILED:', e?.message ?? e); process.exit(1); });
|