@armory-sh/client-ethers 0.2.26-alpha.23.77 → 0.2.26-alpha.23.78

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/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { NetworkId, TokenId, ArmoryPaymentResult, ValidationError, X402ClientErr
2
2
  export { PaymentException as PaymentError, SigningError, X402ClientError } from '@armory-sh/base';
3
3
  import { Signer, Provider } from 'ethers';
4
4
  export { Provider, Signer } from 'ethers';
5
+ import { ClientHook } from '@armory-sh/base/types/hooks';
5
6
 
6
7
  /**
7
8
  * Simple one-line payment API for Armory (Ethers)
@@ -140,6 +141,7 @@ interface X402ClientConfig {
140
141
  domainName?: string;
141
142
  /** Override EIP-712 domain version for custom tokens */
142
143
  domainVersion?: string;
144
+ hooks?: ClientHook<Signer>[];
143
145
  }
144
146
  interface SignerClientConfig extends X402ClientConfig {
145
147
  signer: Signer;
@@ -159,6 +161,7 @@ interface X402TransportConfig {
159
161
  onPaymentRequired?: (requirements: unknown) => boolean | Promise<boolean>;
160
162
  onPaymentSuccess?: (settlement: unknown) => void;
161
163
  onPaymentError?: (error: Error) => void;
164
+ hooks?: ClientHook<Signer>[];
162
165
  }
163
166
  interface X402RequestInit extends Omit<RequestInit, "headers"> {
164
167
  headers?: Record<string, string> | Headers;
@@ -272,7 +275,7 @@ declare function detectX402Version(_response: Response): 2;
272
275
  declare function getPaymentHeaderName(_version: 2): string;
273
276
  interface ParsedPaymentRequirements {
274
277
  version: 2;
275
- requirements: PaymentRequirementsV2;
278
+ accepts: PaymentRequirementsV2[];
276
279
  }
277
280
  /**
278
281
  * Parse x402 PAYMENT-REQUIRED header from response
@@ -282,7 +285,7 @@ declare function parsePaymentRequired(response: Response): ParsedPaymentRequirem
282
285
  /**
283
286
  * Create x402 payment payload (V2-only wrapper)
284
287
  */
285
- declare function createX402Payment(signer: Signer, parsed: ParsedPaymentRequirements, fromAddress: Address, nonce?: `0x${string}`, validBefore?: number, domainName?: string, domainVersion?: string): Promise<PaymentPayloadV2>;
288
+ declare function createX402Payment(signer: Signer, requirement: PaymentRequirementsV2, fromAddress: Address, nonce?: `0x${string}`, validBefore?: number, domainName?: string, domainVersion?: string): Promise<PaymentPayloadV2>;
286
289
 
287
290
  interface X402Transport {
288
291
  fetch(url: string, init?: X402RequestInit): Promise<Response>;
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { X402ClientError, createEIP712Domain, V2_HEADERS, PaymentException, isX402V2PaymentRequired, validatePaymentConfig, isValidationError, resolveNetwork, resolveToken, normalizeBase64Url, decodeBase64ToUtf8, getNetworkConfig, normalizeNetworkName, encodePaymentV2, decodeSettlementV2 } from '@armory-sh/base';
2
2
  export { PaymentException as PaymentError, SigningError, X402ClientError } from '@armory-sh/base';
3
+ import { runOnPaymentRequiredHooks, selectRequirementWithHooks, runBeforeSignPaymentHooks, runAfterPaymentResponseHooks } from '@armory-sh/base/client-hooks-runtime';
3
4
  import { ethers } from 'ethers';
4
5
 
5
6
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -142,7 +143,7 @@ function parsePaymentRequired(response) {
142
143
  }
143
144
  return {
144
145
  version: 2,
145
- requirements: parsed.accepts[0]
146
+ accepts: parsed.accepts
146
147
  };
147
148
  } catch (error) {
148
149
  if (error instanceof PaymentException) throw error;
@@ -203,12 +204,12 @@ async function createX402V2Payment(signer, requirements, fromAddress, nonce, val
203
204
  payload
204
205
  };
205
206
  }
206
- async function createX402Payment(signer, parsed, fromAddress, nonce, validBefore, domainName, domainVersion) {
207
+ async function createX402Payment(signer, requirement, fromAddress, nonce, validBefore, domainName, domainVersion) {
207
208
  const effectiveNonce = nonce ?? createNonce();
208
209
  const effectiveValidBefore = validBefore ?? Math.floor(Date.now() / 1e3) + 3600;
209
210
  return createX402V2Payment(
210
211
  signer,
211
- parsed.requirements,
212
+ requirement,
212
213
  fromAddress,
213
214
  effectiveNonce,
214
215
  effectiveValidBefore,
@@ -229,7 +230,8 @@ var defaultConfig = {
229
230
  onPaymentSuccess: () => {
230
231
  },
231
232
  onPaymentError: () => {
232
- }
233
+ },
234
+ hooks: []
233
235
  };
234
236
  var createState = (config) => ({
235
237
  config: { ...defaultConfig, ...config }
@@ -250,11 +252,11 @@ var fetchWithTimeout = async (url, init, timeout) => {
250
252
  }
251
253
  };
252
254
  var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
253
- var getRequirementDomainOverrides = (parsed) => {
254
- const requirement = parsed.requirements;
255
+ var getRequirementDomainOverrides = (_parsed, requirement) => {
255
256
  const extra = requirement.extra;
256
- const extraName = extra && typeof extra === "object" && typeof extra.name === "string" ? extra.name : void 0;
257
- const extraVersion = extra && typeof extra === "object" && typeof extra.version === "string" ? extra.version : void 0;
257
+ const extraRecord = extra && typeof extra === "object" ? extra : void 0;
258
+ const extraName = extraRecord && typeof extraRecord.name === "string" ? extraRecord.name : void 0;
259
+ const extraVersion = extraRecord && typeof extraRecord.version === "string" ? extraRecord.version : void 0;
258
260
  return {
259
261
  domainName: requirement.name ?? extraName,
260
262
  domainVersion: requirement.version ?? extraVersion
@@ -268,17 +270,46 @@ var handlePaymentRequired = async (state, response) => {
268
270
  }
269
271
  try {
270
272
  const parsed = parsePaymentRequired(response);
273
+ const initialRequirement = parsed.accepts[0];
274
+ if (!initialRequirement) {
275
+ throw new Error("No payment requirements found in accepts array");
276
+ }
271
277
  const from = await state.signer.getAddress();
272
- const requirementDomain = getRequirementDomainOverrides(parsed);
278
+ const paymentRequiredContext = {
279
+ url: response.url,
280
+ requestInit: void 0,
281
+ accepts: parsed.accepts,
282
+ requirements: initialRequirement,
283
+ selectedRequirement: initialRequirement,
284
+ serverExtensions: void 0,
285
+ fromAddress: from,
286
+ nonce: `0x${Date.now().toString(16).padStart(64, "0")}`,
287
+ validBefore: Math.floor(Date.now() / 1e3) + initialRequirement.maxTimeoutSeconds
288
+ };
289
+ await runOnPaymentRequiredHooks(state.config.hooks, paymentRequiredContext);
290
+ const selectedRequirement = await selectRequirementWithHooks(
291
+ state.config.hooks,
292
+ paymentRequiredContext
293
+ );
294
+ const requirementDomain = getRequirementDomainOverrides(
295
+ parsed,
296
+ selectedRequirement
297
+ );
273
298
  const payload = await createX402Payment(
274
299
  state.signer,
275
- parsed,
300
+ selectedRequirement,
276
301
  from,
277
- void 0,
278
- Math.floor(Date.now() / 1e3) + parsed.requirements.maxTimeoutSeconds,
302
+ paymentRequiredContext.nonce,
303
+ paymentRequiredContext.validBefore,
279
304
  requirementDomain.domainName,
280
305
  requirementDomain.domainVersion
281
306
  );
307
+ await runBeforeSignPaymentHooks(state.config.hooks, {
308
+ payload,
309
+ requirements: selectedRequirement,
310
+ wallet: state.signer,
311
+ paymentContext: paymentRequiredContext
312
+ });
282
313
  const encoded = encodePaymentV2(payload);
283
314
  const headerName = getPaymentHeaderName(parsed.version);
284
315
  const paymentResponse = await fetchWithTimeout(
@@ -292,6 +323,13 @@ var handlePaymentRequired = async (state, response) => {
292
323
  const settlement = decodeSettlementV2(
293
324
  paymentResponse.headers.get(V2_HEADERS.PAYMENT_RESPONSE) || ""
294
325
  );
326
+ await runAfterPaymentResponseHooks(state.config.hooks, {
327
+ payload,
328
+ requirements: selectedRequirement,
329
+ wallet: state.signer,
330
+ paymentContext: paymentRequiredContext,
331
+ response: paymentResponse
332
+ });
295
333
  return { success: true, settlement };
296
334
  } catch (error) {
297
335
  return {
@@ -303,7 +341,7 @@ var handlePaymentRequired = async (state, response) => {
303
341
  var shouldRetryPayment = async (state, response) => {
304
342
  if (!state.config.autoPay) return false;
305
343
  const parsed = parsePaymentRequired(response);
306
- return await state.config.onPaymentRequired(parsed.requirements);
344
+ return await state.config.onPaymentRequired(parsed.accepts[0]);
307
345
  };
308
346
  var x402Fetch = async (state, url, init = {}) => {
309
347
  const fullUrl = state.config.baseURL ? new URL(url, state.config.baseURL).toString() : url;
@@ -571,7 +609,9 @@ var createArmory = (config) => {
571
609
 
572
610
  // src/client.ts
573
611
  function createX402Client(config) {
574
- const transport = createX402Transport(void 0);
612
+ const transport = createX402Transport({
613
+ hooks: config.hooks
614
+ });
575
615
  if ("signer" in config && config.signer) {
576
616
  transport.setSigner(config.signer);
577
617
  } else if ("provider" in config && config.provider) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/client-ethers",
3
- "version": "0.2.26-alpha.23.77",
3
+ "version": "0.2.26-alpha.23.78",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "keywords": [
@@ -47,7 +47,7 @@
47
47
  "directory": "packages/client-ethers"
48
48
  },
49
49
  "dependencies": {
50
- "@armory-sh/base": "0.2.27-alpha.23.77",
50
+ "@armory-sh/base": "0.2.27-alpha.23.78",
51
51
  "ethers": "6.16.0"
52
52
  },
53
53
  "devDependencies": {