Skip to content

Commit b1a2a92

Browse files
author
azeth-sync[bot]
committed
v0.2.4: sync from monorepo 2026-03-07
1 parent 1d54368 commit b1a2a92

3 files changed

Lines changed: 226 additions & 11 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azeth/sdk",
3-
"version": "0.2.3",
3+
"version": "0.2.4",
44
"type": "module",
55
"description": "TypeScript SDK for the Azeth trust infrastructure — smart accounts, x402 payments, reputation, and service discovery",
66
"license": "MIT",
@@ -38,7 +38,7 @@
3838
"test:mutation": "npx stryker run"
3939
},
4040
"dependencies": {
41-
"@azeth/common": "^0.2.3",
41+
"@azeth/common": "^0.2.4",
4242
"@x402/core": "^2.4.0",
4343
"@x402/extensions": "^2.4.0",
4444
"@xmtp/agent-sdk": "^2.2.0",

src/client.ts

Lines changed: 223 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
import { validateAddress, validateUrl, validatePositiveAmount } from './utils/validation.js';
3535
import { resolveAddresses, requireAddress } from './utils/addresses.js';
3636
import { withRetry } from './utils/retry.js';
37-
import { AzethFactoryAbi, PaymentAgreementModuleAbi } from '@azeth/common/abis';
37+
import { AzethFactoryAbi, PaymentAgreementModuleAbi, TrustRegistryModuleAbi } from '@azeth/common/abis';
3838
import { createAccount, getAccountAddress, type CreateAccountParams, type CreateAccountResult } from './account/create.js';
3939
import { setTokenWhitelist as setTokenWhitelistFn, setProtocolWhitelist as setProtocolWhitelistFn } from './account/guardian.js';
4040
import { getBalance, getAllBalances, type BalanceResult } from './account/balance.js';
@@ -103,6 +103,63 @@ export interface AzethKitConfig {
103103
guardianAutoSign?: boolean;
104104
}
105105

106+
/** Simplified account creation — auto-fills owner, guardrails, and wraps into registry.
107+
* Use this when you want sensible defaults without manual guardrail configuration. */
108+
export interface SimpleCreateAccountParams {
109+
/** Display name for the trust registry entry */
110+
name: string;
111+
/** Entity type: 'agent', 'service', or 'infrastructure' */
112+
entityType: 'agent' | 'service' | 'infrastructure';
113+
/** Human-readable description */
114+
description: string;
115+
/** Service capabilities for discovery (e.g., ['weather-data', 'price-feed']) */
116+
capabilities?: string[];
117+
/** Service endpoint URL */
118+
endpoint?: string;
119+
/** Max per-transaction amount in USD (default: 100) */
120+
maxTxAmountUSD?: number;
121+
/** Daily spending limit in USD (default: 1000) */
122+
dailySpendLimitUSD?: number;
123+
/** Guardian address for co-signing high-value txs (default: self-guardian) */
124+
guardian?: `0x${string}`;
125+
/** Emergency withdrawal destination (default: owner) */
126+
emergencyWithdrawTo?: `0x${string}`;
127+
}
128+
129+
/** Simplified opinion — rating from -100 to 100, auto-converts to WAD format */
130+
export interface SimpleOpinion {
131+
/** Target service's ERC-8004 token ID */
132+
serviceTokenId: bigint;
133+
/** Rating from -100 to 100 (supports decimals like 85.5) */
134+
rating: number;
135+
/** Primary categorization tag (default: 'quality') */
136+
tag1?: string;
137+
/** Secondary categorization tag (default: '') */
138+
tag2?: string;
139+
/** Service endpoint being rated */
140+
endpoint?: string;
141+
}
142+
143+
/** Result from pay() — fetch402 result with auto-parsed response body */
144+
export interface PayResult {
145+
/** Parsed response body (JSON object or raw text string) */
146+
data: unknown;
147+
/** Raw HTTP response (body already consumed) */
148+
response: Response;
149+
/** Whether an x402 payment was made */
150+
paymentMade: boolean;
151+
/** Payment amount in token base units (e.g., USDC with 6 decimals) */
152+
amount?: bigint;
153+
/** On-chain transaction hash of the payment */
154+
txHash?: `0x${string}`;
155+
/** Response time in milliseconds */
156+
responseTimeMs?: number;
157+
/** Whether on-chain settlement was verified */
158+
settlementVerified: boolean;
159+
/** How access was obtained */
160+
paymentMethod: 'x402' | 'smart-account' | 'session' | 'none';
161+
}
162+
106163
/** AzethKit -- Trust Infrastructure SDK for the Machine Economy
107164
*
108165
* Provides Phase 0 methods for machine participants:
@@ -359,10 +416,60 @@ export class AzethKit {
359416
*
360417
* Single atomic transaction: deploys ERC-1967 proxy, installs all 4 modules,
361418
* registers on ERC-8004 trust registry (optional), and permanently revokes factory access.
419+
*
420+
* Accepts either full params (CreateAccountParams) or simplified params
421+
* (SimpleCreateAccountParams) that auto-fill owner, guardrails, and registry.
422+
*
423+
* @example Simplified (recommended for most cases):
424+
* ```typescript
425+
* await agent.createAccount({
426+
* name: 'WeatherOracle',
427+
* entityType: 'service',
428+
* description: 'Real-time weather data',
429+
* capabilities: ['weather-data'],
430+
* endpoint: 'http://localhost:3402',
431+
* });
432+
* ```
433+
*
434+
* @example Full control:
435+
* ```typescript
436+
* await agent.createAccount({
437+
* owner: agent.address,
438+
* guardrails: { maxTxAmountUSD: 500n * 10n**18n, ... },
439+
* registry: { name: 'WeatherOracle', entityType: 'service', ... },
440+
* });
441+
* ```
362442
*/
363-
async createAccount(params: CreateAccountParams): Promise<CreateAccountResult> {
443+
async createAccount(params: CreateAccountParams | SimpleCreateAccountParams): Promise<CreateAccountResult> {
364444
this._requireNotDestroyed();
365-
const result = await createAccount(this.publicClient, this.walletClient, this.addresses, params);
445+
446+
let fullParams: CreateAccountParams;
447+
if ('owner' in params) {
448+
fullParams = params;
449+
} else {
450+
const maxTx = params.maxTxAmountUSD ?? 100;
451+
const dailyLimit = params.dailySpendLimitUSD ?? 1000;
452+
fullParams = {
453+
owner: this.address,
454+
guardrails: {
455+
maxTxAmountUSD: BigInt(Math.round(maxTx)) * 10n ** 18n,
456+
dailySpendLimitUSD: BigInt(Math.round(dailyLimit)) * 10n ** 18n,
457+
guardianMaxTxAmountUSD: BigInt(Math.round(maxTx * 5)) * 10n ** 18n,
458+
guardianDailySpendLimitUSD: BigInt(Math.round(dailyLimit * 5)) * 10n ** 18n,
459+
guardian: params.guardian ?? this.address,
460+
emergencyWithdrawTo: params.emergencyWithdrawTo ?? this.address,
461+
},
462+
registry: {
463+
name: params.name,
464+
description: params.description,
465+
entityType: params.entityType,
466+
capabilities: params.capabilities ?? [],
467+
endpoint: params.endpoint,
468+
},
469+
};
470+
}
471+
472+
const result = await createAccount(this.publicClient, this.walletClient, this.addresses, fullParams);
366473
// Cache the newly created account
367474
if (!this._smartAccounts) {
368475
this._smartAccounts = [result.account];
@@ -853,15 +960,83 @@ export class AzethKit {
853960
}
854961
}
855962

963+
/** Pay for an x402-gated service and return parsed response data.
964+
*
965+
* Convenience wrapper around fetch402 that auto-parses the response body.
966+
* Returns JSON objects for JSON responses, raw text for others.
967+
*
968+
* @param url - Service URL to fetch and pay for
969+
* @param options - Fetch options (method, body, maxAmount, etc.)
970+
* @returns PayResult with parsed `data` field
971+
*
972+
* @example
973+
* ```typescript
974+
* const result = await agent.pay('https://api.example.com/data');
975+
* console.log(result.data); // parsed JSON response
976+
* ```
977+
*/
978+
async pay(url: string, options?: Fetch402Options): Promise<PayResult> {
979+
const result = await this.fetch402(url, options);
980+
const text = await result.response.text();
981+
let data: unknown;
982+
try {
983+
data = JSON.parse(text);
984+
} catch {
985+
data = text;
986+
}
987+
return { ...result, data };
988+
}
989+
856990
// ──────────────────────────────────────────────
857991
// Trust registry
858992
// ──────────────────────────────────────────────
859993

860-
/** Register this account on the ERC-8004 trust registry */
994+
/** Register on the ERC-8004 trust registry, or update metadata if already registered.
995+
*
996+
* If the smart account is already registered (e.g., via createAccount with registry params),
997+
* this method gracefully falls back to updating the metadata fields instead of reverting.
998+
*/
861999
async publishService(params: RegisterParams): Promise<RegisterResult> {
8621000
this._requireNotDestroyed();
8631001
const account = await this.resolveSmartAccount();
8641002
const smartAccountClient = await this._getSmartAccountClient(account);
1003+
1004+
// Check if already registered to avoid AlreadyRegistered revert
1005+
const moduleAddress = this.addresses.trustRegistryModule;
1006+
if (moduleAddress) {
1007+
let isRegistered = false;
1008+
try {
1009+
isRegistered = await this.publicClient.readContract({
1010+
address: moduleAddress,
1011+
abi: TrustRegistryModuleAbi,
1012+
functionName: 'isRegistered',
1013+
args: [account],
1014+
}) as boolean;
1015+
} catch {
1016+
// If check fails, proceed with registration attempt
1017+
}
1018+
1019+
if (isRegistered) {
1020+
// Already registered — update metadata instead
1021+
const updates: MetadataUpdate[] = [];
1022+
if (params.name) updates.push({ key: 'name', value: params.name });
1023+
if (params.description) updates.push({ key: 'description', value: params.description });
1024+
if (params.capabilities.length > 0) {
1025+
updates.push({ key: 'capabilities', value: JSON.stringify(params.capabilities) });
1026+
}
1027+
if (params.endpoint) updates.push({ key: 'endpoint', value: params.endpoint });
1028+
1029+
let txHash = '0x' as `0x${string}`;
1030+
if (updates.length > 0) {
1031+
txHash = await updateMetadataBatch(
1032+
this.publicClient, smartAccountClient, this.addresses, this.address, updates,
1033+
);
1034+
}
1035+
1036+
return { tokenId: 0n, txHash };
1037+
}
1038+
}
1039+
8651040
return registerOnRegistry(
8661041
this.publicClient, smartAccountClient, this.addresses, this.address, params,
8671042
);
@@ -1050,15 +1225,55 @@ export class AzethKit {
10501225

10511226
/** Submit a reputation opinion for an agent via the ReputationModule.
10521227
*
1053-
* Requires a positive net USD payment from this account to the target agent
1054-
* (aggregated on-chain via Chainlink). Value is int128 with configurable decimal precision.
1228+
* Accepts either full OnChainOpinion params or simplified SimpleOpinion with a rating.
1229+
* Requires a positive net USD payment from this account to the target agent.
1230+
*
1231+
* @example Simplified:
1232+
* ```typescript
1233+
* await agent.submitOpinion({
1234+
* serviceTokenId: service.tokenId,
1235+
* rating: 85, // -100 to 100
1236+
* tag1: 'quality', // optional
1237+
* });
1238+
* ```
1239+
*
1240+
* @example Full control:
1241+
* ```typescript
1242+
* await agent.submitOpinion({
1243+
* agentId: 1024n,
1244+
* value: 85n * 10n**18n,
1245+
* valueDecimals: 18,
1246+
* tag1: 'quality', tag2: 'x402',
1247+
* endpoint: 'https://...', opinionURI: '', opinionHash: '0x...',
1248+
* });
1249+
* ```
10551250
*/
1056-
async submitOpinion(opinion: OnChainOpinion): Promise<`0x${string}`> {
1251+
async submitOpinion(opinion: OnChainOpinion | SimpleOpinion): Promise<`0x${string}`> {
10571252
this._requireNotDestroyed();
1253+
1254+
let fullOpinion: OnChainOpinion;
1255+
if ('agentId' in opinion) {
1256+
fullOpinion = opinion;
1257+
} else {
1258+
if (opinion.rating < -100 || opinion.rating > 100) {
1259+
throw new AzethError('Rating must be between -100 and 100', 'INVALID_INPUT', { field: 'rating' });
1260+
}
1261+
fullOpinion = {
1262+
agentId: opinion.serviceTokenId,
1263+
value: BigInt(Math.round(opinion.rating * 1e18)),
1264+
valueDecimals: 18,
1265+
tag1: opinion.tag1 ?? 'quality',
1266+
tag2: opinion.tag2 ?? '',
1267+
endpoint: opinion.endpoint ?? '',
1268+
opinionURI: '',
1269+
opinionHash: '0x0000000000000000000000000000000000000000000000000000000000000000' as `0x${string}`,
1270+
};
1271+
}
1272+
10581273
const account = await this.resolveSmartAccount();
10591274
const smartAccountClient = await this._getSmartAccountClient(account);
10601275
return submitOnChainOpinion(
1061-
this.publicClient, smartAccountClient, this.addresses, this.address, opinion,
1276+
this.publicClient, smartAccountClient, this.addresses, this.address, fullOpinion,
10621277
);
10631278
}
10641279

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @azeth/sdk — Trust Infrastructure for the Machine Economy
22

3-
export { AzethKit, type AzethKitConfig } from './client.js';
3+
export { AzethKit, type AzethKitConfig, type SimpleCreateAccountParams, type SimpleOpinion, type PayResult } from './client.js';
44

55
// Account operations
66
export { type CreateAccountParams, type CreateAccountResult } from './account/create.js';

0 commit comments

Comments
 (0)