@paylobster/cli 4.3.0 → 4.5.0

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.
Files changed (54) hide show
  1. package/README.md +82 -40
  2. package/dist/src/commands/dashboard.d.ts +3 -0
  3. package/dist/src/commands/dashboard.d.ts.map +1 -0
  4. package/dist/src/commands/dashboard.js +67 -0
  5. package/dist/src/commands/dashboard.js.map +1 -0
  6. package/dist/src/commands/export.d.ts +3 -0
  7. package/dist/src/commands/export.d.ts.map +1 -0
  8. package/dist/src/commands/export.js +97 -0
  9. package/dist/src/commands/export.js.map +1 -0
  10. package/dist/src/commands/health.d.ts +3 -0
  11. package/dist/src/commands/health.d.ts.map +1 -0
  12. package/dist/src/commands/health.js +165 -0
  13. package/dist/src/commands/health.js.map +1 -0
  14. package/dist/src/commands/invest.d.ts +3 -0
  15. package/dist/src/commands/invest.d.ts.map +1 -0
  16. package/dist/src/commands/invest.js +721 -0
  17. package/dist/src/commands/invest.js.map +1 -0
  18. package/dist/src/commands/quickstart.d.ts +3 -0
  19. package/dist/src/commands/quickstart.d.ts.map +1 -0
  20. package/dist/src/commands/quickstart.js +138 -0
  21. package/dist/src/commands/quickstart.js.map +1 -0
  22. package/dist/src/commands/search.d.ts +3 -0
  23. package/dist/src/commands/search.d.ts.map +1 -0
  24. package/dist/src/commands/search.js +126 -0
  25. package/dist/src/commands/search.js.map +1 -0
  26. package/dist/src/commands/treasury.d.ts.map +1 -1
  27. package/dist/src/commands/treasury.js +317 -0
  28. package/dist/src/commands/treasury.js.map +1 -1
  29. package/dist/src/commands/trust-graph.d.ts +3 -0
  30. package/dist/src/commands/trust-graph.d.ts.map +1 -0
  31. package/dist/src/commands/trust-graph.js +282 -0
  32. package/dist/src/commands/trust-graph.js.map +1 -0
  33. package/dist/src/commands/whoami.d.ts +3 -0
  34. package/dist/src/commands/whoami.d.ts.map +1 -0
  35. package/dist/src/commands/whoami.js +160 -0
  36. package/dist/src/commands/whoami.js.map +1 -0
  37. package/dist/src/index.js +18 -2
  38. package/dist/src/index.js.map +1 -1
  39. package/dist/src/lib/contracts.d.ts +177 -23
  40. package/dist/src/lib/contracts.d.ts.map +1 -1
  41. package/dist/src/lib/contracts.js +151 -0
  42. package/dist/src/lib/contracts.js.map +1 -1
  43. package/package.json +4 -2
  44. package/src/commands/dashboard.ts +69 -0
  45. package/src/commands/export.ts +132 -0
  46. package/src/commands/health.ts +212 -0
  47. package/src/commands/invest.ts +810 -0
  48. package/src/commands/quickstart.ts +150 -0
  49. package/src/commands/search.ts +151 -0
  50. package/src/commands/treasury.ts +385 -0
  51. package/src/commands/trust-graph.ts +267 -0
  52. package/src/commands/whoami.ts +172 -0
  53. package/src/index.ts +18 -2
  54. package/src/lib/contracts.ts +159 -0
@@ -0,0 +1,267 @@
1
+ import { Command } from 'commander';
2
+ import { getTrustGraph } from '../lib/contracts';
3
+ import { error, success, outputJSON, header, info } from '../lib/display';
4
+ import type { OutputOptions } from '../lib/types';
5
+ import type { Address } from 'viem';
6
+
7
+ export function createTrustGraphCommand(): Command {
8
+ const cmd = new Command('trust')
9
+ .description('Manage and query trust network')
10
+ .addHelpText('after', `
11
+ Examples:
12
+ $ plob trust endorse 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 85
13
+ $ plob trust revoke 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
14
+ $ plob trust check 0xAlice 0xBob
15
+ $ plob trust score 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
16
+ $ plob trust endorsements 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
17
+ `);
18
+
19
+ // Endorse agent
20
+ cmd
21
+ .command('endorse')
22
+ .description('Endorse another agent with a trust level')
23
+ .argument('<address>', 'Agent address to endorse')
24
+ .argument('<score>', 'Trust score (1-100)')
25
+ .option('--json', 'Output as JSON')
26
+ .action(async (addressArg: string, scoreArg: string, options: OutputOptions) => {
27
+ try {
28
+ const address = addressArg as Address;
29
+ const score = parseInt(scoreArg);
30
+
31
+ if (score < 1 || score > 100) {
32
+ error('Trust score must be between 1 and 100');
33
+ process.exit(1);
34
+ }
35
+
36
+ const trustGraph = getTrustGraph();
37
+
38
+ info(`Endorsing ${address} with trust level ${score}...`);
39
+ const hash = await trustGraph.endorseAgent(address, score);
40
+
41
+ if (outputJSON({ transactionHash: hash, endorsed: address, trustLevel: score }, options)) {
42
+ return;
43
+ }
44
+
45
+ success(`Endorsed ${address} with trust level ${score}/100`);
46
+ console.log(`Transaction: ${hash}`);
47
+ } catch (err) {
48
+ error(`Failed to endorse agent: ${err}`);
49
+ process.exit(1);
50
+ }
51
+ });
52
+
53
+ // Revoke endorsement
54
+ cmd
55
+ .command('revoke')
56
+ .description('Revoke an endorsement')
57
+ .argument('<address>', 'Agent address to revoke endorsement from')
58
+ .option('--json', 'Output as JSON')
59
+ .action(async (addressArg: string, options: OutputOptions) => {
60
+ try {
61
+ const address = addressArg as Address;
62
+ const trustGraph = getTrustGraph();
63
+
64
+ info(`Revoking endorsement of ${address}...`);
65
+ const hash = await trustGraph.revokeEndorsement(address);
66
+
67
+ if (outputJSON({ transactionHash: hash, revoked: address }, options)) {
68
+ return;
69
+ }
70
+
71
+ success(`Revoked endorsement of ${address}`);
72
+ console.log(`Transaction: ${hash}`);
73
+ } catch (err) {
74
+ error(`Failed to revoke endorsement: ${err}`);
75
+ process.exit(1);
76
+ }
77
+ });
78
+
79
+ // Check trust between two agents
80
+ cmd
81
+ .command('check')
82
+ .description('Check trust level between two agents')
83
+ .argument('<from>', 'Source agent address')
84
+ .argument('<to>', 'Target agent address')
85
+ .option('--inferred', 'Calculate inferred trust through network')
86
+ .option('--depth <number>', 'Max hops for inferred trust (default: 4)', '4')
87
+ .option('--json', 'Output as JSON')
88
+ .action(async (fromArg: string, toArg: string, options: any) => {
89
+ try {
90
+ const from = fromArg as Address;
91
+ const to = toArg as Address;
92
+ const trustGraph = getTrustGraph();
93
+
94
+ if (options.inferred) {
95
+ // Get inferred trust through network
96
+ const maxDepth = parseInt(options.depth);
97
+ const result = await trustGraph.getInferredTrust(from, to, maxDepth);
98
+
99
+ if (outputJSON({ from, to, trustScore: result.trustScore, pathLength: result.pathLength, type: 'inferred' }, options)) {
100
+ return;
101
+ }
102
+
103
+ header('Inferred Trust');
104
+ console.log();
105
+ console.log('From: ', from);
106
+ console.log('To: ', to);
107
+ console.log('Trust Score: ', result.trustScore);
108
+ console.log('Path Length: ', result.pathLength, 'hops');
109
+ console.log();
110
+ } else {
111
+ // Get direct trust
112
+ const trustLevel = await trustGraph.getDirectTrust(from, to);
113
+
114
+ if (outputJSON({ from, to, trustLevel, type: 'direct' }, options)) {
115
+ return;
116
+ }
117
+
118
+ header('Direct Trust');
119
+ console.log();
120
+ console.log('From: ', from);
121
+ console.log('To: ', to);
122
+ console.log('Trust Level: ', trustLevel === 0 ? 'No direct endorsement' : `${trustLevel}/100`);
123
+ console.log();
124
+ }
125
+ } catch (err) {
126
+ error(`Failed to check trust: ${err}`);
127
+ process.exit(1);
128
+ }
129
+ });
130
+
131
+ // Get aggregate trust score
132
+ cmd
133
+ .command('score')
134
+ .description('Get aggregate trust score for an agent')
135
+ .argument('<address>', 'Agent address')
136
+ .option('--json', 'Output as JSON')
137
+ .action(async (addressArg: string, options: OutputOptions) => {
138
+ try {
139
+ const address = addressArg as Address;
140
+ const trustGraph = getTrustGraph();
141
+
142
+ const [aggregateScore, endorsers] = await Promise.all([
143
+ trustGraph.getAggregateTrust(address),
144
+ trustGraph.getEndorsers(address),
145
+ ]);
146
+
147
+ if (outputJSON({ address, aggregateScore, endorserCount: endorsers.length }, options)) {
148
+ return;
149
+ }
150
+
151
+ header('Trust Score');
152
+ console.log();
153
+ console.log('Agent: ', address);
154
+ console.log('Aggregate Score: ', aggregateScore);
155
+ console.log('Endorser Count: ', endorsers.length);
156
+ console.log();
157
+
158
+ if (aggregateScore >= 80) {
159
+ console.log('✅ Highly trusted in the network');
160
+ } else if (aggregateScore >= 60) {
161
+ console.log('✅ Well trusted in the network');
162
+ } else if (aggregateScore >= 40) {
163
+ console.log('⚠️ Moderately trusted');
164
+ } else if (aggregateScore > 0) {
165
+ console.log('⚠️ Limited trust in the network');
166
+ } else {
167
+ console.log('❌ No endorsements yet');
168
+ }
169
+ console.log();
170
+ } catch (err) {
171
+ error(`Failed to get trust score: ${err}`);
172
+ process.exit(1);
173
+ }
174
+ });
175
+
176
+ // Get endorsements (agents this address has endorsed)
177
+ cmd
178
+ .command('endorsements')
179
+ .description('List all agents endorsed by an address')
180
+ .argument('[address]', 'Agent address (default: your wallet)')
181
+ .option('--json', 'Output as JSON')
182
+ .action(async (addressArg: string | undefined, options: OutputOptions) => {
183
+ try {
184
+ let address: Address;
185
+
186
+ if (addressArg) {
187
+ address = addressArg as Address;
188
+ } else {
189
+ const { getWalletAddress } = await import('../lib/wallet');
190
+ address = getWalletAddress() as Address;
191
+ }
192
+
193
+ const trustGraph = getTrustGraph();
194
+ const endorsed = await trustGraph.getEndorsements(address);
195
+
196
+ if (outputJSON({ address, endorsed, count: endorsed.length }, options)) {
197
+ return;
198
+ }
199
+
200
+ header('Endorsements');
201
+ console.log();
202
+ console.log('Endorser: ', address);
203
+ console.log('Endorsed: ', endorsed.length, 'agents');
204
+ console.log();
205
+
206
+ if (endorsed.length > 0) {
207
+ endorsed.forEach((agent, i) => {
208
+ console.log(` ${i + 1}. ${agent}`);
209
+ });
210
+ console.log();
211
+ } else {
212
+ console.log('No endorsements yet.');
213
+ console.log();
214
+ }
215
+ } catch (err) {
216
+ error(`Failed to get endorsements: ${err}`);
217
+ process.exit(1);
218
+ }
219
+ });
220
+
221
+ // Get endorsers (agents who endorse this address)
222
+ cmd
223
+ .command('endorsers')
224
+ .description('List all agents who endorse an address')
225
+ .argument('[address]', 'Agent address (default: your wallet)')
226
+ .option('--json', 'Output as JSON')
227
+ .action(async (addressArg: string | undefined, options: OutputOptions) => {
228
+ try {
229
+ let address: Address;
230
+
231
+ if (addressArg) {
232
+ address = addressArg as Address;
233
+ } else {
234
+ const { getWalletAddress } = await import('../lib/wallet');
235
+ address = getWalletAddress() as Address;
236
+ }
237
+
238
+ const trustGraph = getTrustGraph();
239
+ const endorsers = await trustGraph.getEndorsers(address);
240
+
241
+ if (outputJSON({ address, endorsers, count: endorsers.length }, options)) {
242
+ return;
243
+ }
244
+
245
+ header('Endorsers');
246
+ console.log();
247
+ console.log('Endorsed: ', address);
248
+ console.log('Endorsers: ', endorsers.length, 'agents');
249
+ console.log();
250
+
251
+ if (endorsers.length > 0) {
252
+ endorsers.forEach((agent, i) => {
253
+ console.log(` ${i + 1}. ${agent}`);
254
+ });
255
+ console.log();
256
+ } else {
257
+ console.log('No endorsers yet.');
258
+ console.log();
259
+ }
260
+ } catch (err) {
261
+ error(`Failed to get endorsers: ${err}`);
262
+ process.exit(1);
263
+ }
264
+ });
265
+
266
+ return cmd;
267
+ }
@@ -0,0 +1,172 @@
1
+ import { Command } from 'commander';
2
+ import { getAgentInfo, getReputation, getCreditStatus, getBalance, getUserEscrowCount, formatUSDC, formatETH } from '../lib/contracts';
3
+ import { getWalletAddress } from '../lib/wallet';
4
+ import { loadConfig } from '../lib/config';
5
+ import { error, outputJSON } from '../lib/display';
6
+ import type { OutputOptions } from '../lib/types';
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+
10
+ export function createWhoamiCommand(): Command {
11
+ const cmd = new Command('whoami')
12
+ .description('🦞 Show your complete PayLobster profile')
13
+ .option('--json', 'Output as JSON')
14
+ .action(async (options: OutputOptions) => {
15
+ const spinner = ora('Loading your profile...').start();
16
+
17
+ try {
18
+ const address = getWalletAddress() as `0x${string}`;
19
+ const config = loadConfig();
20
+
21
+ // Fetch all data in parallel
22
+ const [agentInfo, reputation, creditStatus, balance, escrowCount] = await Promise.all([
23
+ getAgentInfo(address),
24
+ getReputation(address),
25
+ getCreditStatus(address),
26
+ getBalance(address),
27
+ getUserEscrowCount(address),
28
+ ]);
29
+
30
+ spinner.stop();
31
+
32
+ // Calculate metrics
33
+ const reputationScore = Number(reputation.score);
34
+ const usdcBalance = formatUSDC(balance.usdc);
35
+ const ethBalance = formatETH(balance.eth);
36
+ const creditLimit = formatUSDC(creditStatus.limit);
37
+ const creditAvailable = formatUSDC(creditStatus.available);
38
+ const creditInUse = formatUSDC(creditStatus.inUse);
39
+ const creditUtilization = creditStatus.limit > 0n
40
+ ? ((Number(creditStatus.inUse) / Number(creditStatus.limit)) * 100).toFixed(1)
41
+ : '0';
42
+
43
+ // Calculate total net worth (USDC + credit available)
44
+ const totalNetWorth = parseFloat(usdcBalance) + parseFloat(creditAvailable);
45
+
46
+ // JSON output
47
+ if (outputJSON({
48
+ identity: {
49
+ name: agentInfo.name,
50
+ address,
51
+ registered: agentInfo.registered,
52
+ tokenId: agentInfo.tokenId.toString(),
53
+ registrationDate: agentInfo.registered ? 'N/A' : null, // TODO: get from events
54
+ },
55
+ reputation: {
56
+ score: reputationScore,
57
+ totalInteractions: 0, // TODO: get from events
58
+ successRate: 0, // TODO: calculate
59
+ },
60
+ credit: {
61
+ score: reputationScore, // Using reputation as proxy
62
+ limit: creditLimit,
63
+ available: creditAvailable,
64
+ inUse: creditInUse,
65
+ utilization: parseFloat(creditUtilization),
66
+ },
67
+ treasury: {
68
+ name: null, // TODO: get from TreasuryFactory
69
+ aum: 0,
70
+ budgetAllocation: {},
71
+ memberCount: 0,
72
+ },
73
+ activity: {
74
+ activeEscrows: escrowCount,
75
+ activeStreams: 0, // TODO: get from Stream contract
76
+ },
77
+ balance: {
78
+ usdc: usdcBalance,
79
+ eth: ethBalance,
80
+ totalNetWorth: totalNetWorth.toFixed(2),
81
+ },
82
+ network: config.network,
83
+ }, options)) {
84
+ return;
85
+ }
86
+
87
+ // Pretty output
88
+ console.log('\n' + chalk.cyan.bold('═══════════════════════════════════════════════════════════'));
89
+ console.log(chalk.cyan.bold(' 🦞 PayLobster Profile'));
90
+ console.log(chalk.cyan.bold('═══════════════════════════════════════════════════════════\n'));
91
+
92
+ // Identity Section
93
+ console.log(chalk.bold.underline('👤 IDENTITY'));
94
+ console.log();
95
+ console.log(chalk.gray(' Name: '), agentInfo.registered ? chalk.bold.white(agentInfo.name) : chalk.yellow('Not Registered'));
96
+ console.log(chalk.gray(' Address: '), chalk.dim(address));
97
+ console.log(chalk.gray(' Token ID: '), agentInfo.registered ? chalk.white(`#${agentInfo.tokenId.toString()}`) : chalk.gray('N/A'));
98
+ console.log(chalk.gray(' Network: '), chalk.white(config.network === 'mainnet' ? '🟢 Base Mainnet' : '🟡 Base Sepolia'));
99
+ console.log();
100
+
101
+ // Reputation Section
102
+ console.log(chalk.bold.underline('⭐ REPUTATION'));
103
+ console.log();
104
+
105
+ let reputationColor = chalk.red;
106
+ let reputationEmoji = '❌';
107
+ if (reputationScore >= 80) {
108
+ reputationColor = chalk.green;
109
+ reputationEmoji = '🌟';
110
+ } else if (reputationScore >= 50) {
111
+ reputationColor = chalk.yellow;
112
+ reputationEmoji = '⭐';
113
+ }
114
+
115
+ console.log(chalk.gray(' Score: '), reputationColor.bold(reputationScore.toString()), reputationEmoji);
116
+ console.log(chalk.gray(' Total Txs: '), chalk.white('N/A')); // TODO
117
+ console.log(chalk.gray(' Success Rate: '), chalk.white('N/A')); // TODO
118
+ console.log();
119
+
120
+ // Credit Section
121
+ console.log(chalk.bold.underline('💳 CREDIT'));
122
+ console.log();
123
+ console.log(chalk.gray(' Score: '), reputationColor.bold(reputationScore.toString())); // Using reputation
124
+ console.log(chalk.gray(' Credit Limit: '), chalk.white(creditLimit), chalk.dim('USDC'));
125
+ console.log(chalk.gray(' Available: '), chalk.green(creditAvailable), chalk.dim('USDC'));
126
+ console.log(chalk.gray(' In Use: '), chalk.yellow(creditInUse), chalk.dim('USDC'));
127
+ console.log(chalk.gray(' Utilization: '), chalk.white(creditUtilization + '%'));
128
+ console.log();
129
+
130
+ // Treasury Section
131
+ console.log(chalk.bold.underline('🏦 TREASURY'));
132
+ console.log();
133
+ console.log(chalk.gray(' Name: '), chalk.yellow('Not implemented yet'));
134
+ console.log(chalk.gray(' AUM: '), chalk.white('N/A'));
135
+ console.log(chalk.gray(' Budget: '), chalk.white('N/A'));
136
+ console.log(chalk.gray(' Members: '), chalk.white('N/A'));
137
+ console.log();
138
+
139
+ // Activity Section
140
+ console.log(chalk.bold.underline('📊 ACTIVITY'));
141
+ console.log();
142
+ console.log(chalk.gray(' Active Escrows: '), chalk.white(escrowCount.toString()));
143
+ console.log(chalk.gray(' Active Streams: '), chalk.white('N/A')); // TODO
144
+ console.log(chalk.gray(' Investments: '), chalk.white('N/A')); // TODO
145
+ console.log();
146
+
147
+ // Balance Section
148
+ console.log(chalk.bold.underline('💰 BALANCES'));
149
+ console.log();
150
+ console.log(chalk.gray(' USDC: '), chalk.green.bold(usdcBalance), chalk.dim('USDC'));
151
+ console.log(chalk.gray(' ETH: '), chalk.blue(ethBalance), chalk.dim('ETH'));
152
+ console.log(chalk.gray(' Net Worth: '), chalk.bold.white(totalNetWorth.toFixed(2)), chalk.dim('USDC equiv'));
153
+ console.log();
154
+
155
+ console.log(chalk.cyan.bold('═══════════════════════════════════════════════════════════\n'));
156
+
157
+ // Quick actions
158
+ console.log(chalk.dim('Quick actions:'));
159
+ console.log(chalk.dim(' • Open dashboard: ') + chalk.green('plob dashboard'));
160
+ console.log(chalk.dim(' • Check health: ') + chalk.green('plob health'));
161
+ console.log(chalk.dim(' • View transactions:') + chalk.green('plob status'));
162
+ console.log();
163
+
164
+ } catch (err: any) {
165
+ spinner.stop();
166
+ error(`Failed to fetch profile: ${err.message}`);
167
+ process.exit(1);
168
+ }
169
+ });
170
+
171
+ return cmd;
172
+ }
package/src/index.ts CHANGED
@@ -21,6 +21,14 @@ import { createSwapCommand } from './commands/swap';
21
21
  import { createBridgeCommand } from './commands/bridge';
22
22
  import { createPortfolioCommand } from './commands/portfolio';
23
23
  import { createTreasuryCommand } from './commands/treasury';
24
+ import { registerInvestCommand } from './commands/invest';
25
+ import { createQuickstartCommand } from './commands/quickstart';
26
+ import { createWhoamiCommand } from './commands/whoami';
27
+ import { createDashboardCommand } from './commands/dashboard';
28
+ import { createHealthCommand } from './commands/health';
29
+ import { createSearchCommand } from './commands/search';
30
+ import { createExportCommand } from './commands/export';
31
+ import { createTrustGraphCommand } from './commands/trust-graph';
24
32
  import chalk from 'chalk';
25
33
 
26
34
  // Load environment variables from .env file if present
@@ -30,9 +38,9 @@ dotenv.config();
30
38
  const program = new Command();
31
39
 
32
40
  program
33
- .name('plob')
41
+ .name('paylobster')
34
42
  .description('🦞 PayLobster CLI - Payment infrastructure for AI agents')
35
- .version('4.3.0');
43
+ .version('4.5.0');
36
44
 
37
45
  // ASCII art banner
38
46
  const banner = `
@@ -68,6 +76,14 @@ program.addCommand(createSwapCommand());
68
76
  program.addCommand(createBridgeCommand());
69
77
  program.addCommand(createPortfolioCommand());
70
78
  program.addCommand(createTreasuryCommand());
79
+ program.addCommand(createQuickstartCommand());
80
+ program.addCommand(createWhoamiCommand());
81
+ program.addCommand(createDashboardCommand());
82
+ program.addCommand(createHealthCommand());
83
+ program.addCommand(createSearchCommand());
84
+ program.addCommand(createExportCommand());
85
+ program.addCommand(createTrustGraphCommand());
86
+ registerInvestCommand(program);
71
87
 
72
88
  // Handle errors
73
89
  program.exitOverride((err) => {
@@ -11,6 +11,7 @@ const CONTRACTS_MAINNET = {
11
11
  CREDIT: '0xD9241Ce8a721Ef5fcCAc5A11983addC526eC80E1' as Address,
12
12
  ESCROW: '0x49EdEe04c78B7FeD5248A20706c7a6c540748806' as Address,
13
13
  USDC: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as Address,
14
+ TRUST_GRAPH: '0x0000000000000000000000000000000000000000' as Address, // TODO: Deploy TrustGraph
14
15
  };
15
16
 
16
17
  const CONTRACTS_SEPOLIA = {
@@ -21,6 +22,7 @@ const CONTRACTS_SEPOLIA = {
21
22
  CREDIT: '0xBA64e2b2F2a80D03A4B13b3396942C1e78205C7d' as Address,
22
23
  ESCROW: '0x78D1f50a1965dE34f6b5a3D3546C94FE1809Cd82' as Address,
23
24
  USDC: '0x036CbD53842c5426634e7929541eC2318f3dCF7e' as Address,
25
+ TRUST_GRAPH: '0x0000000000000000000000000000000000000000' as Address, // TODO: Deploy TrustGraph
24
26
  };
25
27
 
26
28
  // ABIs
@@ -390,3 +392,160 @@ export function formatUSDC(amount: bigint): string {
390
392
  export function formatETH(amount: bigint): string {
391
393
  return formatUnits(amount, 18);
392
394
  }
395
+
396
+ // TrustGraph ABI
397
+ const TRUST_GRAPH_ABI = [
398
+ {
399
+ inputs: [
400
+ { name: 'agent', type: 'address' },
401
+ { name: 'trustLevel', type: 'uint8' },
402
+ ],
403
+ name: 'endorseAgent',
404
+ outputs: [],
405
+ stateMutability: 'nonpayable',
406
+ type: 'function',
407
+ },
408
+ {
409
+ inputs: [{ name: 'agent', type: 'address' }],
410
+ name: 'revokeEndorsement',
411
+ outputs: [],
412
+ stateMutability: 'nonpayable',
413
+ type: 'function',
414
+ },
415
+ {
416
+ inputs: [
417
+ { name: 'from', type: 'address' },
418
+ { name: 'to', type: 'address' },
419
+ ],
420
+ name: 'getDirectTrust',
421
+ outputs: [{ name: 'trustLevel', type: 'uint8' }],
422
+ stateMutability: 'view',
423
+ type: 'function',
424
+ },
425
+ {
426
+ inputs: [
427
+ { name: 'from', type: 'address' },
428
+ { name: 'to', type: 'address' },
429
+ { name: 'maxDepth', type: 'uint8' },
430
+ ],
431
+ name: 'getInferredTrust',
432
+ outputs: [
433
+ { name: 'trustScore', type: 'uint256' },
434
+ { name: 'pathLength', type: 'uint8' },
435
+ ],
436
+ stateMutability: 'view',
437
+ type: 'function',
438
+ },
439
+ {
440
+ inputs: [{ name: 'agent', type: 'address' }],
441
+ name: 'getEndorsements',
442
+ outputs: [{ name: 'endorsed', type: 'address[]' }],
443
+ stateMutability: 'view',
444
+ type: 'function',
445
+ },
446
+ {
447
+ inputs: [{ name: 'agent', type: 'address' }],
448
+ name: 'getEndorsers',
449
+ outputs: [{ name: 'endorsers', type: 'address[]' }],
450
+ stateMutability: 'view',
451
+ type: 'function',
452
+ },
453
+ {
454
+ inputs: [{ name: 'agent', type: 'address' }],
455
+ name: 'getTrustScore',
456
+ outputs: [{ name: 'score', type: 'uint256' }],
457
+ stateMutability: 'view',
458
+ type: 'function',
459
+ },
460
+ ] as const;
461
+
462
+ /**
463
+ * Get TrustGraph module instance
464
+ */
465
+ export function getTrustGraph() {
466
+ const config = loadConfig();
467
+ const publicClient = getPublicClient(config.network);
468
+ const contracts = getContracts(config.network);
469
+ const chain = config.network === 'mainnet' ? base : baseSepolia;
470
+
471
+ return {
472
+ async endorseAgent(agent: Address, trustLevel: number) {
473
+ const { client, account } = await loadWallet();
474
+ const hash = await client.writeContract({
475
+ address: contracts.TRUST_GRAPH,
476
+ abi: TRUST_GRAPH_ABI,
477
+ functionName: 'endorseAgent',
478
+ args: [agent, trustLevel],
479
+ account,
480
+ chain,
481
+ });
482
+ return hash;
483
+ },
484
+
485
+ async revokeEndorsement(agent: Address) {
486
+ const { client, account } = await loadWallet();
487
+ const hash = await client.writeContract({
488
+ address: contracts.TRUST_GRAPH,
489
+ abi: TRUST_GRAPH_ABI,
490
+ functionName: 'revokeEndorsement',
491
+ args: [agent],
492
+ account,
493
+ chain,
494
+ });
495
+ return hash;
496
+ },
497
+
498
+ async getDirectTrust(from: Address, to: Address): Promise<number> {
499
+ const result = await publicClient.readContract({
500
+ address: contracts.TRUST_GRAPH,
501
+ abi: TRUST_GRAPH_ABI,
502
+ functionName: 'getDirectTrust',
503
+ args: [from, to],
504
+ });
505
+ return Number(result);
506
+ },
507
+
508
+ async getInferredTrust(from: Address, to: Address, maxDepth: number = 4) {
509
+ const result = await publicClient.readContract({
510
+ address: contracts.TRUST_GRAPH,
511
+ abi: TRUST_GRAPH_ABI,
512
+ functionName: 'getInferredTrust',
513
+ args: [from, to, maxDepth],
514
+ });
515
+ return {
516
+ trustScore: Number(result[0]),
517
+ pathLength: Number(result[1]),
518
+ };
519
+ },
520
+
521
+ async getEndorsements(agent: Address): Promise<Address[]> {
522
+ const result = await publicClient.readContract({
523
+ address: contracts.TRUST_GRAPH,
524
+ abi: TRUST_GRAPH_ABI,
525
+ functionName: 'getEndorsements',
526
+ args: [agent],
527
+ });
528
+ return result as Address[];
529
+ },
530
+
531
+ async getEndorsers(agent: Address): Promise<Address[]> {
532
+ const result = await publicClient.readContract({
533
+ address: contracts.TRUST_GRAPH,
534
+ abi: TRUST_GRAPH_ABI,
535
+ functionName: 'getEndorsers',
536
+ args: [agent],
537
+ });
538
+ return result as Address[];
539
+ },
540
+
541
+ async getAggregateTrust(agent: Address): Promise<number> {
542
+ const result = await publicClient.readContract({
543
+ address: contracts.TRUST_GRAPH,
544
+ abi: TRUST_GRAPH_ABI,
545
+ functionName: 'getTrustScore',
546
+ args: [agent],
547
+ });
548
+ return Number(result);
549
+ },
550
+ };
551
+ }