@@ -218,6 +218,13 @@ ${colors.cyan}Commands:${colors.reset}
218218 events <id> Get escrow audit log
219219 auth <id> Authenticate with escrow token
220220
221+ ${ colors . bright } reputation${ colors . reset }
222+ submit Submit a task receipt
223+ query <agent-did> Query agent reputation
224+ credential <id> Get credential details
225+ verify <id> Verify a credential
226+ revocations List revoked credentials
227+
221228 ${ colors . bright } webhook${ colors . reset }
222229 logs <business-id> Get webhook logs
223230 test <business-id> Send test webhook
@@ -1577,6 +1584,156 @@ async function handleEscrow(subcommand, args, flags) {
15771584 }
15781585}
15791586
1587+ /**
1588+ * Reputation commands
1589+ */
1590+ async function handleReputation ( subcommand , args , flags ) {
1591+ switch ( subcommand ) {
1592+ case 'submit' : {
1593+ const receiptArg = flags . receipt ;
1594+ if ( ! receiptArg ) {
1595+ print . error ( 'Required: --receipt <json-file-or-inline-json>' ) ;
1596+ print . info ( 'Example: coinpay reputation submit --receipt receipt.json' ) ;
1597+ print . info ( 'Example: coinpay reputation submit --receipt \'{"receipt_id":"..."}\'' ) ;
1598+ return ;
1599+ }
1600+
1601+ let receipt ;
1602+ try {
1603+ if ( existsSync ( receiptArg ) ) {
1604+ receipt = JSON . parse ( readFileSync ( receiptArg , 'utf-8' ) ) ;
1605+ } else {
1606+ receipt = JSON . parse ( receiptArg ) ;
1607+ }
1608+ } catch {
1609+ print . error ( 'Could not parse receipt JSON. Provide a valid JSON file path or inline JSON.' ) ;
1610+ return ;
1611+ }
1612+
1613+ const client = createClient ( ) ;
1614+ const { submitReceipt } = await import ( '../src/reputation.js' ) ;
1615+ const result = await submitReceipt ( client , receipt ) ;
1616+
1617+ if ( result . success ) {
1618+ print . success ( 'Receipt submitted' ) ;
1619+ } else {
1620+ print . error ( result . error || 'Submission failed' ) ;
1621+ }
1622+
1623+ if ( flags . json ) print . json ( result ) ;
1624+ else if ( result . receipt ) print . json ( result . receipt ) ;
1625+ break ;
1626+ }
1627+
1628+ case 'query' : {
1629+ const agentDid = args [ 0 ] ;
1630+ if ( ! agentDid ) {
1631+ print . error ( 'Agent DID required' ) ;
1632+ print . info ( 'Usage: coinpay reputation query <agent-did> [--window 30d|90d|all]' ) ;
1633+ return ;
1634+ }
1635+
1636+ const client = createClient ( ) ;
1637+ const { getReputation } = await import ( '../src/reputation.js' ) ;
1638+ const result = await getReputation ( client , agentDid ) ;
1639+
1640+ if ( flags . json ) {
1641+ print . json ( result ) ;
1642+ } else if ( result . success && result . reputation ) {
1643+ const rep = result . reputation ;
1644+ const windowKey = flags . window === '90d' ? 'last_90_days'
1645+ : flags . window === 'all' ? 'all_time'
1646+ : 'last_30_days' ;
1647+ const label = flags . window || '30d' ;
1648+ const w = rep . windows [ windowKey ] ;
1649+
1650+ print . info ( `Reputation for ${ rep . agent_did } (${ label } ):` ) ;
1651+ console . log ( ` Tasks: ${ w . task_count } ` ) ;
1652+ console . log ( ` Accepted: ${ w . accepted_count } (${ ( w . accepted_rate * 100 ) . toFixed ( 1 ) } %)` ) ;
1653+ console . log ( ` Disputed: ${ w . disputed_count } (${ ( w . dispute_rate * 100 ) . toFixed ( 1 ) } %)` ) ;
1654+ console . log ( ` Volume: ${ w . total_volume . toFixed ( 2 ) } ` ) ;
1655+ console . log ( ` Avg Value: ${ w . avg_task_value . toFixed ( 2 ) } ` ) ;
1656+ console . log ( ` Unique Buyers: ${ w . unique_buyers } ` ) ;
1657+
1658+ if ( rep . anti_gaming . flagged ) {
1659+ print . warn ( `Anti-gaming flags: ${ rep . anti_gaming . flags . join ( ', ' ) } ` ) ;
1660+ }
1661+ } else {
1662+ print . json ( result ) ;
1663+ }
1664+ break ;
1665+ }
1666+
1667+ case 'credential' : {
1668+ const credentialId = args [ 0 ] ;
1669+ if ( ! credentialId ) {
1670+ print . error ( 'Credential ID required' ) ;
1671+ print . info ( 'Usage: coinpay reputation credential <credential-id>' ) ;
1672+ return ;
1673+ }
1674+
1675+ const client = createClient ( ) ;
1676+ const { getCredential } = await import ( '../src/reputation.js' ) ;
1677+ const result = await getCredential ( client , credentialId ) ;
1678+
1679+ if ( result . success && result . credential ) {
1680+ print . success ( `Credential ${ result . credential . id } ` ) ;
1681+ console . log ( ` Agent: ${ result . credential . agent_did } ` ) ;
1682+ console . log ( ` Type: ${ result . credential . credential_type } ` ) ;
1683+ console . log ( ` Issued: ${ result . credential . issued_at } ` ) ;
1684+ console . log ( ` Revoked: ${ result . credential . revoked ? 'YES' : 'no' } ` ) ;
1685+ }
1686+
1687+ if ( flags . json ) print . json ( result ) ;
1688+ break ;
1689+ }
1690+
1691+ case 'verify' : {
1692+ const credentialId = args [ 0 ] ;
1693+ if ( ! credentialId ) {
1694+ print . error ( 'Credential ID required' ) ;
1695+ print . info ( 'Usage: coinpay reputation verify <credential-id>' ) ;
1696+ return ;
1697+ }
1698+
1699+ const client = createClient ( ) ;
1700+ const { verifyCredential } = await import ( '../src/reputation.js' ) ;
1701+ const result = await verifyCredential ( client , { credential_id : credentialId } ) ;
1702+
1703+ if ( result . valid ) {
1704+ print . success ( 'Credential is valid' ) ;
1705+ } else {
1706+ print . error ( `Credential invalid: ${ result . reason } ` ) ;
1707+ }
1708+
1709+ if ( flags . json ) print . json ( result ) ;
1710+ break ;
1711+ }
1712+
1713+ case 'revocations' : {
1714+ const client = createClient ( ) ;
1715+ const { getRevocationList } = await import ( '../src/reputation.js' ) ;
1716+ const result = await getRevocationList ( client ) ;
1717+
1718+ if ( flags . json ) {
1719+ print . json ( result ) ;
1720+ } else {
1721+ const revocations = result . revocations || [ ] ;
1722+ print . info ( `Revoked credentials: ${ revocations . length } ` ) ;
1723+ for ( const r of revocations ) {
1724+ console . log ( ` ${ r . credential_id } — ${ r . reason || 'no reason' } (${ r . revoked_at } )` ) ;
1725+ }
1726+ }
1727+ break ;
1728+ }
1729+
1730+ default :
1731+ print . error ( `Unknown reputation command: ${ subcommand } ` ) ;
1732+ print . info ( 'Available: submit, query, credential, verify, revocations' ) ;
1733+ process . exit ( 1 ) ;
1734+ }
1735+ }
1736+
15801737/**
15811738 * Main entry point
15821739 */
@@ -1626,6 +1783,10 @@ async function main() {
16261783 case 'webhook' :
16271784 await handleWebhook ( subcommand , args , flags ) ;
16281785 break ;
1786+
1787+ case 'reputation' :
1788+ await handleReputation ( subcommand , args , flags ) ;
1789+ break ;
16291790
16301791 default :
16311792 print . error ( `Unknown command: ${ command } ` ) ;
0 commit comments