@profullstack/coinpay 0.4.16 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/coinpay.js CHANGED
@@ -218,6 +218,13 @@ ${colors.cyan}Commands:${colors.reset}
218
218
  events <id> Get escrow audit log
219
219
  auth <id> Authenticate with escrow token
220
220
 
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
+
221
228
  ${colors.bright}webhook${colors.reset}
222
229
  logs <business-id> Get webhook logs
223
230
  test <business-id> Send test webhook
@@ -1577,6 +1584,156 @@ async function handleEscrow(subcommand, args, flags) {
1577
1584
  }
1578
1585
  }
1579
1586
 
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
+
1580
1737
  /**
1581
1738
  * Main entry point
1582
1739
  */
@@ -1626,6 +1783,10 @@ async function main() {
1626
1783
  case 'webhook':
1627
1784
  await handleWebhook(subcommand, args, flags);
1628
1785
  break;
1786
+
1787
+ case 'reputation':
1788
+ await handleReputation(subcommand, args, flags);
1789
+ break;
1629
1790
 
1630
1791
  default:
1631
1792
  print.error(`Unknown command: ${command}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/coinpay",
3
- "version": "0.4.16",
3
+ "version": "0.5.1",
4
4
  "description": "CoinPay SDK & CLI — Accept cryptocurrency payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet and swap support",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.d.ts CHANGED
@@ -96,5 +96,20 @@ export type {
96
96
  SwapHistoryResult,
97
97
  } from './swap.js';
98
98
 
99
+ // Reputation exports
100
+ export {
101
+ submitReceipt,
102
+ getReputation,
103
+ getCredential,
104
+ verifyCredential,
105
+ getRevocationList,
106
+ } from './reputation.js';
107
+ export type {
108
+ ReceiptInput,
109
+ ReputationWindow,
110
+ ReputationResult,
111
+ Credential,
112
+ } from './reputation.js';
113
+
99
114
  import { CoinPayClient } from './client.js';
100
115
  export default CoinPayClient;
package/src/index.js CHANGED
@@ -78,6 +78,15 @@ import {
78
78
  } from './wallet.js';
79
79
 
80
80
  // Swap exports
81
+ // Reputation exports
82
+ import {
83
+ submitReceipt,
84
+ getReputation,
85
+ getCredential,
86
+ verifyCredential,
87
+ getRevocationList,
88
+ } from './reputation.js';
89
+
81
90
  import {
82
91
  SwapClient,
83
92
  SwapCoins,
@@ -134,6 +143,13 @@ export {
134
143
  PaymentStatus,
135
144
  FiatCurrency,
136
145
 
146
+ // Reputation
147
+ submitReceipt,
148
+ getReputation,
149
+ getCredential,
150
+ verifyCredential,
151
+ getRevocationList,
152
+
137
153
  // Webhook utilities
138
154
  verifyWebhookSignature,
139
155
  generateWebhookSignature,
@@ -0,0 +1,71 @@
1
+ import { CoinPayClient } from './client';
2
+
3
+ export interface ReceiptInput {
4
+ receipt_id: string;
5
+ task_id: string;
6
+ agent_did: string;
7
+ buyer_did: string;
8
+ platform_did?: string;
9
+ escrow_tx?: string;
10
+ amount?: number;
11
+ currency?: string;
12
+ category?: string;
13
+ sla?: Record<string, unknown>;
14
+ outcome: 'accepted' | 'rejected' | 'disputed';
15
+ dispute?: boolean;
16
+ artifact_hash?: string;
17
+ signatures: {
18
+ escrow_sig: string;
19
+ agent_sig?: string;
20
+ buyer_sig?: string;
21
+ arbitration_sig?: string;
22
+ };
23
+ finalized_at?: string;
24
+ }
25
+
26
+ export interface ReputationWindow {
27
+ task_count: number;
28
+ accepted_count: number;
29
+ disputed_count: number;
30
+ total_volume: number;
31
+ unique_buyers: number;
32
+ avg_task_value: number;
33
+ accepted_rate: number;
34
+ dispute_rate: number;
35
+ categories: Record<string, { count: number; volume: number }>;
36
+ }
37
+
38
+ export interface ReputationResult {
39
+ agent_did: string;
40
+ windows: {
41
+ last_30_days: ReputationWindow;
42
+ last_90_days: ReputationWindow;
43
+ all_time: ReputationWindow;
44
+ };
45
+ anti_gaming: {
46
+ flagged: boolean;
47
+ flags: string[];
48
+ adjusted_weight: number;
49
+ };
50
+ }
51
+
52
+ export interface Credential {
53
+ id: string;
54
+ agent_did: string;
55
+ credential_type: string;
56
+ category?: string;
57
+ data: Record<string, unknown>;
58
+ window_start: string;
59
+ window_end: string;
60
+ issued_at: string;
61
+ issuer_did: string;
62
+ signature: string;
63
+ revoked: boolean;
64
+ revoked_at?: string;
65
+ }
66
+
67
+ export function submitReceipt(client: CoinPayClient, receipt: ReceiptInput): Promise<{ success: boolean; receipt?: Record<string, unknown>; error?: string }>;
68
+ export function getReputation(client: CoinPayClient, agentDid: string): Promise<{ success: boolean; reputation: ReputationResult }>;
69
+ export function getCredential(client: CoinPayClient, credentialId: string): Promise<{ success: boolean; credential: Credential }>;
70
+ export function verifyCredential(client: CoinPayClient, credential: { credential_id: string }): Promise<{ valid: boolean; reason?: string }>;
71
+ export function getRevocationList(client: CoinPayClient): Promise<{ success: boolean; revoked_credentials: string[]; revocations: Array<Record<string, unknown>> }>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Reputation SDK Module
3
+ *
4
+ * Query and submit reputation data for the CoinPayPortal Reputation Protocol (CPR).
5
+ *
6
+ * @example
7
+ * import { CoinPayClient } from '@profullstack/coinpay';
8
+ * import { submitReceipt, getReputation } from '@profullstack/coinpay/reputation';
9
+ */
10
+
11
+ /**
12
+ * Submit a task receipt
13
+ * @param {import('./client.js').CoinPayClient} client
14
+ * @param {Object} receipt - Receipt data
15
+ * @returns {Promise<Object>}
16
+ */
17
+ export async function submitReceipt(client, receipt) {
18
+ return client.request('/reputation/receipt', {
19
+ method: 'POST',
20
+ body: JSON.stringify(receipt),
21
+ });
22
+ }
23
+
24
+ /**
25
+ * Get reputation for an agent DID
26
+ * @param {import('./client.js').CoinPayClient} client
27
+ * @param {string} agentDid
28
+ * @returns {Promise<Object>}
29
+ */
30
+ export async function getReputation(client, agentDid) {
31
+ return client.request(`/reputation/agent/${encodeURIComponent(agentDid)}/reputation`);
32
+ }
33
+
34
+ /**
35
+ * Get a specific credential
36
+ * @param {import('./client.js').CoinPayClient} client
37
+ * @param {string} credentialId
38
+ * @returns {Promise<Object>}
39
+ */
40
+ export async function getCredential(client, credentialId) {
41
+ return client.request(`/reputation/credential/${credentialId}`);
42
+ }
43
+
44
+ /**
45
+ * Verify a credential
46
+ * @param {import('./client.js').CoinPayClient} client
47
+ * @param {Object} credential - { credential_id: string }
48
+ * @returns {Promise<{valid: boolean, reason?: string}>}
49
+ */
50
+ export async function verifyCredential(client, credential) {
51
+ return client.request('/reputation/verify', {
52
+ method: 'POST',
53
+ body: JSON.stringify(credential),
54
+ });
55
+ }
56
+
57
+ /**
58
+ * Get the revocation list
59
+ * @param {import('./client.js').CoinPayClient} client
60
+ * @returns {Promise<Object>}
61
+ */
62
+ export async function getRevocationList(client) {
63
+ return client.request('/reputation/revocation-list');
64
+ }