import { TmuxOrchestrator } from '../../../hyper-lab/lib/tmux-orchestrator.js'
export default async function testAddressSync(agentConfigs, options = {}) {
const test = new TmuxOrchestrator('address-sync', agentConfigs)
try {
// Connect to all agents
await test.connect()
// Create tmux session (both human and AI can see)
await test.createSession()
await test.log('📱 Starting address sync test...', 'blue')
const device1 = agentConfigs[0].name
const device2 = agentConfigs[1].name
// Initialize wallets
await test.log('🔐 Initializing wallets...', 'blue')
await test.run(device1, 'init')
await test.run(device2, 'init')
// Bootstrap device1
await test.log('🖥️ Bootstrapping device1...', 'blue')
await test.run(device1, 'device', ['bootstrap', 'Device1'])
// Create invite
await test.log('🔗 Creating device pairing invite...', 'blue')
await test.run(device1, 'device', ['add'])
// Wait for invite to appear, then capture it
await test.sleep(2000)
const device1Output = await test.capturePane(test.paneMap.get(device1), 100)
const invite = extractInvite(device1Output)
if (!invite) {
throw new Error('Could not extract invite from device1 output')
}
await test.log(`📋 Invite extracted: ${invite.substring(0, 20)}...`, 'blue')
// Device2 joins (this will wait for approval)
await test.log('📱 Device2 joining...', 'blue')
await test.run(device2, 'device', ['join', invite, 'Device2'])
// Wait for join success message
await test.log('⏳ Waiting for pairing to complete...', 'yellow')
await test.waitForOutput(device2, '✅ Joined wallet successfully', 30000)
// Generate address on device1
await test.log('🔑 Generating Bitcoin address on device1...', 'blue')
await test.run(device1, 'address', ['new', 'bitcoin'])
// Wait for sync (Autobase replication)
await test.log('⏳ Waiting for Autobase sync (8 seconds)...', 'yellow')
await test.sleep(8000)
// Check device2 has the address
await test.log('🔍 Checking sync on device2...', 'blue')
await test.run(device2, 'address', ['list', 'bitcoin'])
// Wait a moment for list output
await test.sleep(1000)
// Verify by reading device2's pane output
const device2Output = await test.capturePane(test.paneMap.get(device2), 50)
test.assert(
device2Output.includes('Total: 1 address'),
'Device2 should have 1 synced address'
)
test.assert(
device2Output.includes('tb1q'),
'Address should be Bitcoin testnet (tb1q...)'
)
await test.log('🎉 Test passed!', 'green')
// Return session name for --attach option
return test.sessionName
} catch (err) {
await test.log(`💥 Test failed: ${err.message}`, 'red')
throw err
} finally {
await test.cleanup()
}
}
function extractInvite(output) {
const lines = output.split('\n')
for (let i = 0; i < lines.length; i++) {
if (lines[i].includes('━━━━')) {
// Invite is on the next line
const invite = lines[i + 1].trim()
if (invite && invite.length > 20) {
return invite
}
}
}
return null
}