@azeth/provider 0.2.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.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/agreement-cache.d.ts +20 -0
- package/dist/agreement-cache.d.ts.map +1 -0
- package/dist/agreement-cache.js +133 -0
- package/dist/agreement-cache.js.map +1 -0
- package/dist/agreement-keeper.d.ts +43 -0
- package/dist/agreement-keeper.d.ts.map +1 -0
- package/dist/agreement-keeper.js +102 -0
- package/dist/agreement-keeper.js.map +1 -0
- package/dist/examples/index.d.ts +4 -0
- package/dist/examples/index.d.ts.map +1 -0
- package/dist/examples/index.js +3 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/examples/price-feed.d.ts +22 -0
- package/dist/examples/price-feed.d.ts.map +1 -0
- package/dist/examples/price-feed.js +148 -0
- package/dist/examples/price-feed.js.map +1 -0
- package/dist/examples/pricing-routes.d.ts +15 -0
- package/dist/examples/pricing-routes.d.ts.map +1 -0
- package/dist/examples/pricing-routes.js +77 -0
- package/dist/examples/pricing-routes.js.map +1 -0
- package/dist/extensions/payment-agreement.d.ts +37 -0
- package/dist/extensions/payment-agreement.d.ts.map +1 -0
- package/dist/extensions/payment-agreement.js +39 -0
- package/dist/extensions/payment-agreement.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/pre-settled.d.ts +29 -0
- package/dist/middleware/pre-settled.d.ts.map +1 -0
- package/dist/middleware/pre-settled.js +80 -0
- package/dist/middleware/pre-settled.js.map +1 -0
- package/dist/stack.d.ts +75 -0
- package/dist/stack.d.ts.map +1 -0
- package/dist/stack.js +169 -0
- package/dist/stack.js.map +1 -0
- package/dist/storage.d.ts +48 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +96 -0
- package/dist/storage.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { AzethError, TOKENS } from '@azeth/common';
|
|
3
|
+
import { paymentMiddlewareFromHTTPServer } from '@x402/hono';
|
|
4
|
+
import { isSupportedCoin, getPrice, getFreshPrice } from './price-feed.js';
|
|
5
|
+
import { preSettledPaymentMiddleware } from '../middleware/pre-settled.js';
|
|
6
|
+
/** Create the x402-gated pricing routes.
|
|
7
|
+
*
|
|
8
|
+
* Uses @x402/hono middleware for V2 protocol support including:
|
|
9
|
+
* - PAYMENT-SIGNATURE / PAYMENT-RESPONSE headers (v2)
|
|
10
|
+
* - SIWx wallet-based sessions (pay once, then access via wallet sig)
|
|
11
|
+
* - Payment agreement extension (subscription terms in 402 response)
|
|
12
|
+
* - Pre-settled smart account payments (X-Payment-Tx header bypass)
|
|
13
|
+
*
|
|
14
|
+
* When httpServer is null, all routes return 503 (graceful degradation).
|
|
15
|
+
*/
|
|
16
|
+
export function createPricingRoutes(httpServer) {
|
|
17
|
+
const app = new Hono();
|
|
18
|
+
if (!httpServer) {
|
|
19
|
+
app.get('/:coinId', (c) => {
|
|
20
|
+
return c.json({
|
|
21
|
+
error: {
|
|
22
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
23
|
+
message: 'Price feed requires x402 facilitator configuration',
|
|
24
|
+
},
|
|
25
|
+
}, 503);
|
|
26
|
+
});
|
|
27
|
+
return app;
|
|
28
|
+
}
|
|
29
|
+
// Pre-settled payment verification — checks X-Payment-Tx header for smart account payments.
|
|
30
|
+
// If a valid on-chain Transfer is found, sets paymentTxHash/paymentFrom/paymentAmount context
|
|
31
|
+
// and skips the x402 facilitator settlement (payment already happened via UserOp).
|
|
32
|
+
const payTo = (process.env['X402_PAY_TO'] ?? '');
|
|
33
|
+
const chainName = (process.env['AZETH_CHAIN'] ?? 'baseSepolia');
|
|
34
|
+
// Use chain-aware USDC address from TOKENS constants (not env var, which may be for a different chain)
|
|
35
|
+
const usdcAddress = TOKENS[chainName].USDC;
|
|
36
|
+
const priceStr = process.env['X402_PRICE_FEED_PRICE'] ?? '$0.01';
|
|
37
|
+
// Parse price string like "$0.01" to atomic USDC (6 decimals)
|
|
38
|
+
const priceNum = parseFloat(priceStr.replace('$', ''));
|
|
39
|
+
const priceAtomicAmount = BigInt(Math.round(priceNum * 1e6));
|
|
40
|
+
if (payTo && usdcAddress) {
|
|
41
|
+
app.use('*', preSettledPaymentMiddleware({
|
|
42
|
+
payTo,
|
|
43
|
+
usdcAddress,
|
|
44
|
+
priceAtomicAmount,
|
|
45
|
+
rpcUrl: process.env['AZETH_RPC_URL'] ?? process.env['BASE_RPC_URL'],
|
|
46
|
+
chainName,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
// x402 V2 middleware — handles 402, verify, settle, SIWx, extensions.
|
|
50
|
+
// Skipped when pre-settled payment was verified (preSettledVerified flag set).
|
|
51
|
+
app.use('*', async (c, next) => {
|
|
52
|
+
if (c['preSettledVerified']) {
|
|
53
|
+
return next();
|
|
54
|
+
}
|
|
55
|
+
return paymentMiddlewareFromHTTPServer(httpServer)(c, next);
|
|
56
|
+
});
|
|
57
|
+
// Price data handler — pure business logic, no payment context needed.
|
|
58
|
+
// Payment info (amount, settlement tx) is in response headers via standard x402 protocol:
|
|
59
|
+
// - PAYMENT-RESPONSE header contains { success, transaction, network }
|
|
60
|
+
app.get('/:coinId', async (c) => {
|
|
61
|
+
const coinId = c.req.param('coinId');
|
|
62
|
+
if (!isSupportedCoin(coinId)) {
|
|
63
|
+
throw new AzethError('Unsupported coin', 'INVALID_INPUT', {
|
|
64
|
+
coinId,
|
|
65
|
+
supported: [
|
|
66
|
+
'bitcoin', 'ethereum', 'solana', 'usd-coin', 'chainlink',
|
|
67
|
+
'aave', 'uniswap', 'maker', 'compound-governance-token',
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const fresh = c.req.query('fresh') === 'true';
|
|
72
|
+
const data = fresh ? await getFreshPrice(coinId) : await getPrice(coinId);
|
|
73
|
+
return c.json({ data });
|
|
74
|
+
});
|
|
75
|
+
return app;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=pricing-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing-routes.js","sourceRoot":"","sources":["../../src/examples/pricing-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ResourceServerExtension } from '@x402/core/types';
|
|
2
|
+
/** Payment agreement terms advertised in the 402 response.
|
|
3
|
+
* Tells clients they can create an on-chain agreement instead of paying per-request. */
|
|
4
|
+
export interface AgreementTerms {
|
|
5
|
+
/** Service payee address */
|
|
6
|
+
payee: `0x${string}`;
|
|
7
|
+
/** Payment token address (e.g., USDC) */
|
|
8
|
+
token: `0x${string}`;
|
|
9
|
+
/** PaymentAgreementModule contract address */
|
|
10
|
+
moduleAddress: `0x${string}`;
|
|
11
|
+
/** Minimum amount per interval in token smallest units */
|
|
12
|
+
minAmountPerInterval: string;
|
|
13
|
+
/** Suggested interval in seconds (e.g., 86400 for daily) */
|
|
14
|
+
suggestedInterval: number;
|
|
15
|
+
}
|
|
16
|
+
/** Extension key used in 402 response extensions object */
|
|
17
|
+
export declare const PAYMENT_AGREEMENT_KEY = "payment-agreement";
|
|
18
|
+
/** Create a custom ResourceServerExtension that adds agreement terms to the 402 response.
|
|
19
|
+
*
|
|
20
|
+
* Clients see in the 402 response:
|
|
21
|
+
* ```json
|
|
22
|
+
* {
|
|
23
|
+
* "extensions": {
|
|
24
|
+
* "payment-agreement": {
|
|
25
|
+
* "acceptsAgreements": true,
|
|
26
|
+
* "terms": { "payee": "0x...", "token": "0x...", ... }
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* This is a server-side-only extension — it adds metadata to the PaymentRequired
|
|
33
|
+
* response but does not validate incoming payment payloads. Agreement validation
|
|
34
|
+
* happens in AzethSIWxStorage.hasPaid().
|
|
35
|
+
*/
|
|
36
|
+
export declare function createPaymentAgreementExtension(terms: AgreementTerms): ResourceServerExtension;
|
|
37
|
+
//# sourceMappingURL=payment-agreement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-agreement.d.ts","sourceRoot":"","sources":["../../src/extensions/payment-agreement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE;yFACyF;AACzF,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,yCAAyC;IACzC,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,8CAA8C;IAC9C,aAAa,EAAE,KAAK,MAAM,EAAE,CAAC;IAC7B,0DAA0D;IAC1D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,cAAc,GAAG,uBAAuB,CAkB9F"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Extension key used in 402 response extensions object */
|
|
2
|
+
export const PAYMENT_AGREEMENT_KEY = 'payment-agreement';
|
|
3
|
+
/** Create a custom ResourceServerExtension that adds agreement terms to the 402 response.
|
|
4
|
+
*
|
|
5
|
+
* Clients see in the 402 response:
|
|
6
|
+
* ```json
|
|
7
|
+
* {
|
|
8
|
+
* "extensions": {
|
|
9
|
+
* "payment-agreement": {
|
|
10
|
+
* "acceptsAgreements": true,
|
|
11
|
+
* "terms": { "payee": "0x...", "token": "0x...", ... }
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* This is a server-side-only extension — it adds metadata to the PaymentRequired
|
|
18
|
+
* response but does not validate incoming payment payloads. Agreement validation
|
|
19
|
+
* happens in AzethSIWxStorage.hasPaid().
|
|
20
|
+
*/
|
|
21
|
+
export function createPaymentAgreementExtension(terms) {
|
|
22
|
+
return {
|
|
23
|
+
key: PAYMENT_AGREEMENT_KEY,
|
|
24
|
+
/** Enrich the 402 PaymentRequired response with agreement terms */
|
|
25
|
+
async enrichPaymentRequiredResponse(_declaration, _context) {
|
|
26
|
+
return {
|
|
27
|
+
acceptsAgreements: true,
|
|
28
|
+
terms: {
|
|
29
|
+
payee: terms.payee,
|
|
30
|
+
token: terms.token,
|
|
31
|
+
moduleAddress: terms.moduleAddress,
|
|
32
|
+
minAmountPerInterval: terms.minAmountPerInterval,
|
|
33
|
+
suggestedInterval: terms.suggestedInterval,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=payment-agreement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-agreement.js","sourceRoot":"","sources":["../../src/extensions/payment-agreement.ts"],"names":[],"mappings":"AAiBA,2DAA2D;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAAqB;IACnE,OAAO;QACL,GAAG,EAAE,qBAAqB;QAE1B,mEAAmE;QACnE,KAAK,CAAC,6BAA6B,CAAC,YAAqB,EAAE,QAAiB;YAC1E,OAAO;gBACL,iBAAiB,EAAE,IAAI;gBACvB,KAAK,EAAE;oBACL,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;oBAChD,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;iBAC3C;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { createX402Stack, createX402StackFromEnv, CAIP2_NETWORKS, LocalFacilitatorClient, declareSIWxExtension, paymentMiddlewareFromHTTPServer, } from './stack.js';
|
|
2
|
+
export type { X402StackConfig, X402Stack, RoutesConfig, x402HTTPResourceServer, } from './stack.js';
|
|
3
|
+
export { AzethSIWxStorage } from './storage.js';
|
|
4
|
+
export type { AzethSIWxStorageConfig } from './storage.js';
|
|
5
|
+
export { AgreementKeeper } from './agreement-keeper.js';
|
|
6
|
+
export type { AgreementKeeperConfig } from './agreement-keeper.js';
|
|
7
|
+
export { findActiveAgreementForPayee, clearAgreementCache, setAgreementCacheTtl } from './agreement-cache.js';
|
|
8
|
+
export { createPaymentAgreementExtension, PAYMENT_AGREEMENT_KEY } from './extensions/payment-agreement.js';
|
|
9
|
+
export type { AgreementTerms } from './extensions/payment-agreement.js';
|
|
10
|
+
export { preSettledPaymentMiddleware } from './middleware/pre-settled.js';
|
|
11
|
+
export type { ProviderEnv } from './middleware/pre-settled.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,sBAAsB,EAEtB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAG3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGnE,OAAO,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG9G,OAAO,EAAE,+BAA+B,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC3G,YAAY,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// x402 stack — core provider functionality
|
|
2
|
+
export { createX402Stack, createX402StackFromEnv, CAIP2_NETWORKS, LocalFacilitatorClient,
|
|
3
|
+
// Re-exported x402 types
|
|
4
|
+
declareSIWxExtension, paymentMiddlewareFromHTTPServer, } from './stack.js';
|
|
5
|
+
// Agreement-aware SIWx storage
|
|
6
|
+
export { AzethSIWxStorage } from './storage.js';
|
|
7
|
+
// Agreement keeper — periodic execution of due agreements
|
|
8
|
+
export { AgreementKeeper } from './agreement-keeper.js';
|
|
9
|
+
// Agreement cache — LRU cache with stale-on-error
|
|
10
|
+
export { findActiveAgreementForPayee, clearAgreementCache, setAgreementCacheTtl } from './agreement-cache.js';
|
|
11
|
+
// Payment agreement extension
|
|
12
|
+
export { createPaymentAgreementExtension, PAYMENT_AGREEMENT_KEY } from './extensions/payment-agreement.js';
|
|
13
|
+
// Pre-settled payment middleware
|
|
14
|
+
export { preSettledPaymentMiddleware } from './middleware/pre-settled.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,sBAAsB;AACtB,yBAAyB;AACzB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,YAAY,CAAC;AAQpB,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,0DAA0D;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,kDAAkD;AAClD,OAAO,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE9G,8BAA8B;AAC9B,OAAO,EAAE,+BAA+B,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG3G,iCAAiC;AACjC,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Context, Env, Next } from 'hono';
|
|
2
|
+
import { type SupportedChainName } from '@azeth/common';
|
|
3
|
+
/** Minimal Hono env for pre-settled payment middleware.
|
|
4
|
+
* Consumer apps can extend this with their own variables. */
|
|
5
|
+
export interface ProviderEnv extends Env {
|
|
6
|
+
Variables: {
|
|
7
|
+
paymentFrom: `0x${string}`;
|
|
8
|
+
paymentAmount: bigint;
|
|
9
|
+
paymentTxHash: `0x${string}`;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Pre-settled payment verification middleware.
|
|
13
|
+
*
|
|
14
|
+
* Checks for X-Payment-Tx header. If present, verifies the transaction on-chain
|
|
15
|
+
* by decoding USDC Transfer event logs and confirming the payment meets requirements.
|
|
16
|
+
*
|
|
17
|
+
* When valid: sets context variables (paymentFrom, paymentAmount, paymentTxHash)
|
|
18
|
+
* and calls next() — downstream x402 middleware should be skipped.
|
|
19
|
+
*
|
|
20
|
+
* When invalid: falls through to let x402 middleware handle normally.
|
|
21
|
+
*/
|
|
22
|
+
export declare function preSettledPaymentMiddleware(config: {
|
|
23
|
+
payTo: `0x${string}`;
|
|
24
|
+
usdcAddress: `0x${string}`;
|
|
25
|
+
priceAtomicAmount: bigint;
|
|
26
|
+
rpcUrl?: string;
|
|
27
|
+
chainName?: SupportedChainName;
|
|
28
|
+
}): (c: Context<ProviderEnv>, next: Next) => Promise<void>;
|
|
29
|
+
//# sourceMappingURL=pre-settled.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-settled.d.ts","sourceRoot":"","sources":["../../src/middleware/pre-settled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE/C,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAE1E;8DAC8D;AAC9D,MAAM,WAAW,WAAY,SAAQ,GAAG;IACtC,SAAS,EAAE;QACT,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,KAAK,MAAM,EAAE,CAAC;KAC9B,CAAC;CACH;AASD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC,IAOe,GAAG,OAAO,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,mBA4DlD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createPublicClient, http, parseAbiItem } from 'viem';
|
|
2
|
+
import { resolveViemChain } from '@azeth/common';
|
|
3
|
+
/** USDC Transfer(address,address,uint256) event topic */
|
|
4
|
+
const TRANSFER_EVENT = parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)');
|
|
5
|
+
/** Track consumed tx hashes to prevent replay (one payment = one access) */
|
|
6
|
+
const usedTxHashes = new Set();
|
|
7
|
+
const MAX_USED_TX_HASHES = 50_000;
|
|
8
|
+
/** Pre-settled payment verification middleware.
|
|
9
|
+
*
|
|
10
|
+
* Checks for X-Payment-Tx header. If present, verifies the transaction on-chain
|
|
11
|
+
* by decoding USDC Transfer event logs and confirming the payment meets requirements.
|
|
12
|
+
*
|
|
13
|
+
* When valid: sets context variables (paymentFrom, paymentAmount, paymentTxHash)
|
|
14
|
+
* and calls next() — downstream x402 middleware should be skipped.
|
|
15
|
+
*
|
|
16
|
+
* When invalid: falls through to let x402 middleware handle normally.
|
|
17
|
+
*/
|
|
18
|
+
export function preSettledPaymentMiddleware(config) {
|
|
19
|
+
const chain = resolveViemChain(config.chainName ?? 'baseSepolia');
|
|
20
|
+
const publicClient = createPublicClient({
|
|
21
|
+
chain,
|
|
22
|
+
transport: http(config.rpcUrl),
|
|
23
|
+
});
|
|
24
|
+
return async (c, next) => {
|
|
25
|
+
const txHashHeader = c.req.header('X-Payment-Tx');
|
|
26
|
+
if (!txHashHeader || !/^0x[0-9a-fA-F]{64}$/.test(txHashHeader)) {
|
|
27
|
+
return next();
|
|
28
|
+
}
|
|
29
|
+
const txHash = txHashHeader;
|
|
30
|
+
// Reject already-consumed tx hashes before making RPC call
|
|
31
|
+
if (usedTxHashes.has(txHash)) {
|
|
32
|
+
return next(); // Fall through to x402
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const receipt = await publicClient.getTransactionReceipt({ hash: txHash });
|
|
36
|
+
if (receipt.status !== 'success') {
|
|
37
|
+
return next(); // Transaction failed, fall through to x402
|
|
38
|
+
}
|
|
39
|
+
// Find USDC Transfer event matching requirements
|
|
40
|
+
for (const log of receipt.logs) {
|
|
41
|
+
if (log.address.toLowerCase() !== config.usdcAddress.toLowerCase())
|
|
42
|
+
continue;
|
|
43
|
+
if (log.topics.length < 3)
|
|
44
|
+
continue;
|
|
45
|
+
// topics[0] = event sig, topics[1] = from, topics[2] = to
|
|
46
|
+
const eventSig = log.topics[0];
|
|
47
|
+
if (eventSig !== '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef')
|
|
48
|
+
continue;
|
|
49
|
+
const toAddress = `0x${log.topics[2].slice(26)}`;
|
|
50
|
+
if (toAddress.toLowerCase() !== config.payTo.toLowerCase())
|
|
51
|
+
continue;
|
|
52
|
+
// Decode value from log data
|
|
53
|
+
const value = BigInt(log.data);
|
|
54
|
+
if (value < config.priceAtomicAmount)
|
|
55
|
+
continue;
|
|
56
|
+
// Valid pre-settled payment found — extract `from` from the on-chain log,
|
|
57
|
+
// NOT the client-controlled header (which could be spoofed).
|
|
58
|
+
const logFrom = `0x${log.topics[1].slice(26)}`;
|
|
59
|
+
c.set('paymentFrom', logFrom);
|
|
60
|
+
c.set('paymentAmount', value);
|
|
61
|
+
c.set('paymentTxHash', txHash);
|
|
62
|
+
// Mark tx hash as consumed — prevents replay
|
|
63
|
+
usedTxHashes.add(txHash);
|
|
64
|
+
if (usedTxHashes.size > MAX_USED_TX_HASHES) {
|
|
65
|
+
const oldest = usedTxHashes.values().next().value;
|
|
66
|
+
if (oldest !== undefined)
|
|
67
|
+
usedTxHashes.delete(oldest);
|
|
68
|
+
}
|
|
69
|
+
// Set a flag for downstream to know payment is pre-settled
|
|
70
|
+
c['preSettledVerified'] = true;
|
|
71
|
+
return next();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// RPC error or tx not found — fall through to x402
|
|
76
|
+
}
|
|
77
|
+
return next();
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=pre-settled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-settled.js","sourceRoot":"","sources":["../../src/middleware/pre-settled.ts"],"names":[],"mappings":"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"}
|
package/dist/stack.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type PublicClient, type WalletClient, type Chain, type Transport, type Account } from 'viem';
|
|
2
|
+
import { type SupportedChainName } from '@azeth/common';
|
|
3
|
+
import { x402Facilitator } from '@x402/core/facilitator';
|
|
4
|
+
import { x402ResourceServer, x402HTTPResourceServer, type FacilitatorClient, type RoutesConfig } from '@x402/core/server';
|
|
5
|
+
import type { PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse, SupportedResponse } from '@x402/core/types';
|
|
6
|
+
import { AzethSIWxStorage } from './storage.js';
|
|
7
|
+
import { type AgreementTerms } from './extensions/payment-agreement.js';
|
|
8
|
+
/** CAIP-2 network identifiers for supported chains */
|
|
9
|
+
export declare const CAIP2_NETWORKS: Record<SupportedChainName, `eip155:${string}`>;
|
|
10
|
+
/** Configuration for the x402 stack */
|
|
11
|
+
export interface X402StackConfig {
|
|
12
|
+
/** Chain name */
|
|
13
|
+
chainName: SupportedChainName;
|
|
14
|
+
/** Network in CAIP-2 format */
|
|
15
|
+
network: `eip155:${string}`;
|
|
16
|
+
/** Payment recipient address */
|
|
17
|
+
payTo: `0x${string}`;
|
|
18
|
+
/** Wallet client for gas settlement */
|
|
19
|
+
walletClient: WalletClient<Transport, Chain, Account>;
|
|
20
|
+
/** Public client for on-chain reads */
|
|
21
|
+
publicClient: PublicClient<Transport, Chain>;
|
|
22
|
+
/** Agreement terms (null = agreements disabled) */
|
|
23
|
+
agreementTerms?: AgreementTerms | null;
|
|
24
|
+
}
|
|
25
|
+
/** The complete x402 V2 stack returned by createX402Stack */
|
|
26
|
+
export interface X402Stack {
|
|
27
|
+
/** Self-hosted facilitator */
|
|
28
|
+
facilitator: x402Facilitator;
|
|
29
|
+
/** Resource server wrapping the facilitator */
|
|
30
|
+
server: x402ResourceServer;
|
|
31
|
+
/** HTTP server wrapping the resource server with routes */
|
|
32
|
+
httpServer: x402HTTPResourceServer;
|
|
33
|
+
/** Agreement-aware SIWx storage */
|
|
34
|
+
storage: AzethSIWxStorage;
|
|
35
|
+
/** Public client for on-chain reads (needed by keeper) */
|
|
36
|
+
publicClient: PublicClient<Transport, Chain>;
|
|
37
|
+
/** Wallet client for gas settlement (needed by keeper) */
|
|
38
|
+
walletClient: WalletClient<Transport, Chain, Account>;
|
|
39
|
+
}
|
|
40
|
+
/** Wraps x402Facilitator as a FacilitatorClient for in-process use.
|
|
41
|
+
* Avoids HTTP round-trips by calling the facilitator directly. */
|
|
42
|
+
export declare class LocalFacilitatorClient implements FacilitatorClient {
|
|
43
|
+
private readonly f;
|
|
44
|
+
constructor(facilitator: x402Facilitator);
|
|
45
|
+
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
|
|
46
|
+
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
|
|
47
|
+
getSupported(): Promise<SupportedResponse>;
|
|
48
|
+
}
|
|
49
|
+
/** Create the complete x402 V2 stack with self-hosted facilitator, SIWx sessions,
|
|
50
|
+
* and payment agreement support.
|
|
51
|
+
*
|
|
52
|
+
* Architecture:
|
|
53
|
+
* 1. Self-hosted facilitator (we control settlement, no external dependency)
|
|
54
|
+
* 2. Resource server with EVM price parsing
|
|
55
|
+
* 3. SIWx extension for wallet-based sessions
|
|
56
|
+
* 4. Payment-agreement extension for subscription terms
|
|
57
|
+
* 5. Agreement-aware SIWx storage for hybrid access
|
|
58
|
+
*
|
|
59
|
+
* @param config - Stack configuration
|
|
60
|
+
* @param routes - Route configurations for protected endpoints
|
|
61
|
+
* @returns Complete x402 stack
|
|
62
|
+
*/
|
|
63
|
+
export declare function createX402Stack(config: X402StackConfig, routes: RoutesConfig): X402Stack;
|
|
64
|
+
/** Create a complete x402 stack from environment variables.
|
|
65
|
+
* Returns null if required keys are missing (graceful degradation).
|
|
66
|
+
*
|
|
67
|
+
* Unlike the server's version, this creates its own publicClient
|
|
68
|
+
* directly from the RPC URL — no dependency on external singletons.
|
|
69
|
+
*/
|
|
70
|
+
export declare function createX402StackFromEnv(routes: RoutesConfig): X402Stack | null;
|
|
71
|
+
export { declareSIWxExtension } from '@x402/extensions/sign-in-with-x';
|
|
72
|
+
export { paymentMiddlewareFromHTTPServer } from '@x402/hono';
|
|
73
|
+
export type { RoutesConfig } from '@x402/core/server';
|
|
74
|
+
export type { x402HTTPResourceServer } from '@x402/core/server';
|
|
75
|
+
//# sourceMappingURL=stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../src/stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,OAAO,EACb,MAAM,MAAM,CAAC;AAGd,OAAO,EAA6C,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC1H,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAU/H,OAAO,EAAE,gBAAgB,EAA+B,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEzG,sDAAsD;AACtD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,kBAAkB,EAAE,UAAU,MAAM,EAAE,CAKzE,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,eAAe;IAC9B,iBAAiB;IACjB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,+BAA+B;IAC/B,OAAO,EAAE,UAAU,MAAM,EAAE,CAAC;IAC5B,gCAAgC;IAChC,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,uCAAuC;IACvC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACtD,uCAAuC;IACvC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C,mDAAmD;IACnD,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACxC;AAED,6DAA6D;AAC7D,MAAM,WAAW,SAAS;IACxB,8BAA8B;IAC9B,WAAW,EAAE,eAAe,CAAC;IAC7B,+CAA+C;IAC/C,MAAM,EAAE,kBAAkB,CAAC;IAC3B,2DAA2D;IAC3D,UAAU,EAAE,sBAAsB,CAAC;IACnC,mCAAmC;IACnC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,0DAA0D;IAC1D,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C,0DAA0D;IAC1D,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;CACvD;AAED;mEACmE;AACnE,qBAAa,sBAAuB,YAAW,iBAAiB;IAC9D,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAkB;gBAExB,WAAW,EAAE,eAAe;IAIlC,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAIzG,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAIzG,YAAY,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAMjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,YAAY,GACnB,SAAS,CAgEX;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,YAAY,GACnB,SAAS,GAAG,IAAI,CA+DlB;AAGD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/stack.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { createPublicClient, createWalletClient, http, } from 'viem';
|
|
2
|
+
import { publicActions } from 'viem';
|
|
3
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
|
+
import { TOKENS, AZETH_CONTRACTS, resolveViemChain } from '@azeth/common';
|
|
5
|
+
import { x402Facilitator } from '@x402/core/facilitator';
|
|
6
|
+
import { x402ResourceServer, x402HTTPResourceServer } from '@x402/core/server';
|
|
7
|
+
import { registerExactEvmScheme as registerFacilitatorEvm } from '@x402/evm/exact/facilitator';
|
|
8
|
+
import { registerExactEvmScheme as registerServerEvm } from '@x402/evm/exact/server';
|
|
9
|
+
import { toFacilitatorEvmSigner } from '@x402/evm';
|
|
10
|
+
import { siwxResourceServerExtension, createSIWxSettleHook, createSIWxRequestHook, } from '@x402/extensions/sign-in-with-x';
|
|
11
|
+
import { AzethSIWxStorage } from './storage.js';
|
|
12
|
+
import { createPaymentAgreementExtension } from './extensions/payment-agreement.js';
|
|
13
|
+
/** CAIP-2 network identifiers for supported chains */
|
|
14
|
+
export const CAIP2_NETWORKS = {
|
|
15
|
+
base: 'eip155:8453',
|
|
16
|
+
baseSepolia: 'eip155:84532',
|
|
17
|
+
ethereumSepolia: 'eip155:11155111',
|
|
18
|
+
ethereum: 'eip155:1',
|
|
19
|
+
};
|
|
20
|
+
/** Wraps x402Facilitator as a FacilitatorClient for in-process use.
|
|
21
|
+
* Avoids HTTP round-trips by calling the facilitator directly. */
|
|
22
|
+
export class LocalFacilitatorClient {
|
|
23
|
+
f;
|
|
24
|
+
constructor(facilitator) {
|
|
25
|
+
this.f = facilitator;
|
|
26
|
+
}
|
|
27
|
+
async verify(paymentPayload, paymentRequirements) {
|
|
28
|
+
return this.f.verify(paymentPayload, paymentRequirements);
|
|
29
|
+
}
|
|
30
|
+
async settle(paymentPayload, paymentRequirements) {
|
|
31
|
+
return this.f.settle(paymentPayload, paymentRequirements);
|
|
32
|
+
}
|
|
33
|
+
async getSupported() {
|
|
34
|
+
// x402Facilitator.getSupported() returns network as plain string,
|
|
35
|
+
// but FacilitatorClient expects Network (`${string}:${string}`).
|
|
36
|
+
// The values are always CAIP-2 formatted, so the cast is safe.
|
|
37
|
+
return this.f.getSupported();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Create the complete x402 V2 stack with self-hosted facilitator, SIWx sessions,
|
|
41
|
+
* and payment agreement support.
|
|
42
|
+
*
|
|
43
|
+
* Architecture:
|
|
44
|
+
* 1. Self-hosted facilitator (we control settlement, no external dependency)
|
|
45
|
+
* 2. Resource server with EVM price parsing
|
|
46
|
+
* 3. SIWx extension for wallet-based sessions
|
|
47
|
+
* 4. Payment-agreement extension for subscription terms
|
|
48
|
+
* 5. Agreement-aware SIWx storage for hybrid access
|
|
49
|
+
*
|
|
50
|
+
* @param config - Stack configuration
|
|
51
|
+
* @param routes - Route configurations for protected endpoints
|
|
52
|
+
* @returns Complete x402 stack
|
|
53
|
+
*/
|
|
54
|
+
export function createX402Stack(config, routes) {
|
|
55
|
+
// 1. Create facilitator signer from wallet+public client
|
|
56
|
+
const combinedClient = config.walletClient.extend(publicActions);
|
|
57
|
+
// Cast needed: viem's verifyTypedData uses strict TypedDataParameter[] types
|
|
58
|
+
// while @x402's FacilitatorEvmSigner uses simplified Record<string, unknown>.
|
|
59
|
+
// Runtime behavior is identical — this is a type-level mismatch only.
|
|
60
|
+
const signer = toFacilitatorEvmSigner(combinedClient);
|
|
61
|
+
// 2. Self-hosted facilitator with EVM exact scheme
|
|
62
|
+
const facilitator = new x402Facilitator();
|
|
63
|
+
registerFacilitatorEvm(facilitator, {
|
|
64
|
+
signer,
|
|
65
|
+
networks: config.network,
|
|
66
|
+
deployERC4337WithEIP6492: true,
|
|
67
|
+
});
|
|
68
|
+
// 3. Local facilitator client (no HTTP round-trips)
|
|
69
|
+
const facilitatorClient = new LocalFacilitatorClient(facilitator);
|
|
70
|
+
// 4. Resource server with EVM scheme
|
|
71
|
+
const server = new x402ResourceServer(facilitatorClient);
|
|
72
|
+
registerServerEvm(server);
|
|
73
|
+
// 5. Register SIWx extension (wallet sessions)
|
|
74
|
+
server.registerExtension(siwxResourceServerExtension);
|
|
75
|
+
// 6. Register payment-agreement extension if configured
|
|
76
|
+
if (config.agreementTerms) {
|
|
77
|
+
server.registerExtension(createPaymentAgreementExtension(config.agreementTerms));
|
|
78
|
+
}
|
|
79
|
+
// 7. Agreement-aware SIWx storage
|
|
80
|
+
const storageConfig = {
|
|
81
|
+
publicClient: config.publicClient,
|
|
82
|
+
servicePayee: config.payTo,
|
|
83
|
+
serviceToken: config.agreementTerms?.token
|
|
84
|
+
? config.agreementTerms.token
|
|
85
|
+
: undefined,
|
|
86
|
+
moduleAddress: config.agreementTerms?.moduleAddress
|
|
87
|
+
? config.agreementTerms.moduleAddress
|
|
88
|
+
: undefined,
|
|
89
|
+
minAgreementAmount: config.agreementTerms?.minAmountPerInterval
|
|
90
|
+
? BigInt(config.agreementTerms.minAmountPerInterval)
|
|
91
|
+
: undefined,
|
|
92
|
+
};
|
|
93
|
+
const storage = new AzethSIWxStorage(storageConfig);
|
|
94
|
+
// 8. SIWx hooks: session recording + request validation
|
|
95
|
+
facilitator.onAfterSettle(createSIWxSettleHook({ storage }));
|
|
96
|
+
// 9. HTTP server wraps resource server + routes
|
|
97
|
+
const httpServer = new x402HTTPResourceServer(server, routes);
|
|
98
|
+
httpServer.onProtectedRequest(createSIWxRequestHook({
|
|
99
|
+
storage,
|
|
100
|
+
verifyOptions: {
|
|
101
|
+
// publicClient.verifyMessage satisfies EVMMessageVerifier —
|
|
102
|
+
// enables EIP-1271 (deployed smart wallets) and EIP-6492 (counterfactual)
|
|
103
|
+
evmVerifier: config.publicClient.verifyMessage,
|
|
104
|
+
},
|
|
105
|
+
}));
|
|
106
|
+
return { facilitator, server, httpServer, storage, publicClient: config.publicClient, walletClient: config.walletClient };
|
|
107
|
+
}
|
|
108
|
+
/** Create a complete x402 stack from environment variables.
|
|
109
|
+
* Returns null if required keys are missing (graceful degradation).
|
|
110
|
+
*
|
|
111
|
+
* Unlike the server's version, this creates its own publicClient
|
|
112
|
+
* directly from the RPC URL — no dependency on external singletons.
|
|
113
|
+
*/
|
|
114
|
+
export function createX402StackFromEnv(routes) {
|
|
115
|
+
const privateKey = process.env['X402_FACILITATOR_KEY'] ?? process.env['DEPLOYER_PRIVATE_KEY'];
|
|
116
|
+
const payTo = process.env['X402_PAY_TO'];
|
|
117
|
+
if (!privateKey || !payTo) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
// Validate address format
|
|
121
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(payTo)) {
|
|
122
|
+
console.error('[AzethProvider] Invalid X402_PAY_TO address format');
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const chainName = (process.env['AZETH_CHAIN'] ?? 'baseSepolia');
|
|
126
|
+
const chain = resolveViemChain(chainName);
|
|
127
|
+
const network = CAIP2_NETWORKS[chainName];
|
|
128
|
+
const rpcUrl = process.env['AZETH_RPC_URL'] ?? process.env['BASE_RPC_URL'];
|
|
129
|
+
let formattedKey = privateKey;
|
|
130
|
+
if (!formattedKey.startsWith('0x')) {
|
|
131
|
+
formattedKey = `0x${formattedKey}`;
|
|
132
|
+
}
|
|
133
|
+
const account = privateKeyToAccount(formattedKey);
|
|
134
|
+
const walletClient = createWalletClient({
|
|
135
|
+
account,
|
|
136
|
+
chain,
|
|
137
|
+
transport: http(rpcUrl),
|
|
138
|
+
});
|
|
139
|
+
// Create publicClient directly — no dependency on external singletons
|
|
140
|
+
const publicClient = createPublicClient({
|
|
141
|
+
chain,
|
|
142
|
+
transport: http(rpcUrl),
|
|
143
|
+
});
|
|
144
|
+
// Build agreement terms from env + contract addresses
|
|
145
|
+
const contracts = AZETH_CONTRACTS[chainName];
|
|
146
|
+
const moduleAddress = contracts?.paymentAgreementModule;
|
|
147
|
+
const usdcAddress = TOKENS[chainName].USDC;
|
|
148
|
+
const agreementTerms = moduleAddress
|
|
149
|
+
? {
|
|
150
|
+
payee: payTo,
|
|
151
|
+
token: usdcAddress,
|
|
152
|
+
moduleAddress: moduleAddress,
|
|
153
|
+
minAmountPerInterval: process.env['X402_AGREEMENT_MIN_AMOUNT'] ?? '10000',
|
|
154
|
+
suggestedInterval: 86400,
|
|
155
|
+
}
|
|
156
|
+
: null;
|
|
157
|
+
return createX402Stack({
|
|
158
|
+
chainName,
|
|
159
|
+
network,
|
|
160
|
+
payTo: payTo,
|
|
161
|
+
walletClient,
|
|
162
|
+
publicClient,
|
|
163
|
+
agreementTerms,
|
|
164
|
+
}, routes);
|
|
165
|
+
}
|
|
166
|
+
// Re-export x402 types so consumers don't need direct @x402/* dependencies
|
|
167
|
+
export { declareSIWxExtension } from '@x402/extensions/sign-in-with-x';
|
|
168
|
+
export { paymentMiddlewareFromHTTPServer } from '@x402/hono';
|
|
169
|
+
//# sourceMappingURL=stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../src/stack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { PublicClient, Chain, Transport } from 'viem';
|
|
2
|
+
import type { SIWxStorage } from '@x402/extensions/sign-in-with-x';
|
|
3
|
+
import type { AgreementKeeper } from './agreement-keeper.js';
|
|
4
|
+
/** Configuration for agreement-aware SIWx storage */
|
|
5
|
+
export interface AzethSIWxStorageConfig {
|
|
6
|
+
/** viem public client for on-chain reads */
|
|
7
|
+
publicClient: PublicClient<Transport, Chain>;
|
|
8
|
+
/** The service's payment recipient address */
|
|
9
|
+
servicePayee: `0x${string}`;
|
|
10
|
+
/** Token address the service accepts (e.g., USDC) */
|
|
11
|
+
serviceToken?: `0x${string}`;
|
|
12
|
+
/** PaymentAgreementModule contract address */
|
|
13
|
+
moduleAddress?: `0x${string}`;
|
|
14
|
+
/** Minimum agreement amount per interval */
|
|
15
|
+
minAgreementAmount?: bigint;
|
|
16
|
+
}
|
|
17
|
+
export declare class AzethSIWxStorage implements SIWxStorage {
|
|
18
|
+
private readonly paymentRecords;
|
|
19
|
+
private readonly usedNonces;
|
|
20
|
+
private readonly config;
|
|
21
|
+
private keeper;
|
|
22
|
+
constructor(config: AzethSIWxStorageConfig);
|
|
23
|
+
/** Inject the agreement keeper after construction.
|
|
24
|
+
* Called from server startup to avoid circular initialization. */
|
|
25
|
+
setKeeper(keeper: AgreementKeeper): void;
|
|
26
|
+
/** Check if an address has paid for a resource.
|
|
27
|
+
*
|
|
28
|
+
* Two-tier lookup:
|
|
29
|
+
* 1. Check in-memory payment records (x402 settlement — permanent grant)
|
|
30
|
+
* 2. Check on-chain agreements (subscription — re-verified every ~60s via cache TTL)
|
|
31
|
+
*
|
|
32
|
+
* Settlement grants (recordPayment) are permanent for the session.
|
|
33
|
+
* Agreement grants are NOT cached permanently — they are re-verified on each
|
|
34
|
+
* call via findActiveAgreementForPayee (which uses a 60s TTL cache internally).
|
|
35
|
+
* This ensures that if a payer's balance drops to zero, their access is revoked
|
|
36
|
+
* within ~60s instead of being permanently granted.
|
|
37
|
+
*/
|
|
38
|
+
hasPaid(resource: string, address: string): Promise<boolean>;
|
|
39
|
+
/** Record that an address has paid for a resource */
|
|
40
|
+
recordPayment(resource: string, address: string): void;
|
|
41
|
+
/** Check if a nonce has been used (replay prevention) */
|
|
42
|
+
hasUsedNonce(nonce: string): boolean;
|
|
43
|
+
/** Record a nonce as used */
|
|
44
|
+
recordNonce(nonce: string): void;
|
|
45
|
+
/** Synchronous payment record helper */
|
|
46
|
+
private recordPaymentSync;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=storage.d.ts.map
|