@profullstack/coinpay 0.5.0 → 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.5.0",
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
@@ -105,11 +105,10 @@ export {
105
105
  getRevocationList,
106
106
  } from './reputation.js';
107
107
  export type {
108
- TaskReceipt,
109
- ReputationSummary,
110
- MultiWindowReputation,
111
- CredentialVerification,
112
- RevocationList,
108
+ ReceiptInput,
109
+ ReputationWindow,
110
+ ReputationResult,
111
+ Credential,
113
112
  } from './reputation.js';
114
113
 
115
114
  import { CoinPayClient } from './client.js';
package/src/index.js CHANGED
@@ -78,6 +78,7 @@ import {
78
78
  } from './wallet.js';
79
79
 
80
80
  // Swap exports
81
+ // Reputation exports
81
82
  import {
82
83
  submitReceipt,
83
84
  getReputation,
@@ -1,69 +1,71 @@
1
1
  import { CoinPayClient } from './client';
2
2
 
3
- export interface TaskReceipt {
3
+ export interface ReceiptInput {
4
4
  receipt_id: string;
5
5
  task_id: string;
6
6
  agent_did: string;
7
7
  buyer_did: string;
8
- platform_did: string;
8
+ platform_did?: string;
9
9
  escrow_tx?: string;
10
- amount: number;
11
- currency: string;
10
+ amount?: number;
11
+ currency?: string;
12
12
  category?: string;
13
13
  sla?: Record<string, unknown>;
14
- outcome: 'completed' | 'failed' | 'disputed' | 'cancelled';
14
+ outcome: 'accepted' | 'rejected' | 'disputed';
15
15
  dispute?: boolean;
16
16
  artifact_hash?: string;
17
17
  signatures: {
18
- agent?: string;
19
- buyer?: string;
20
- platform?: string;
18
+ escrow_sig: string;
19
+ agent_sig?: string;
20
+ buyer_sig?: string;
21
+ arbitration_sig?: string;
21
22
  };
22
23
  finalized_at?: string;
23
24
  }
24
25
 
25
- export interface ReputationSummary {
26
- agent_did: string;
27
- total_tasks: number;
28
- completed: number;
29
- failed: number;
30
- disputed: number;
31
- cancelled: number;
32
- completion_rate: number;
33
- dispute_rate: number;
26
+ export interface ReputationWindow {
27
+ task_count: number;
28
+ accepted_count: number;
29
+ disputed_count: number;
34
30
  total_volume: number;
35
- avg_task_value: number;
36
31
  unique_buyers: number;
32
+ avg_task_value: number;
33
+ accepted_rate: number;
34
+ dispute_rate: number;
37
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
+ };
38
45
  anti_gaming: {
39
- circular_payment: boolean;
40
- burst_detected: boolean;
41
- below_economic_threshold: boolean;
42
- insufficient_unique_buyers: boolean;
43
46
  flagged: boolean;
44
- details: string[];
47
+ flags: string[];
48
+ adjusted_weight: number;
45
49
  };
46
50
  }
47
51
 
48
- export interface MultiWindowReputation {
49
- '30d': ReputationSummary;
50
- '90d': ReputationSummary;
51
- all: ReputationSummary;
52
- }
53
-
54
- export interface CredentialVerification {
55
- valid: boolean;
56
- reason: string;
57
- credential?: Record<string, unknown>;
58
- }
59
-
60
- export interface RevocationList {
61
- revoked: string[];
62
- details: Array<{ credential_id: string; reason: string; revoked_at: string }>;
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;
63
65
  }
64
66
 
65
- export function submitReceipt(client: CoinPayClient, receipt: TaskReceipt): Promise<{ id: string; verified_signatures: string[] }>;
66
- export function getReputation(client: CoinPayClient, agentDid: string): Promise<MultiWindowReputation>;
67
- export function getCredential(client: CoinPayClient, credentialId: string): Promise<Record<string, unknown>>;
68
- export function verifyCredential(client: CoinPayClient, credentialId: string): Promise<CredentialVerification>;
69
- export function getRevocationList(client: CoinPayClient): Promise<RevocationList>;
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>> }>;
package/src/reputation.js CHANGED
@@ -1,51 +1,64 @@
1
1
  /**
2
2
  * Reputation SDK Module
3
3
  *
4
- * Submit receipts, query reputation, verify credentials.
4
+ * Query and submit reputation data for the CoinPayPortal Reputation Protocol (CPR).
5
5
  *
6
6
  * @example
7
7
  * import { CoinPayClient } from '@profullstack/coinpay';
8
- * const client = new CoinPayClient({ apiKey: 'your-key' });
9
- *
10
- * // Submit a task receipt
11
- * const result = await client.submitReceipt({ ... });
12
- *
13
- * // Get agent reputation
14
- * const rep = await client.getReputation('did:web:agent.example.com');
8
+ * import { submitReceipt, getReputation } from '@profullstack/coinpay/reputation';
15
9
  */
16
10
 
17
11
  /**
18
12
  * Submit a task receipt
13
+ * @param {import('./client.js').CoinPayClient} client
14
+ * @param {Object} receipt - Receipt data
15
+ * @returns {Promise<Object>}
19
16
  */
20
17
  export async function submitReceipt(client, receipt) {
21
- return client._request('POST', '/api/reputation/receipt', receipt);
18
+ return client.request('/reputation/receipt', {
19
+ method: 'POST',
20
+ body: JSON.stringify(receipt),
21
+ });
22
22
  }
23
23
 
24
24
  /**
25
- * Get aggregated reputation for an agent DID
25
+ * Get reputation for an agent DID
26
+ * @param {import('./client.js').CoinPayClient} client
27
+ * @param {string} agentDid
28
+ * @returns {Promise<Object>}
26
29
  */
27
30
  export async function getReputation(client, agentDid) {
28
- const encoded = encodeURIComponent(agentDid);
29
- return client._request('GET', `/api/reputation/agent/${encoded}/reputation`);
31
+ return client.request(`/reputation/agent/${encodeURIComponent(agentDid)}/reputation`);
30
32
  }
31
33
 
32
34
  /**
33
- * Get a specific credential by ID
35
+ * Get a specific credential
36
+ * @param {import('./client.js').CoinPayClient} client
37
+ * @param {string} credentialId
38
+ * @returns {Promise<Object>}
34
39
  */
35
40
  export async function getCredential(client, credentialId) {
36
- return client._request('GET', `/api/reputation/credential/${credentialId}`);
41
+ return client.request(`/reputation/credential/${credentialId}`);
37
42
  }
38
43
 
39
44
  /**
40
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}>}
41
49
  */
42
- export async function verifyCredential(client, credentialId) {
43
- return client._request('POST', '/api/reputation/verify', { credential_id: credentialId });
50
+ export async function verifyCredential(client, credential) {
51
+ return client.request('/reputation/verify', {
52
+ method: 'POST',
53
+ body: JSON.stringify(credential),
54
+ });
44
55
  }
45
56
 
46
57
  /**
47
58
  * Get the revocation list
59
+ * @param {import('./client.js').CoinPayClient} client
60
+ * @returns {Promise<Object>}
48
61
  */
49
62
  export async function getRevocationList(client) {
50
- return client._request('GET', '/api/reputation/revocation-list');
63
+ return client.request('/reputation/revocation-list');
51
64
  }