@agirails/sdk 2.2.3 → 2.3.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.
Files changed (211) hide show
  1. package/README.md +65 -31
  2. package/dist/ACTPClient.d.ts +42 -1
  3. package/dist/ACTPClient.d.ts.map +1 -1
  4. package/dist/ACTPClient.js +207 -22
  5. package/dist/ACTPClient.js.map +1 -1
  6. package/dist/abi/AgentRegistry.json +133 -0
  7. package/dist/adapters/AdapterRouter.d.ts.map +1 -1
  8. package/dist/adapters/AdapterRouter.js.map +1 -1
  9. package/dist/adapters/BasicAdapter.d.ts +10 -1
  10. package/dist/adapters/BasicAdapter.d.ts.map +1 -1
  11. package/dist/adapters/BasicAdapter.js +36 -1
  12. package/dist/adapters/BasicAdapter.js.map +1 -1
  13. package/dist/adapters/X402Adapter.d.ts +34 -7
  14. package/dist/adapters/X402Adapter.d.ts.map +1 -1
  15. package/dist/adapters/X402Adapter.js +36 -8
  16. package/dist/adapters/X402Adapter.js.map +1 -1
  17. package/dist/adapters/index.d.ts +1 -1
  18. package/dist/adapters/index.d.ts.map +1 -1
  19. package/dist/adapters/index.js.map +1 -1
  20. package/dist/cli/commands/diff.d.ts +11 -0
  21. package/dist/cli/commands/diff.d.ts.map +1 -0
  22. package/dist/cli/commands/diff.js +115 -0
  23. package/dist/cli/commands/diff.js.map +1 -0
  24. package/dist/cli/commands/init.d.ts +1 -0
  25. package/dist/cli/commands/init.d.ts.map +1 -1
  26. package/dist/cli/commands/init.js +260 -19
  27. package/dist/cli/commands/init.js.map +1 -1
  28. package/dist/cli/commands/publish.d.ts +11 -0
  29. package/dist/cli/commands/publish.d.ts.map +1 -0
  30. package/dist/cli/commands/publish.js +170 -0
  31. package/dist/cli/commands/publish.js.map +1 -0
  32. package/dist/cli/commands/pull.d.ts +12 -0
  33. package/dist/cli/commands/pull.d.ts.map +1 -0
  34. package/dist/cli/commands/pull.js +99 -0
  35. package/dist/cli/commands/pull.js.map +1 -0
  36. package/dist/cli/commands/register.d.ts +16 -0
  37. package/dist/cli/commands/register.d.ts.map +1 -0
  38. package/dist/cli/commands/register.js +211 -0
  39. package/dist/cli/commands/register.js.map +1 -0
  40. package/dist/cli/index.js +10 -0
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/cli/utils/config.d.ts +6 -0
  43. package/dist/cli/utils/config.d.ts.map +1 -1
  44. package/dist/cli/utils/config.js.map +1 -1
  45. package/dist/config/agirailsmd.d.ts +94 -0
  46. package/dist/config/agirailsmd.d.ts.map +1 -0
  47. package/dist/config/agirailsmd.js +209 -0
  48. package/dist/config/agirailsmd.js.map +1 -0
  49. package/dist/config/networks.d.ts +22 -4
  50. package/dist/config/networks.d.ts.map +1 -1
  51. package/dist/config/networks.js +64 -26
  52. package/dist/config/networks.js.map +1 -1
  53. package/dist/config/publishPipeline.d.ts +75 -0
  54. package/dist/config/publishPipeline.d.ts.map +1 -0
  55. package/dist/config/publishPipeline.js +193 -0
  56. package/dist/config/publishPipeline.js.map +1 -0
  57. package/dist/config/syncOperations.d.ts +67 -0
  58. package/dist/config/syncOperations.d.ts.map +1 -0
  59. package/dist/config/syncOperations.js +208 -0
  60. package/dist/config/syncOperations.js.map +1 -0
  61. package/dist/erc8004/ERC8004Bridge.d.ts.map +1 -1
  62. package/dist/erc8004/ERC8004Bridge.js +6 -5
  63. package/dist/erc8004/ERC8004Bridge.js.map +1 -1
  64. package/dist/erc8004/ReputationReporter.d.ts.map +1 -1
  65. package/dist/erc8004/ReputationReporter.js +9 -12
  66. package/dist/erc8004/ReputationReporter.js.map +1 -1
  67. package/dist/index.d.ts +5 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +11 -3
  70. package/dist/index.js.map +1 -1
  71. package/dist/level0/request.d.ts.map +1 -1
  72. package/dist/level0/request.js +23 -86
  73. package/dist/level0/request.js.map +1 -1
  74. package/dist/level1/Agent.d.ts +0 -11
  75. package/dist/level1/Agent.d.ts.map +1 -1
  76. package/dist/level1/Agent.js +19 -36
  77. package/dist/level1/Agent.js.map +1 -1
  78. package/dist/protocol/ACTPKernel.d.ts +7 -1
  79. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  80. package/dist/protocol/ACTPKernel.js +13 -10
  81. package/dist/protocol/ACTPKernel.js.map +1 -1
  82. package/dist/protocol/EventMonitor.d.ts +14 -0
  83. package/dist/protocol/EventMonitor.d.ts.map +1 -1
  84. package/dist/protocol/EventMonitor.js +14 -0
  85. package/dist/protocol/EventMonitor.js.map +1 -1
  86. package/dist/registry/AgentRegistryClient.d.ts +75 -0
  87. package/dist/registry/AgentRegistryClient.d.ts.map +1 -0
  88. package/dist/registry/AgentRegistryClient.js +160 -0
  89. package/dist/registry/AgentRegistryClient.js.map +1 -0
  90. package/dist/runtime/BlockchainRuntime.d.ts +5 -0
  91. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  92. package/dist/runtime/BlockchainRuntime.js +1 -1
  93. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  94. package/dist/storage/ArchiveBundleBuilder.d.ts.map +1 -1
  95. package/dist/storage/ArchiveBundleBuilder.js.map +1 -1
  96. package/dist/storage/ArweaveClient.d.ts.map +1 -1
  97. package/dist/storage/ArweaveClient.js +2 -0
  98. package/dist/storage/ArweaveClient.js.map +1 -1
  99. package/dist/storage/FilebaseClient.d.ts.map +1 -1
  100. package/dist/storage/FilebaseClient.js +2 -0
  101. package/dist/storage/FilebaseClient.js.map +1 -1
  102. package/dist/types/adapter.d.ts +39 -0
  103. package/dist/types/adapter.d.ts.map +1 -1
  104. package/dist/types/adapter.js +7 -0
  105. package/dist/types/adapter.js.map +1 -1
  106. package/dist/types/x402.d.ts +23 -0
  107. package/dist/types/x402.d.ts.map +1 -1
  108. package/dist/types/x402.js.map +1 -1
  109. package/dist/utils/ErrorRecoveryGuide.d.ts.map +1 -1
  110. package/dist/utils/ErrorRecoveryGuide.js +3 -2
  111. package/dist/utils/ErrorRecoveryGuide.js.map +1 -1
  112. package/dist/utils/IPFSClient.d.ts +3 -2
  113. package/dist/utils/IPFSClient.d.ts.map +1 -1
  114. package/dist/utils/IPFSClient.js +7 -5
  115. package/dist/utils/IPFSClient.js.map +1 -1
  116. package/dist/utils/computeTypeHash.js +1 -3
  117. package/dist/utils/computeTypeHash.js.map +1 -1
  118. package/dist/utils/retry.d.ts.map +1 -1
  119. package/dist/utils/retry.js +0 -1
  120. package/dist/utils/retry.js.map +1 -1
  121. package/dist/utils/validation.d.ts +2 -2
  122. package/dist/utils/validation.d.ts.map +1 -1
  123. package/dist/utils/validation.js +2 -2
  124. package/dist/utils/validation.js.map +1 -1
  125. package/dist/wallet/AutoWalletProvider.d.ts +77 -0
  126. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -0
  127. package/dist/wallet/AutoWalletProvider.js +197 -0
  128. package/dist/wallet/AutoWalletProvider.js.map +1 -0
  129. package/dist/wallet/EOAWalletProvider.d.ts +21 -0
  130. package/dist/wallet/EOAWalletProvider.d.ts.map +1 -0
  131. package/dist/wallet/EOAWalletProvider.js +57 -0
  132. package/dist/wallet/EOAWalletProvider.js.map +1 -0
  133. package/dist/wallet/IWalletProvider.d.ts +115 -0
  134. package/dist/wallet/IWalletProvider.d.ts.map +1 -0
  135. package/dist/wallet/IWalletProvider.js +12 -0
  136. package/dist/wallet/IWalletProvider.js.map +1 -0
  137. package/dist/wallet/aa/BundlerClient.d.ts +70 -0
  138. package/dist/wallet/aa/BundlerClient.d.ts.map +1 -0
  139. package/dist/wallet/aa/BundlerClient.js +183 -0
  140. package/dist/wallet/aa/BundlerClient.js.map +1 -0
  141. package/dist/wallet/aa/DualNonceManager.d.ts +55 -0
  142. package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -0
  143. package/dist/wallet/aa/DualNonceManager.js +131 -0
  144. package/dist/wallet/aa/DualNonceManager.js.map +1 -0
  145. package/dist/wallet/aa/PaymasterClient.d.ts +52 -0
  146. package/dist/wallet/aa/PaymasterClient.d.ts.map +1 -0
  147. package/dist/wallet/aa/PaymasterClient.js +115 -0
  148. package/dist/wallet/aa/PaymasterClient.js.map +1 -0
  149. package/dist/wallet/aa/TransactionBatcher.d.ts +87 -0
  150. package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -0
  151. package/dist/wallet/aa/TransactionBatcher.js +148 -0
  152. package/dist/wallet/aa/TransactionBatcher.js.map +1 -0
  153. package/dist/wallet/aa/UserOpBuilder.d.ts +71 -0
  154. package/dist/wallet/aa/UserOpBuilder.d.ts.map +1 -0
  155. package/dist/wallet/aa/UserOpBuilder.js +196 -0
  156. package/dist/wallet/aa/UserOpBuilder.js.map +1 -0
  157. package/dist/wallet/aa/constants.d.ts +54 -0
  158. package/dist/wallet/aa/constants.d.ts.map +1 -0
  159. package/dist/wallet/aa/constants.js +18 -0
  160. package/dist/wallet/aa/constants.js.map +1 -0
  161. package/dist/wallet/keystore.d.ts +16 -0
  162. package/dist/wallet/keystore.d.ts.map +1 -0
  163. package/dist/wallet/keystore.js +132 -0
  164. package/dist/wallet/keystore.js.map +1 -0
  165. package/package.json +5 -2
  166. package/src/ACTPClient.ts +275 -27
  167. package/src/abi/AgentRegistry.json +133 -0
  168. package/src/adapters/AdapterRouter.ts +0 -1
  169. package/src/adapters/BasicAdapter.ts +41 -1
  170. package/src/adapters/X402Adapter.ts +94 -16
  171. package/src/adapters/index.ts +9 -1
  172. package/src/cli/commands/diff.ts +141 -0
  173. package/src/cli/commands/init.ts +311 -22
  174. package/src/cli/commands/publish.ts +208 -0
  175. package/src/cli/commands/pull.ts +124 -0
  176. package/src/cli/commands/register.ts +233 -0
  177. package/src/cli/index.ts +12 -0
  178. package/src/cli/utils/config.ts +9 -0
  179. package/src/config/agirailsmd.ts +262 -0
  180. package/src/config/networks.ts +89 -26
  181. package/src/config/publishPipeline.ts +276 -0
  182. package/src/config/syncOperations.ts +279 -0
  183. package/src/erc8004/ERC8004Bridge.ts +6 -5
  184. package/src/erc8004/ReputationReporter.ts +14 -18
  185. package/src/index.ts +15 -0
  186. package/src/level0/request.ts +27 -88
  187. package/src/level1/Agent.ts +21 -37
  188. package/src/protocol/ACTPKernel.ts +20 -10
  189. package/src/protocol/EventMonitor.ts +14 -0
  190. package/src/registry/AgentRegistryClient.ts +202 -0
  191. package/src/runtime/BlockchainRuntime.ts +7 -1
  192. package/src/storage/ArchiveBundleBuilder.ts +0 -2
  193. package/src/storage/ArweaveClient.ts +2 -1
  194. package/src/storage/FilebaseClient.ts +3 -3
  195. package/src/types/adapter.ts +14 -0
  196. package/src/types/x402.ts +32 -0
  197. package/src/utils/ErrorRecoveryGuide.ts +4 -2
  198. package/src/utils/IPFSClient.ts +9 -7
  199. package/src/utils/computeTypeHash.ts +1 -3
  200. package/src/utils/retry.ts +0 -1
  201. package/src/utils/validation.ts +2 -2
  202. package/src/wallet/AutoWalletProvider.ts +294 -0
  203. package/src/wallet/EOAWalletProvider.ts +69 -0
  204. package/src/wallet/IWalletProvider.ts +133 -0
  205. package/src/wallet/aa/BundlerClient.ts +273 -0
  206. package/src/wallet/aa/DualNonceManager.ts +163 -0
  207. package/src/wallet/aa/PaymasterClient.ts +173 -0
  208. package/src/wallet/aa/TransactionBatcher.ts +240 -0
  209. package/src/wallet/aa/UserOpBuilder.ts +246 -0
  210. package/src/wallet/aa/constants.ts +60 -0
  211. package/src/wallet/keystore.ts +119 -0
@@ -0,0 +1,202 @@
1
+ /**
2
+ * AgentRegistryClient - Thin wrapper for AgentRegistry v2 config operations
3
+ *
4
+ * Provides methods for:
5
+ * - Publishing AGIRAILS.md config (CID + hash) on-chain
6
+ * - Managing launchpad listing visibility
7
+ * - Reading config state for any agent
8
+ *
9
+ * @module registry/AgentRegistryClient
10
+ */
11
+
12
+ import { Contract, Signer, Provider } from 'ethers';
13
+ import AgentRegistryABI from '../abi/AgentRegistry.json';
14
+ import { ValidationError, TransactionRevertedError } from '../errors';
15
+
16
+ // ============================================================================
17
+ // Types
18
+ // ============================================================================
19
+
20
+ export interface AgentConfigState {
21
+ configHash: string;
22
+ configCID: string;
23
+ listed: boolean;
24
+ isActive: boolean;
25
+ updatedAt: number;
26
+ }
27
+
28
+ export interface PublishConfigResult {
29
+ txHash: string;
30
+ }
31
+
32
+ interface GasOptions {
33
+ maxFeePerGas?: bigint;
34
+ maxPriorityFeePerGas?: bigint;
35
+ }
36
+
37
+ // ============================================================================
38
+ // Client
39
+ // ============================================================================
40
+
41
+ export class AgentRegistryClient {
42
+ private contract: Contract;
43
+ private readonlyContract: Contract;
44
+
45
+ constructor(
46
+ private readonly registryAddress: string,
47
+ private readonly signer: Signer,
48
+ private readonly gasSettings?: GasOptions
49
+ ) {
50
+ this.contract = new Contract(registryAddress, AgentRegistryABI, signer);
51
+ this.readonlyContract = this.contract;
52
+ }
53
+
54
+ /**
55
+ * Create a read-only client (no signer required)
56
+ */
57
+ static readOnly(registryAddress: string, provider: Provider): AgentRegistryClient {
58
+ // Create a minimal signer-like object for the contract
59
+ // but only the readonly contract will be used
60
+ const contract = new Contract(registryAddress, AgentRegistryABI, provider);
61
+ const client = Object.create(AgentRegistryClient.prototype);
62
+ client.registryAddress = registryAddress;
63
+ client.readonlyContract = contract;
64
+ client.contract = null; // Write operations will throw
65
+ return client;
66
+ }
67
+
68
+ // ========== WRITE OPERATIONS ==========
69
+
70
+ /**
71
+ * Publish config (AGIRAILS.md) on-chain
72
+ *
73
+ * @param cid - IPFS CID pointing to the AGIRAILS.md file
74
+ * @param hash - keccak256 of canonical AGIRAILS.md content (bytes32)
75
+ * @returns Transaction hash
76
+ */
77
+ async publishConfig(cid: string, hash: string): Promise<PublishConfigResult> {
78
+ if (!this.contract) {
79
+ throw new Error('Write operations require a signer. Use AgentRegistryClient constructor, not readOnly().');
80
+ }
81
+
82
+ if (!cid || cid.length === 0) {
83
+ throw new ValidationError('cid', 'IPFS CID is required');
84
+ }
85
+ if (cid.length > 128) {
86
+ throw new ValidationError('cid', 'CID too long (max 128 characters)');
87
+ }
88
+ if (!hash || hash === '0x' + '0'.repeat(64)) {
89
+ throw new ValidationError('hash', 'Config hash is required (cannot be zero)');
90
+ }
91
+ if (!/^0x[a-fA-F0-9]{64}$/.test(hash)) {
92
+ throw new ValidationError('hash', 'Config hash must be a valid bytes32 hex string');
93
+ }
94
+
95
+ try {
96
+ const estimatedGas = await this.contract.publishConfig.estimateGas(cid, hash);
97
+ const gasLimit = (estimatedGas * 120n) / 100n; // 20% buffer
98
+
99
+ const txOptions: Record<string, unknown> = { gasLimit };
100
+ if (this.gasSettings?.maxFeePerGas) {
101
+ txOptions.maxFeePerGas = this.gasSettings.maxFeePerGas;
102
+ }
103
+ if (this.gasSettings?.maxPriorityFeePerGas) {
104
+ txOptions.maxPriorityFeePerGas = this.gasSettings.maxPriorityFeePerGas;
105
+ }
106
+
107
+ const tx = await this.contract.publishConfig(cid, hash, txOptions);
108
+ const receipt = await tx.wait();
109
+
110
+ return { txHash: receipt.hash };
111
+ } catch (error: unknown) {
112
+ if (error instanceof Error && error.message.includes('Not registered')) {
113
+ throw new TransactionRevertedError(
114
+ 'Agent not registered. Register first using the AgentRegistry before publishing config.',
115
+ 'publishConfig'
116
+ );
117
+ }
118
+ throw error;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Set launchpad listing visibility
124
+ *
125
+ * @param listed - Whether agent should be visible on launchpad
126
+ * @returns Transaction hash
127
+ */
128
+ async setListed(listed: boolean): Promise<string> {
129
+ if (!this.contract) {
130
+ throw new Error('Write operations require a signer. Use AgentRegistryClient constructor, not readOnly().');
131
+ }
132
+
133
+ try {
134
+ const estimatedGas = await this.contract.setListed.estimateGas(listed);
135
+ const gasLimit = (estimatedGas * 115n) / 100n; // 15% buffer
136
+
137
+ const txOptions: Record<string, unknown> = { gasLimit };
138
+ if (this.gasSettings?.maxFeePerGas) {
139
+ txOptions.maxFeePerGas = this.gasSettings.maxFeePerGas;
140
+ }
141
+ if (this.gasSettings?.maxPriorityFeePerGas) {
142
+ txOptions.maxPriorityFeePerGas = this.gasSettings.maxPriorityFeePerGas;
143
+ }
144
+
145
+ const tx = await this.contract.setListed(listed, txOptions);
146
+ const receipt = await tx.wait();
147
+
148
+ return receipt.hash;
149
+ } catch (error: unknown) {
150
+ if (error instanceof Error && error.message.includes('Not registered')) {
151
+ throw new TransactionRevertedError(
152
+ 'Agent not registered. Register first before setting listing status.',
153
+ 'setListed'
154
+ );
155
+ }
156
+ throw error;
157
+ }
158
+ }
159
+
160
+ // ========== READ OPERATIONS ==========
161
+
162
+ /**
163
+ * Get config state for an agent
164
+ *
165
+ * @param agentAddress - Agent's Ethereum address
166
+ * @returns Config state (hash, CID, listed, isActive, updatedAt)
167
+ */
168
+ async getConfig(agentAddress: string): Promise<AgentConfigState> {
169
+ const contract = this.readonlyContract || this.contract;
170
+ const profile = await contract.getAgent(agentAddress);
171
+
172
+ return {
173
+ configHash: profile.configHash,
174
+ configCID: profile.configCID,
175
+ listed: profile.listed,
176
+ isActive: profile.isActive,
177
+ updatedAt: Number(profile.updatedAt),
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Check if an agent is listed on the launchpad
183
+ *
184
+ * @param agentAddress - Agent's Ethereum address
185
+ * @returns true if agent is listed
186
+ */
187
+ async isListed(agentAddress: string): Promise<boolean> {
188
+ const config = await this.getConfig(agentAddress);
189
+ return config.listed;
190
+ }
191
+
192
+ /**
193
+ * Get the on-chain config hash for an agent
194
+ *
195
+ * @param agentAddress - Agent's Ethereum address
196
+ * @returns Config hash (bytes32) or zero hash if not published
197
+ */
198
+ async getConfigHash(agentAddress: string): Promise<string> {
199
+ const config = await this.getConfig(agentAddress);
200
+ return config.configHash;
201
+ }
202
+ }
@@ -65,6 +65,11 @@ export interface BlockchainRuntimeConfig {
65
65
  * If provided, attestation replay protection will survive restarts
66
66
  */
67
67
  stateDirectory?: string;
68
+ /**
69
+ * Number of block confirmations to wait after each state-changing tx.
70
+ * Default: 2 (Base L2 reorg safety). Set to 1 on testnet for speed.
71
+ */
72
+ confirmations?: number;
68
73
  }
69
74
 
70
75
  /**
@@ -163,7 +168,8 @@ export class BlockchainRuntime implements IACTPRuntime {
163
168
  this.kernel = new ACTPKernel(
164
169
  this.networkConfig.contracts.actpKernel,
165
170
  this.signer,
166
- config.gasSettings
171
+ config.gasSettings,
172
+ config.confirmations
167
173
  );
168
174
 
169
175
  this.escrow = new EscrowVault(
@@ -15,14 +15,12 @@ import { ValidationError } from '../errors';
15
15
  import {
16
16
  ArchiveBundle,
17
17
  ArchiveChainId,
18
- ArchiveFinalState,
19
18
  ArchiveParticipants,
20
19
  ArchiveReferences,
21
20
  ArchiveHashes,
22
21
  ArchiveSignatures,
23
22
  ArchiveAttestation,
24
23
  ArchiveSettlement,
25
- EscrowRelease,
26
24
  ARCHIVE_BUNDLE_TYPE
27
25
  } from './types';
28
26
 
@@ -48,7 +48,6 @@ import {
48
48
  import { withRetry, RetryOptions } from '../utils/retry';
49
49
  import {
50
50
  GatewayCircuitBreaker,
51
- CircuitBreakerConfig
52
51
  } from '../utils/circuitBreaker';
53
52
 
54
53
  // ============================================================================
@@ -538,6 +537,7 @@ export class ArweaveClient {
538
537
  const chunks: Uint8Array[] = [];
539
538
  let totalSize = 0;
540
539
 
540
+ // eslint-disable-next-line no-constant-condition
541
541
  while (true) {
542
542
  const { done, value } = await reader.read();
543
543
  if (done) break;
@@ -671,6 +671,7 @@ export class ArweaveClient {
671
671
  const chunks: Uint8Array[] = [];
672
672
  let totalSize = 0;
673
673
 
674
+ // eslint-disable-next-line no-constant-condition
674
675
  while (true) {
675
676
  const { done, value } = await reader.read();
676
677
  if (done) break;
@@ -14,7 +14,7 @@
14
14
  * @module storage/FilebaseClient
15
15
  */
16
16
 
17
- import { S3Client, PutObjectCommand, GetObjectCommand, HeadObjectCommand } from '@aws-sdk/client-s3';
17
+ import { S3Client, PutObjectCommand, HeadObjectCommand } from '@aws-sdk/client-s3';
18
18
  import {
19
19
  StorageError,
20
20
  StorageAuthenticationError,
@@ -39,8 +39,6 @@ import {
39
39
  import { withRetry, RetryOptions } from '../utils/retry';
40
40
  import {
41
41
  GatewayCircuitBreaker,
42
- CircuitBreakerConfig,
43
- globalCircuitBreaker
44
42
  } from '../utils/circuitBreaker';
45
43
 
46
44
  // ============================================================================
@@ -329,6 +327,7 @@ export class FilebaseClient {
329
327
  const chunks: Uint8Array[] = [];
330
328
  let totalSize = 0;
331
329
 
330
+ // eslint-disable-next-line no-constant-condition
332
331
  while (true) {
333
332
  const { done, value } = await reader.read();
334
333
  if (done) break;
@@ -516,6 +515,7 @@ export class FilebaseClient {
516
515
  const chunks: Uint8Array[] = [];
517
516
  let totalSize = 0;
518
517
 
518
+ // eslint-disable-next-line no-constant-condition
519
519
  while (true) {
520
520
  const { done, value } = await reader.read();
521
521
  if (done) break;
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import { z } from 'zod';
14
+ import type { X402FeeBreakdown } from './x402';
14
15
 
15
16
  // ============================================================================
16
17
  // AdapterMetadata - Describes adapter capabilities
@@ -249,6 +250,12 @@ export interface UnifiedPayResult {
249
250
  * Use with ReputationReporter.reportSettlement() after release.
250
251
  */
251
252
  erc8004AgentId?: string;
253
+
254
+ /**
255
+ * Fee breakdown for x402 payments routed through X402Relay.
256
+ * Present only when relay is configured and payment used the relay path.
257
+ */
258
+ feeBreakdown?: X402FeeBreakdown;
252
259
  }
253
260
 
254
261
  /**
@@ -268,6 +275,13 @@ export const UnifiedPayResultSchema = z.object({
268
275
  requester: z.string().min(1),
269
276
  deadline: z.string().min(1),
270
277
  erc8004AgentId: z.string().optional(),
278
+ feeBreakdown: z.object({
279
+ grossAmount: z.string(),
280
+ providerNet: z.string(),
281
+ platformFee: z.string(),
282
+ feeBps: z.number(),
283
+ estimated: z.literal(true),
284
+ }).optional(),
271
285
  });
272
286
 
273
287
  // ============================================================================
package/src/types/x402.ts CHANGED
@@ -194,6 +194,38 @@ export class X402Error extends Error {
194
194
  }
195
195
  }
196
196
 
197
+ // ============================================================================
198
+ // Fee Types
199
+ // ============================================================================
200
+
201
+ /**
202
+ * Fee breakdown for x402 payments routed through X402Relay.
203
+ *
204
+ * Shows how the gross amount was split between provider and platform.
205
+ * Fee = max(grossAmount * feeBps / 10000, MIN_FEE).
206
+ *
207
+ * NOTE: This is a client-side **estimate** computed from the configured
208
+ * platformFeeBps. The on-chain X402Relay contract is the source of truth.
209
+ * If an admin updates the relay's fee rate, this estimate may diverge
210
+ * from the actual on-chain split until the SDK config is refreshed.
211
+ */
212
+ export interface X402FeeBreakdown {
213
+ /** Total amount from the 402 header (USDC wei, 6 decimals) */
214
+ grossAmount: string;
215
+
216
+ /** Estimated amount provider received: grossAmount - platformFee */
217
+ providerNet: string;
218
+
219
+ /** Estimated amount treasury received: max(feeBps%, $0.05) */
220
+ platformFee: string;
221
+
222
+ /** Fee rate used for estimate (basis points, e.g. 100 = 1%) */
223
+ feeBps: number;
224
+
225
+ /** True — this is a client-side estimate, not read from chain */
226
+ estimated: true;
227
+ }
228
+
197
229
  // ============================================================================
198
230
  // Type Guards
199
231
  // ============================================================================
@@ -7,6 +7,8 @@
7
7
  * @module utils/ErrorRecoveryGuide
8
8
  */
9
9
 
10
+ import { sdkLogger } from './Logger';
11
+
10
12
  /**
11
13
  * Error severity levels for prioritization
12
14
  */
@@ -650,14 +652,14 @@ export async function withRecoveryGuidance<T>(
650
652
  }
651
653
 
652
654
  if (logGuidance) {
653
- console.error(ErrorRecoveryGuide.formatGuidance(error));
655
+ sdkLogger.error(ErrorRecoveryGuide.formatGuidance(error));
654
656
  }
655
657
 
656
658
  if (autoRetry && recovery.retryable) {
657
659
  const retryParams = ErrorRecoveryGuide.getRetryParams(error);
658
660
  if (retryParams && attempts < retryParams.maxRetries) {
659
661
  attempts++;
660
- console.log(
662
+ sdkLogger.info(
661
663
  `Retrying (${attempts}/${retryParams.maxRetries}) after ${retryParams.delayMs}ms...`
662
664
  );
663
665
  await new Promise((resolve) =>
@@ -74,8 +74,8 @@ export interface IPFSClientConfig {
74
74
  allowedProtocols?: string[];
75
75
 
76
76
  /**
77
- * SECURITY FIX (MEDIUM-3): Allow localhost URLs
78
- * Default: true (required for local IPFS daemon)
77
+ * Allow localhost URLs (e.g., local IPFS daemon).
78
+ * Default: false (SSRF protection). Set to true explicitly for local development.
79
79
  */
80
80
  allowLocalhost?: boolean;
81
81
  }
@@ -85,7 +85,8 @@ export interface IPFSClientConfig {
85
85
  */
86
86
  export const IPFS_CONFIGS = {
87
87
  local: {
88
- url: 'http://localhost:5001'
88
+ url: 'http://localhost:5001',
89
+ allowLocalhost: true, // Explicit opt-in for local development
89
90
  },
90
91
  infura: {
91
92
  url: 'https://ipfs.infura.io:5001/api/v0'
@@ -128,14 +129,14 @@ export class IPFSHTTPClientImpl implements IPFSClient {
128
129
  const url = config.url || 'http://localhost:5001';
129
130
 
130
131
  // SECURITY FIX (MEDIUM-3): Validate URL
131
- this.validateUrl(url, config.allowLocalhost ?? true, config.allowedProtocols);
132
+ this.validateUrl(url, config.allowLocalhost ?? false, config.allowedProtocols);
132
133
 
133
134
  this.config = {
134
135
  url,
135
136
  timeout: config.timeout || 60000,
136
137
  maxSize: config.maxSize || IPFSHTTPClientImpl.DEFAULT_MAX_SIZE,
137
138
  allowedProtocols: config.allowedProtocols || IPFSHTTPClientImpl.DEFAULT_ALLOWED_PROTOCOLS,
138
- allowLocalhost: config.allowLocalhost ?? true,
139
+ allowLocalhost: config.allowLocalhost ?? false,
139
140
  auth: config.auth,
140
141
  headers: config.headers,
141
142
  } as Required<IPFSClientConfig>;
@@ -359,8 +360,9 @@ export function createIPFSClient(): IPFSClient {
359
360
  });
360
361
  }
361
362
 
362
- // Default to local IPFS daemon
363
+ // Default to local IPFS daemon (explicit localhost opt-in)
363
364
  return new IPFSHTTPClientImpl({
364
- url: 'http://localhost:5001'
365
+ url: 'http://localhost:5001',
366
+ allowLocalhost: true,
365
367
  });
366
368
  }
@@ -44,7 +44,5 @@ if (require.main === module) {
44
44
  console.log(typeHash);
45
45
  console.log();
46
46
 
47
- console.log(' Update this value in:');
48
- console.log('- /Testnet/docs/AIP-4.md:204');
49
- console.log('- /Testnet/docs/schemas/aip-4-delivery.eip712.json:11');
47
+ console.log('Use this type hash in your EIP-712 typed data configuration.');
50
48
  }
@@ -236,7 +236,6 @@ export async function withRetry<T>(
236
236
  } = options;
237
237
 
238
238
  let lastError: unknown;
239
- const startTime = Date.now();
240
239
 
241
240
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
242
241
  try {
@@ -320,7 +320,7 @@ export async function validateEndpointURL(endpoint: string, fieldName: string =
320
320
  * @param fieldName - Field name for error messages
321
321
  * @throws {InvalidCIDError} If CID is invalid
322
322
  */
323
- export function validateCID(cid: string, fieldName: string = 'cid'): void {
323
+ export function validateCID(cid: string, _fieldName: string = 'cid'): void {
324
324
  if (!cid || typeof cid !== 'string') {
325
325
  throw new InvalidCIDError(String(cid), 'CID is required');
326
326
  }
@@ -337,7 +337,7 @@ export function validateCID(cid: string, fieldName: string = 'cid'): void {
337
337
  * @param fieldName - Field name for error messages
338
338
  * @throws {InvalidArweaveTxIdError} If TX ID is invalid
339
339
  */
340
- export function validateArweaveTxId(txId: string, fieldName: string = 'txId'): void {
340
+ export function validateArweaveTxId(txId: string, _fieldName: string = 'txId'): void {
341
341
  if (!txId || typeof txId !== 'string') {
342
342
  throw new InvalidArweaveTxIdError(String(txId), 'TX ID is required');
343
343
  }