Snapshot of the shared working tree's outstanding changes (multiple concurrent workstreams), excluding generated runtime state files (.football-tote-state.json, .tote-platform-state.json, .usdm-historical-chart.html). Spans: wallet shell (connect/, keystore MultiKeyStore+vault, screens, currency picker, sign-message), verify artifacts, new Potidaea/DRA/tote contracts + regtest suites, cross-chain/T6 + WalletConnect Parameters, a telegram-orderbook subproject, design mockups, and docs. See shells/app/WALLET-COORDINATION.md for the per-file ownership split. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
121 lines
5 KiB
JavaScript
121 lines
5 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* connect.mjs — minimal WalletConnect v2 "dApp" that pairs with a BCH wallet
|
|
* (Cashonize) and proves the handshake + signing works with a CHIPNET address,
|
|
* per the wc2-bch-bcr spec (namespace `bch`, chain `bch:bchtest`).
|
|
*
|
|
* This is the FIRST milestone for the Deviant tote connector: confirm a bettor's
|
|
* own wallet can connect and sign. The tote bet co-sign (bch_signTransaction with
|
|
* an unsigned tote tx) is the next milestone, added once this handshake works on
|
|
* your device.
|
|
*
|
|
* Steps:
|
|
* 1. Get a free WalletConnect/Reown projectId at https://cloud.reown.com
|
|
* 2. In Cashonize, import a chipnet WIF (e.g. wallet D) and switch to chipnet.
|
|
* 3. WC_PROJECT_ID=<id> npm run connect
|
|
* 4. Paste the printed URI (or scan the QR) into Cashonize → WalletConnect.
|
|
* 5. Approve the session, then the getAddresses + signMessage prompts.
|
|
*
|
|
* Network note: the tote runs on chipnet (`bch:bchtest`). If your Cashonize build
|
|
* exposes only mainnet for WC, the handshake + signMessage still prove the wiring
|
|
* (no funds needed); chipnet tx-signing is handled at the next milestone.
|
|
*
|
|
* Co-pairing pattern (recommended for any dApp — added 2026-06-15 per the
|
|
* Checkers chipnet-co-support issue, where a mainnet-only dApp builds couldn't
|
|
* pair with chipnet wallets like the Deviant chipnet beta): request BOTH chains
|
|
* as `optionalNamespaces.bch.chains` and read the chain the wallet actually
|
|
* picked from the returned session's `namespaces.bch.accounts[0]` (account
|
|
* string `bch:<chain>:<cashaddr>`). One dApp build then pairs with mainnet AND
|
|
* chipnet wallets — no separate builds, no Cloud-project switching. Set
|
|
* `WC_CHAIN=bch:bchtest` (or `bch:bitcoincash`) to force a single chain for
|
|
* chain-locked test flows.
|
|
*/
|
|
import { SignClient } from '@walletconnect/sign-client';
|
|
import qrcode from 'qrcode-terminal';
|
|
|
|
const FORCED_CHAIN = process.env.WC_CHAIN; // optional override, e.g. 'bch:bchtest'
|
|
const CHAINS = FORCED_CHAIN ? [FORCED_CHAIN] : ['bch:bitcoincash', 'bch:bchtest'];
|
|
const projectId = process.env.WC_PROJECT_ID;
|
|
if (!projectId) {
|
|
console.error('Set WC_PROJECT_ID — get a free one at https://cloud.reown.com');
|
|
process.exit(1);
|
|
}
|
|
|
|
/** Read the chain the wallet picked at approval time from a session's
|
|
* `namespaces.bch.accounts[0]`. The wc2-bch-bcr account format is
|
|
* `bch:<chain>:<cashaddr>` — segments 0..1 are the chain id. */
|
|
function chainFromSession(session) {
|
|
const acc = session?.namespaces?.bch?.accounts?.[0] ?? '';
|
|
const parts = acc.split(':');
|
|
return parts.length >= 2 ? `${parts[0]}:${parts[1]}` : CHAINS[0];
|
|
}
|
|
|
|
function divider() { console.log('='.repeat(72)); }
|
|
|
|
async function main() {
|
|
const client = await SignClient.init({
|
|
projectId,
|
|
metadata: {
|
|
name: 'Deviant Tote (chipnet test)',
|
|
description: 'Non-custodial pari-mutuel tote — WalletConnect co-sign test',
|
|
url: 'https://deviant.cash',
|
|
icons: ['https://deviant.cash/icon.png'],
|
|
},
|
|
});
|
|
|
|
const { uri, approval } = await client.connect({
|
|
optionalNamespaces: {
|
|
bch: {
|
|
chains: CHAINS, // request all supported chains; wallet picks one at approval
|
|
methods: ['bch_getAddresses', 'bch_signMessage', 'bch_signTransaction'],
|
|
events: [],
|
|
},
|
|
},
|
|
});
|
|
|
|
if (uri) {
|
|
divider();
|
|
console.log(`Pair this in Cashonize → WalletConnect (chains: ${CHAINS.join(', ')}):`);
|
|
divider();
|
|
console.log(uri);
|
|
console.log('');
|
|
qrcode.generate(uri, { small: true });
|
|
console.log('Waiting for the wallet to approve the session…');
|
|
}
|
|
|
|
const session = await approval();
|
|
// Read which chain the wallet actually picked from the session — don't assume
|
|
// CHAINS[0]. A chipnet wallet pairing against this dApp will return a
|
|
// `bch:bchtest:…` account; a mainnet wallet returns `bch:bitcoincash:…`.
|
|
const pickedChain = chainFromSession(session);
|
|
divider();
|
|
console.log(`Paired with: ${session.peer.metadata.name}`);
|
|
console.log(`Chain: ${pickedChain}`);
|
|
const accounts = session.namespaces.bch?.accounts ?? [];
|
|
console.log(`Accounts: ${accounts.join(', ')}`);
|
|
divider();
|
|
|
|
// 1) getAddresses — confirm which address the wallet exposes.
|
|
const addresses = await client.request({
|
|
topic: session.topic,
|
|
chainId: pickedChain,
|
|
request: { method: 'bch_getAddresses', params: {} },
|
|
});
|
|
console.log('bch_getAddresses →', addresses);
|
|
|
|
// 2) signMessage — confirm the wallet can sign with that key.
|
|
const message = `Deviant tote WalletConnect test ${new Date().toISOString()}`;
|
|
const signed = await client.request({
|
|
topic: session.topic,
|
|
chainId: pickedChain,
|
|
request: { method: 'bch_signMessage', params: { message, userPrompt: 'Sign to prove your Deviant tote connection' } },
|
|
});
|
|
console.log('bch_signMessage →', signed);
|
|
|
|
divider();
|
|
console.log('HANDSHAKE OK — the wallet connected and signed. Next milestone: bch_signTransaction co-sign of a tote bet.');
|
|
divider();
|
|
process.exit(0);
|
|
}
|
|
|
|
main().catch((e) => { console.error('FAILED:', e?.message ?? e); process.exit(1); });
|