@armory-sh/base 0.2.27-alpha.23.73 → 0.2.27-alpha.23.76
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/errors.d.ts +10 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +193 -1
- package/dist/payment-requirements.d.ts +22 -0
- package/dist/protocol.d.ts +33 -0
- package/dist/types/wallet.d.ts +24 -0
- package/package.json +1 -1
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class X402ClientError extends Error {
|
|
2
|
+
readonly cause?: unknown;
|
|
3
|
+
constructor(message: string, cause?: unknown);
|
|
4
|
+
}
|
|
5
|
+
export declare class SigningError extends X402ClientError {
|
|
6
|
+
constructor(message: string, cause?: unknown);
|
|
7
|
+
}
|
|
8
|
+
export declare class PaymentException extends X402ClientError {
|
|
9
|
+
constructor(message: string, cause?: unknown);
|
|
10
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { X402_VERSION, SCHEMES, isPaymentPayload, isExactEvmPayload, } from "./t
|
|
|
3
3
|
export { safeBase64Encode, safeBase64Decode, encodePayment, decodePayment, encodeSettlementResponse, decodeSettlementResponse, encodeX402Response, decodeX402Response, detectPaymentVersion, extractPaymentFromHeaders, createPaymentRequiredHeaders, createSettlementHeaders, } from "./encoding/x402";
|
|
4
4
|
export type { PaymentRequiredOptions } from "./encoding/x402";
|
|
5
5
|
export { createNonce, toAtomicUnits, fromAtomicUnits, caip2ToNetwork, networkToCaip2, getCurrentTimestamp, isValidAddress, normalizeAddress, } from "./utils/x402";
|
|
6
|
+
export { encodeUtf8ToBase64, decodeBase64ToUtf8, toBase64Url, normalizeBase64Url, } from "./utils/base64";
|
|
6
7
|
export type { CAIP2Network as CAIP2ChainId, CAIPAssetId, Address, Signature, PayToV2, Extensions, PaymentPayloadV2, PaymentRequirementsV2, SettlementResponseV2, PaymentRequiredV2, ResourceInfo, EIP3009Authorization, SchemePayloadV2, } from "./types/v2";
|
|
7
8
|
export { V2_HEADERS, isCAIP2ChainId, isCAIPAssetId, isAddress, isPaymentRequiredV2, isPaymentPayloadV2, assetIdToAddress, addressToAssetId, parseSignature as parseSignatureV2, combineSignature as combineSignatureV2, } from "./types/v2";
|
|
8
9
|
export type { PaymentPayload, PaymentRequirements, SettlementResponse, PaymentRequired, } from "./types/protocol";
|
|
@@ -22,3 +23,8 @@ export type { NetworkId, TokenId, FacilitatorConfig, FacilitatorVerifyResult, Fa
|
|
|
22
23
|
export type { PaymentRequiredContext, PaymentPayloadContext, HookResult, OnPaymentRequiredHook, BeforePaymentHook, ExtensionHook, HookConfig, HookRegistry, } from "./types/hooks";
|
|
23
24
|
export type { FacilitatorClientConfig, SupportedKind, SupportedResponse, } from "./payment-client";
|
|
24
25
|
export { verifyPayment, settlePayment, getSupported, decodePayloadHeader, extractPayerAddress, } from "./payment-client";
|
|
26
|
+
export { createPaymentRequirements, findRequirementByNetwork, } from "./payment-requirements";
|
|
27
|
+
export type { PaymentConfig, ResolvedRequirementsConfig, } from "./payment-requirements";
|
|
28
|
+
export { X402ClientError, SigningError, PaymentException, } from "./errors";
|
|
29
|
+
export { parseJsonOrBase64, detectX402Version, getPaymentHeaderName, generateNonce, calculateValidBefore, } from "./protocol";
|
|
30
|
+
export type { PaymentWallet } from "./types/wallet";
|
package/dist/index.js
CHANGED
|
@@ -1350,4 +1350,196 @@ function extractPayerAddress(payload) {
|
|
|
1350
1350
|
throw new Error("Unable to extract payer address from payload");
|
|
1351
1351
|
}
|
|
1352
1352
|
|
|
1353
|
-
|
|
1353
|
+
// src/payment-requirements.ts
|
|
1354
|
+
var DEFAULT_NETWORKS = [
|
|
1355
|
+
"ethereum",
|
|
1356
|
+
"base",
|
|
1357
|
+
"base-sepolia",
|
|
1358
|
+
"skale-base",
|
|
1359
|
+
"skale-base-sepolia",
|
|
1360
|
+
"ethereum-sepolia"
|
|
1361
|
+
];
|
|
1362
|
+
var DEFAULT_TOKENS = ["usdc"];
|
|
1363
|
+
var isValidationError2 = (value) => {
|
|
1364
|
+
return typeof value === "object" && value !== null && "code" in value;
|
|
1365
|
+
};
|
|
1366
|
+
function resolvePayTo(config, network, token) {
|
|
1367
|
+
const chainId = network.config.chainId;
|
|
1368
|
+
if (config.payToByToken) {
|
|
1369
|
+
for (const [chainKey, tokenMap] of Object.entries(config.payToByToken)) {
|
|
1370
|
+
const resolvedChain = resolveNetwork(chainKey);
|
|
1371
|
+
if (!isValidationError2(resolvedChain) && resolvedChain.config.chainId === chainId) {
|
|
1372
|
+
for (const [tokenKey2, address] of Object.entries(tokenMap)) {
|
|
1373
|
+
const resolvedToken = resolveToken(tokenKey2, network);
|
|
1374
|
+
if (!isValidationError2(resolvedToken) && resolvedToken.config.contractAddress.toLowerCase() === token.config.contractAddress.toLowerCase()) {
|
|
1375
|
+
return address;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
if (config.payToByChain) {
|
|
1382
|
+
for (const [chainKey, address] of Object.entries(config.payToByChain)) {
|
|
1383
|
+
const resolvedChain = resolveNetwork(chainKey);
|
|
1384
|
+
if (!isValidationError2(resolvedChain) && resolvedChain.config.chainId === chainId) {
|
|
1385
|
+
return address;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
return config.payTo;
|
|
1390
|
+
}
|
|
1391
|
+
function resolveFacilitatorUrl(config, network, token) {
|
|
1392
|
+
const chainId = network.config.chainId;
|
|
1393
|
+
if (config.facilitatorUrlByToken) {
|
|
1394
|
+
for (const [chainKey, tokenMap] of Object.entries(config.facilitatorUrlByToken)) {
|
|
1395
|
+
const resolvedChain = resolveNetwork(chainKey);
|
|
1396
|
+
if (!isValidationError2(resolvedChain) && resolvedChain.config.chainId === chainId) {
|
|
1397
|
+
for (const [tokenKey2, url] of Object.entries(tokenMap)) {
|
|
1398
|
+
const resolvedToken = resolveToken(tokenKey2, network);
|
|
1399
|
+
if (!isValidationError2(resolvedToken) && resolvedToken.config.contractAddress.toLowerCase() === token.config.contractAddress.toLowerCase()) {
|
|
1400
|
+
return url;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
if (config.facilitatorUrlByChain) {
|
|
1407
|
+
for (const [chainKey, url] of Object.entries(config.facilitatorUrlByChain)) {
|
|
1408
|
+
const resolvedChain = resolveNetwork(chainKey);
|
|
1409
|
+
if (!isValidationError2(resolvedChain) && resolvedChain.config.chainId === chainId) {
|
|
1410
|
+
return url;
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
return config.facilitatorUrl;
|
|
1415
|
+
}
|
|
1416
|
+
function resolveNetworks(chainInputs) {
|
|
1417
|
+
const resolvedNetworks = [];
|
|
1418
|
+
const errors = [];
|
|
1419
|
+
const networks = chainInputs?.length ? chainInputs : DEFAULT_NETWORKS;
|
|
1420
|
+
for (const networkId of networks) {
|
|
1421
|
+
const resolved = resolveNetwork(networkId);
|
|
1422
|
+
if (isValidationError2(resolved)) {
|
|
1423
|
+
errors.push(`Network "${networkId}": ${resolved.message}`);
|
|
1424
|
+
} else {
|
|
1425
|
+
resolvedNetworks.push(resolved);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
if (errors.length > 0) {
|
|
1429
|
+
return {
|
|
1430
|
+
networks: resolvedNetworks,
|
|
1431
|
+
error: {
|
|
1432
|
+
code: "VALIDATION_FAILED",
|
|
1433
|
+
message: errors.join("; ")
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
return { networks: resolvedNetworks };
|
|
1438
|
+
}
|
|
1439
|
+
function createPaymentRequirements(config) {
|
|
1440
|
+
const {
|
|
1441
|
+
payTo,
|
|
1442
|
+
chains,
|
|
1443
|
+
chain,
|
|
1444
|
+
tokens,
|
|
1445
|
+
token,
|
|
1446
|
+
amount = "1.0",
|
|
1447
|
+
maxTimeoutSeconds = 300
|
|
1448
|
+
} = config;
|
|
1449
|
+
const chainInputs = chain ? [chain] : chains;
|
|
1450
|
+
const tokenInputs = token ? [token] : tokens;
|
|
1451
|
+
const { networks, error: networksError } = resolveNetworks(chainInputs);
|
|
1452
|
+
if (networksError) {
|
|
1453
|
+
return { requirements: [], error: networksError };
|
|
1454
|
+
}
|
|
1455
|
+
const requirements = [];
|
|
1456
|
+
for (const network of networks) {
|
|
1457
|
+
const tokensToResolve = tokenInputs?.length ? tokenInputs : DEFAULT_TOKENS;
|
|
1458
|
+
for (const tokenId of tokensToResolve) {
|
|
1459
|
+
const resolvedToken = resolveToken(tokenId, network);
|
|
1460
|
+
if (isValidationError2(resolvedToken)) {
|
|
1461
|
+
continue;
|
|
1462
|
+
}
|
|
1463
|
+
const atomicAmount = toAtomicUnits(amount);
|
|
1464
|
+
const tokenConfig = resolvedToken.config;
|
|
1465
|
+
const resolvedPayTo = resolvePayTo(config, network, resolvedToken);
|
|
1466
|
+
resolveFacilitatorUrl(config, network, resolvedToken);
|
|
1467
|
+
const requirement = {
|
|
1468
|
+
scheme: "exact",
|
|
1469
|
+
network: network.caip2,
|
|
1470
|
+
amount: atomicAmount,
|
|
1471
|
+
asset: tokenConfig.contractAddress,
|
|
1472
|
+
payTo: resolvedPayTo,
|
|
1473
|
+
maxTimeoutSeconds,
|
|
1474
|
+
extra: {
|
|
1475
|
+
name: tokenConfig.name,
|
|
1476
|
+
version: tokenConfig.version
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
requirements.push(requirement);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
if (requirements.length === 0) {
|
|
1483
|
+
return {
|
|
1484
|
+
requirements: [],
|
|
1485
|
+
error: {
|
|
1486
|
+
code: "VALIDATION_FAILED",
|
|
1487
|
+
message: "No valid network/token combinations found"
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
return { requirements };
|
|
1492
|
+
}
|
|
1493
|
+
function findRequirementByNetwork(requirements, network) {
|
|
1494
|
+
const normalized = normalizeNetworkName(network);
|
|
1495
|
+
const netConfig = getNetworkConfig(normalized);
|
|
1496
|
+
if (!netConfig) return void 0;
|
|
1497
|
+
return requirements.find((r) => r.network === netConfig.caip2Id);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// src/errors.ts
|
|
1501
|
+
var X402ClientError = class extends Error {
|
|
1502
|
+
cause;
|
|
1503
|
+
constructor(message, cause) {
|
|
1504
|
+
super(message);
|
|
1505
|
+
this.name = "X402ClientError";
|
|
1506
|
+
this.cause = cause;
|
|
1507
|
+
}
|
|
1508
|
+
};
|
|
1509
|
+
var SigningError = class extends X402ClientError {
|
|
1510
|
+
constructor(message, cause) {
|
|
1511
|
+
super(`Signing failed: ${message}`, cause);
|
|
1512
|
+
this.name = "SigningError";
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
var PaymentException = class extends X402ClientError {
|
|
1516
|
+
constructor(message, cause) {
|
|
1517
|
+
super(`Payment failed: ${message}`, cause);
|
|
1518
|
+
this.name = "PaymentException";
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1522
|
+
// src/protocol.ts
|
|
1523
|
+
function parseJsonOrBase64(value) {
|
|
1524
|
+
try {
|
|
1525
|
+
return JSON.parse(value);
|
|
1526
|
+
} catch {
|
|
1527
|
+
const normalized = normalizeBase64Url(value);
|
|
1528
|
+
return JSON.parse(decodeBase64ToUtf8(normalized));
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function detectX402Version(_response) {
|
|
1532
|
+
return 2;
|
|
1533
|
+
}
|
|
1534
|
+
function getPaymentHeaderName(_version) {
|
|
1535
|
+
return V2_HEADERS.PAYMENT_SIGNATURE;
|
|
1536
|
+
}
|
|
1537
|
+
function generateNonce() {
|
|
1538
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1539
|
+
return `0x${(now * 1e3).toString(16).padStart(64, "0")}`;
|
|
1540
|
+
}
|
|
1541
|
+
function calculateValidBefore(expirySeconds = 3600) {
|
|
1542
|
+
return Math.floor(Date.now() / 1e3) + expirySeconds;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
export { EIP712_TYPES, ERC20_ABI, EURC_BASE, NETWORKS, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PAYMENT_SIGNATURE_HEADER, PaymentException, SCHEMES, SKL_SKALE_BASE, SKL_SKALE_BASE_SEPOLIA, SigningError, TOKENS, USDC_BASE, USDC_BASE_SEPOLIA, USDC_DOMAIN, USDC_SKALE_BASE, USDC_SKALE_BASE_SEPOLIA, USDT_SKALE_BASE, USDT_SKALE_BASE_SEPOLIA, V2_HEADERS, WBTC_SKALE_BASE, WBTC_SKALE_BASE_SEPOLIA, WETH_SKALE_BASE, WETH_SKALE_BASE_SEPOLIA, X402ClientError, X402_VERSION, addressToAssetId, assetIdToAddress, caip2ToNetwork, calculateValidBefore, checkFacilitatorSupport, combineSignature as combineSignatureV2, createEIP712Domain, createError, createNonce, createPaymentRequiredHeaders, createPaymentRequirements, createSettlementHeaders, createTransferWithAuthorization, decodeBase64ToUtf8, decodePayloadHeader, decodePayment, decodePaymentV2, decodeSettlementResponse, decodeSettlementV2, decodeX402Response, detectPaymentVersion, detectX402Version, encodePayment, encodePaymentV2, encodeSettlementResponse, encodeSettlementV2, encodeUtf8ToBase64, encodeX402Response, extractPayerAddress, extractPaymentFromHeaders, findMatchingRoute, findRequirementByNetwork, fromAtomicUnits, generateNonce, getAllCustomTokens, getAllTokens, getAvailableNetworks, getAvailableTokens, getCurrentTimestamp, getCustomToken, getEURCTokens, getMainnets, getNetworkByChainId, getNetworkConfig, getPaymentHeaderName, getSKLTokens, getSupported, getTestnets, getToken, getTokensByChain, getTokensBySymbol, getTxHash, getUSDCTokens, getUSDTTokens, getWBTCTokens, getWETHTokens, isAddress, isCAIP2ChainId, isCAIPAssetId, isCustomToken, isExactEvmPayload, isPaymentPayload, isPaymentPayloadV2, isPaymentRequiredV2, isPaymentV2, isResolvedNetwork, isResolvedToken, isSettlementSuccessful, isSettlementV2, isValidAddress, isValidationError, isX402V2Payload, isX402V2PaymentRequired, isX402V2Requirements, isX402V2Settlement, matchRoute, networkToCaip2, normalizeAddress, normalizeBase64Url, normalizeNetworkName, parseJsonOrBase64, parseRoutePattern, parseSignature as parseSignatureV2, registerToken, resolveFacilitator, resolveNetwork, resolveToken, safeBase64Decode, safeBase64Encode, settlePayment, toAtomicUnits, toBase64Url, unregisterToken, validateAcceptConfig, validatePaymentConfig, validateRouteConfig, validateTransferWithAuthorization, verifyPayment };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PaymentRequirementsV2, Address } from "./types/v2";
|
|
2
|
+
import type { NetworkId, TokenId, ValidationError } from "./types/api";
|
|
3
|
+
export interface PaymentConfig {
|
|
4
|
+
payTo: Address | string;
|
|
5
|
+
chains?: NetworkId[];
|
|
6
|
+
chain?: NetworkId;
|
|
7
|
+
tokens?: TokenId[];
|
|
8
|
+
token?: TokenId;
|
|
9
|
+
amount?: string;
|
|
10
|
+
maxTimeoutSeconds?: number;
|
|
11
|
+
payToByChain?: Record<string, Address | string>;
|
|
12
|
+
payToByToken?: Record<string, Record<string, Address | string>>;
|
|
13
|
+
facilitatorUrl?: string;
|
|
14
|
+
facilitatorUrlByChain?: Record<string, string>;
|
|
15
|
+
facilitatorUrlByToken?: Record<string, Record<string, string>>;
|
|
16
|
+
}
|
|
17
|
+
export interface ResolvedRequirementsConfig {
|
|
18
|
+
requirements: PaymentRequirementsV2[];
|
|
19
|
+
error?: ValidationError;
|
|
20
|
+
}
|
|
21
|
+
export declare function createPaymentRequirements(config: PaymentConfig): ResolvedRequirementsConfig;
|
|
22
|
+
export declare function findRequirementByNetwork(requirements: PaymentRequirementsV2[], network: string): PaymentRequirementsV2 | undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X402 Protocol Utilities (V2 Only)
|
|
3
|
+
*
|
|
4
|
+
* Shared protocol utilities for x402 client implementations.
|
|
5
|
+
* These functions are protocol-level and don't depend on wallet libraries.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse JSON or Base64-encoded JSON
|
|
9
|
+
* Handles both raw JSON and Base64URL-encoded JSON
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseJsonOrBase64(value: string): unknown;
|
|
12
|
+
/**
|
|
13
|
+
* Detect x402 protocol version from response
|
|
14
|
+
* V2-only: Always returns 2
|
|
15
|
+
*/
|
|
16
|
+
export declare function detectX402Version(_response: Response): 2;
|
|
17
|
+
/**
|
|
18
|
+
* Get payment header name for protocol version
|
|
19
|
+
* V2-only: Returns PAYMENT-SIGNATURE header name
|
|
20
|
+
*/
|
|
21
|
+
export declare function getPaymentHeaderName(_version: 2): string;
|
|
22
|
+
/**
|
|
23
|
+
* Generate a timestamp-based nonce as hex string
|
|
24
|
+
* Matches Coinbase SDK format: "0x" + 64 hex characters
|
|
25
|
+
* Uses timestamp for reproducibility (vs random)
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateNonce(): `0x${string}`;
|
|
28
|
+
/**
|
|
29
|
+
* Calculate expiry timestamp
|
|
30
|
+
* @param expirySeconds - Seconds from now (default: 3600 = 1 hour)
|
|
31
|
+
* @returns Unix timestamp
|
|
32
|
+
*/
|
|
33
|
+
export declare function calculateValidBefore(expirySeconds?: number): number;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic Wallet Adapter Interface
|
|
3
|
+
*
|
|
4
|
+
* This interface defines the minimum wallet operations required
|
|
5
|
+
* for x402 payment signing. Each client package implements this
|
|
6
|
+
* interface for their specific wallet library (viem, ethers, etc.).
|
|
7
|
+
*/
|
|
8
|
+
export interface PaymentWallet {
|
|
9
|
+
/**
|
|
10
|
+
* Get the wallet address
|
|
11
|
+
* Can be synchronous or asynchronous depending on the wallet library
|
|
12
|
+
*/
|
|
13
|
+
getAddress(): string | Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Sign EIP-712 typed data
|
|
16
|
+
* Used for EIP-3009 TransferWithAuthorization signatures
|
|
17
|
+
*
|
|
18
|
+
* @param domain - EIP-712 domain separator
|
|
19
|
+
* @param types - EIP-712 type definitions
|
|
20
|
+
* @param value - Message to sign
|
|
21
|
+
* @returns Signature as hex string (0x-prefixed)
|
|
22
|
+
*/
|
|
23
|
+
signTypedData(domain: Record<string, unknown>, types: Record<string, unknown>, value: Record<string, unknown>): Promise<string>;
|
|
24
|
+
}
|