deviant/Parameters/WalletConnect/examples/dapp-connect-example.mjs
walerikus 35076606c7 chore: checkpoint in-flight work across shell, contracts, and docs
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>
2026-07-07 02:02:05 +02:00

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); });