@springmint/x402-payment 1.0.1 → 1.0.3
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/README.md +120 -13
- package/SKILL.md +18 -2
- package/dist/cli/{743.index.js → 618.index.js} +442 -236
- package/dist/cli/client.d.ts +19 -0
- package/dist/cli/client.d.ts.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/x402_invoke.js +96 -3
- package/dist/lib/client.d.ts +19 -0
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +45 -0
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export const id =
|
|
2
|
-
export const ids = [
|
|
1
|
+
export const id = 618;
|
|
2
|
+
export const ids = [618];
|
|
3
3
|
export const modules = {
|
|
4
4
|
|
|
5
5
|
/***/ 1491:
|
|
@@ -37689,7 +37689,7 @@ function randomBytes(bytesLength = 32) {
|
|
|
37689
37689
|
|
|
37690
37690
|
/***/ }),
|
|
37691
37691
|
|
|
37692
|
-
/***/
|
|
37692
|
+
/***/ 8618:
|
|
37693
37693
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
37694
37694
|
|
|
37695
37695
|
|
|
@@ -37703,14 +37703,14 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
37703
37703
|
ExactPermitTronClientMechanism: () => (/* reexport */ ExactPermitTronClientMechanism),
|
|
37704
37704
|
ExactTronClientMechanism: () => (/* reexport */ ExactTronClientMechanism),
|
|
37705
37705
|
o6: () => (/* reexport */ InsufficientAllowanceError),
|
|
37706
|
-
uF: () => (/* reexport */ KIND_MAP),
|
|
37707
|
-
N3: () => (/* reexport */ PAYMENT_PERMIT_TYPES),
|
|
37708
37706
|
Px: () => (/* reexport */ config_PAYMENT_REQUIRED_HEADER),
|
|
37709
37707
|
g7: () => (/* reexport */ config_PAYMENT_SIGNATURE_HEADER),
|
|
37708
|
+
gG: () => (/* reexport */ PERMIT402_TYPES),
|
|
37709
|
+
uz: () => (/* reexport */ PTYPE_MAP),
|
|
37710
37710
|
fL: () => (/* reexport */ PermitValidationError),
|
|
37711
|
+
dz: () => (/* reexport */ setting_SCHEMES),
|
|
37711
37712
|
e$: () => (/* reexport */ SignatureCreationError),
|
|
37712
37713
|
SufficientBalancePolicy: () => (/* reexport */ SufficientBalancePolicy),
|
|
37713
|
-
P5: () => (/* reexport */ TRON_RPC_URLS),
|
|
37714
37714
|
KT: () => (/* reexport */ TRON_ZERO_ADDRESS),
|
|
37715
37715
|
qR: () => (/* reexport */ TronAddressConverter),
|
|
37716
37716
|
TronClientSigner: () => (/* reexport */ TronClientSigner),
|
|
@@ -37720,12 +37720,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
37720
37720
|
hV: () => (/* reexport */ encoding_decodePaymentPayload),
|
|
37721
37721
|
Py: () => (/* reexport */ encoding_encodePaymentPayload),
|
|
37722
37722
|
TH: () => (/* reexport */ getChainId),
|
|
37723
|
-
|
|
37724
|
-
|
|
37723
|
+
e5: () => (/* reexport */ getPermit402Address),
|
|
37724
|
+
AB: () => (/* reexport */ resolveRpcUrls),
|
|
37725
37725
|
ld: () => (/* reexport */ toEvmHex)
|
|
37726
37726
|
});
|
|
37727
37727
|
|
|
37728
|
-
// UNUSED EXPORTS: AllowanceError, CHAIN_IDS, CheapestTokenSelectionStrategy, ConfigurationError, DefaultTokenSelectionStrategy, EIP712_DOMAIN_TYPE, ERC20_ABI, EVM_RPC_URLS, Facilitator, FacilitatorFetchError, FacilitatorSettleError, FacilitatorVerifyError, JSON_CONTENT_TYPE, NETWORKS, PAYMENT_ONLY,
|
|
37728
|
+
// UNUSED EXPORTS: AllowanceError, CHAIN_IDS, CheapestTokenSelectionStrategy, ConfigurationError, DefaultTokenSelectionStrategy, EIP712_DOMAIN_TYPE, ERC20_ABI, EVM_RPC_URLS, FACILITATOR_ENDPOINTS, Facilitator, FacilitatorFetchError, FacilitatorSettleError, FacilitatorVerifyError, JSON_CONTENT_TYPE, NETWORKS, PAYMENT_ONLY, PERMIT402_ADDRESSES, PERMIT402_PRIMARY_TYPE, ResourceConfig, ResponseError, SignatureError, TRANSFER_AUTH_EIP712_TYPES, TRANSFER_AUTH_PRIMARY_TYPE, TRON_RPC_URLS, ValidationError, X402Error, X402Middleware, X402Server, ZERO_ADDRESS_HEX, buildEip712Domain, buildEip712Message, bytesToHex, createNonce, createValidityWindow, decodeBase64, decodeBase64ToBytes, decodeJSON, encodeBase64, encodeJSON, findByAddress, getNetworkTokens, getToken, getZeroAddress, hexToBytes, isEvmNetwork, isTronNetwork, paymentIdToBytes, registerToken, resolveRpcUrl, toBase58, x402_protected
|
|
37729
37729
|
|
|
37730
37730
|
// NAMESPACE OBJECT: ./node_modules/tronweb/lib/esm/utils/bytes.js
|
|
37731
37731
|
var bytes_namespaceObject = {};
|
|
@@ -38388,11 +38388,6 @@ class X402Client {
|
|
|
38388
38388
|
*
|
|
38389
38389
|
* Policies are applied in order after mechanism filtering and before token selection.
|
|
38390
38390
|
*/
|
|
38391
|
-
|
|
38392
|
-
function policies_getDecimals(req) {
|
|
38393
|
-
const token = findByAddress(req.network, req.asset);
|
|
38394
|
-
return token?.decimals ?? 6;
|
|
38395
|
-
}
|
|
38396
38391
|
/**
|
|
38397
38392
|
* Policy that filters out requirements with insufficient balance.
|
|
38398
38393
|
*
|
|
@@ -38431,31 +38426,16 @@ class SufficientBalancePolicy {
|
|
|
38431
38426
|
try {
|
|
38432
38427
|
balance = await signer.checkBalance(req.asset, req.network);
|
|
38433
38428
|
}
|
|
38434
|
-
catch {
|
|
38435
|
-
|
|
38436
|
-
affordable.push(req);
|
|
38437
|
-
continue;
|
|
38429
|
+
catch (error) {
|
|
38430
|
+
throw new Error(`Failed to query balance via RPC for ${req.scheme} on ${req.network}: ${error instanceof Error ? error.message : String(error)}`);
|
|
38438
38431
|
}
|
|
38439
38432
|
let needed = BigInt(req.amount);
|
|
38440
38433
|
if (req.extra?.fee?.feeAmount) {
|
|
38441
38434
|
needed += BigInt(req.extra.fee.feeAmount);
|
|
38442
38435
|
}
|
|
38443
|
-
const decimals = policies_getDecimals(req);
|
|
38444
|
-
const token = findByAddress(req.network, req.asset);
|
|
38445
|
-
const symbol = token?.symbol ?? req.asset.slice(0, 8);
|
|
38446
|
-
const divisor = 10 ** decimals;
|
|
38447
|
-
const hBalance = (Number(balance) / divisor).toFixed(decimals);
|
|
38448
|
-
const hNeeded = (Number(needed) / divisor).toFixed(decimals);
|
|
38449
38436
|
if (balance >= needed) {
|
|
38450
|
-
console.log(`[x402] ${symbol} on ${req.network}: balance=${hBalance} >= needed=${hNeeded} (OK)`);
|
|
38451
38437
|
affordable.push(req);
|
|
38452
38438
|
}
|
|
38453
|
-
else {
|
|
38454
|
-
console.log(`[x402] ${symbol} on ${req.network}: balance=${hBalance} < needed=${hNeeded} (skipped)`);
|
|
38455
|
-
}
|
|
38456
|
-
}
|
|
38457
|
-
if (affordable.length === 0) {
|
|
38458
|
-
console.error("[x402] All payment requirements filtered: insufficient balance");
|
|
38459
38439
|
}
|
|
38460
38440
|
return affordable;
|
|
38461
38441
|
}
|
|
@@ -38587,8 +38567,8 @@ function paymentIdToBytes(paymentId) {
|
|
|
38587
38567
|
* ABI and EIP-712 type definitions for x402 protocol
|
|
38588
38568
|
* Shared across all mechanisms
|
|
38589
38569
|
*/
|
|
38590
|
-
/** EIP-712 Primary Type for Permit402
|
|
38591
|
-
const
|
|
38570
|
+
/** EIP-712 Primary Type for Permit402 */
|
|
38571
|
+
const PERMIT402_PRIMARY_TYPE = "Permit402Details";
|
|
38592
38572
|
/**
|
|
38593
38573
|
* EIP-712 Domain Type
|
|
38594
38574
|
* Based on contract: keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)")
|
|
@@ -38601,9 +38581,9 @@ const EIP712_DOMAIN_TYPE = [
|
|
|
38601
38581
|
];
|
|
38602
38582
|
/**
|
|
38603
38583
|
* EIP-712 type definitions for Permit402
|
|
38604
|
-
*
|
|
38584
|
+
* Based on PermitHash.sol from the contract
|
|
38605
38585
|
*/
|
|
38606
|
-
const
|
|
38586
|
+
const PERMIT402_TYPES = {
|
|
38607
38587
|
PermitMeta: [
|
|
38608
38588
|
{ name: "ptype", type: "uint8" },
|
|
38609
38589
|
{ name: "paymentId", type: "bytes16" },
|
|
@@ -38627,8 +38607,8 @@ const PAYMENT_PERMIT_TYPES = {
|
|
|
38627
38607
|
{ name: "fee", type: "Fee" },
|
|
38628
38608
|
],
|
|
38629
38609
|
};
|
|
38630
|
-
/**
|
|
38631
|
-
const
|
|
38610
|
+
/** Ptype mapping for EIP-712 (string to numeric) */
|
|
38611
|
+
const PTYPE_MAP = {
|
|
38632
38612
|
PAYMENT_ONLY: 0,
|
|
38633
38613
|
};
|
|
38634
38614
|
/** ERC20 ABI for allowance/approve calls */
|
|
@@ -38683,18 +38663,18 @@ const NETWORKS = {
|
|
|
38683
38663
|
BSC_MAINNET: "eip155:56",
|
|
38684
38664
|
BSC_TESTNET: "eip155:97",
|
|
38685
38665
|
};
|
|
38686
|
-
/**
|
|
38687
|
-
const
|
|
38688
|
-
"tron:mainnet": "
|
|
38689
|
-
"tron:shasta": "
|
|
38690
|
-
"tron:nile": "
|
|
38691
|
-
"eip155:97": "
|
|
38692
|
-
"eip155:56": "
|
|
38666
|
+
/** Permit402 contract addresses */
|
|
38667
|
+
const PERMIT402_ADDRESSES = {
|
|
38668
|
+
"tron:mainnet": "TK5kfgbNK5B5sFWSbtDs2HyCaSUuEzfN2B",
|
|
38669
|
+
"tron:shasta": "TSNfGRDkyyDY4dHsWzQ6rWWG63p9iczz1k",
|
|
38670
|
+
"tron:nile": "TRK2rYmbyFZKcPTDREEF36rEsLfDWZXnjA",
|
|
38671
|
+
"eip155:97": "",
|
|
38672
|
+
"eip155:56": "0x105a6f4613a1d1c17ef35d4d5f053fa2e659a958",
|
|
38693
38673
|
};
|
|
38694
38674
|
/** Default RPC URLs for EVM networks */
|
|
38695
38675
|
const EVM_RPC_URLS = {
|
|
38696
|
-
"eip155:97": "https://data-seed-prebsc-2-s2.bnbchain.org:8545",
|
|
38697
|
-
"eip155:56": "https://bsc-dataseed.binance.org",
|
|
38676
|
+
"eip155:97": ["https://data-seed-prebsc-2-s2.bnbchain.org:8545", "https://bsc-testnet-rpc.publicnode.com"],
|
|
38677
|
+
"eip155:56": ["https://bsc-dataseed.binance.org", "https://rpc-bsc.48.club"],
|
|
38698
38678
|
// 'eip155:1': 'https://eth.llamarpc.com',
|
|
38699
38679
|
};
|
|
38700
38680
|
/** Default TronGrid hosts for TRON networks */
|
|
@@ -38703,12 +38683,38 @@ const TRON_RPC_URLS = {
|
|
|
38703
38683
|
"tron:shasta": "https://api.shasta.trongrid.io",
|
|
38704
38684
|
"tron:nile": "https://nile.trongrid.io",
|
|
38705
38685
|
};
|
|
38686
|
+
/** Normalize any RPC URL input into a de-duplicated array */
|
|
38687
|
+
function normalizeRpcUrls(input) {
|
|
38688
|
+
if (!input)
|
|
38689
|
+
return [];
|
|
38690
|
+
const values = Array.isArray(input) ? input : [input];
|
|
38691
|
+
const unique = [];
|
|
38692
|
+
for (const value of values) {
|
|
38693
|
+
const url = value.trim();
|
|
38694
|
+
if (!url)
|
|
38695
|
+
continue;
|
|
38696
|
+
if (!unique.includes(url)) {
|
|
38697
|
+
unique.push(url);
|
|
38698
|
+
}
|
|
38699
|
+
}
|
|
38700
|
+
return unique;
|
|
38701
|
+
}
|
|
38702
|
+
/**
|
|
38703
|
+
* Resolve all available RPC URLs for a network.
|
|
38704
|
+
* Priority: caller overrides first, built-in defaults second.
|
|
38705
|
+
*/
|
|
38706
|
+
function resolveRpcUrls(network, overrides) {
|
|
38707
|
+
const customUrls = normalizeRpcUrls(overrides?.[network]);
|
|
38708
|
+
const defaultUrl = EVM_RPC_URLS[network] ?? TRON_RPC_URLS[network];
|
|
38709
|
+
const defaultUrls = normalizeRpcUrls(defaultUrl);
|
|
38710
|
+
return [...customUrls, ...defaultUrls.filter((url) => !customUrls.includes(url))];
|
|
38711
|
+
}
|
|
38706
38712
|
/**
|
|
38707
38713
|
* Resolve a network identifier to an RPC URL.
|
|
38708
38714
|
* Returns the URL from the built-in map, or undefined if not configured.
|
|
38709
38715
|
*/
|
|
38710
38716
|
function resolveRpcUrl(network) {
|
|
38711
|
-
return
|
|
38717
|
+
return resolveRpcUrls(network)[0];
|
|
38712
38718
|
}
|
|
38713
38719
|
/** Zero address for TRON */
|
|
38714
38720
|
const TRON_ZERO_ADDRESS = "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb";
|
|
@@ -38733,10 +38739,10 @@ function getChainId(network) {
|
|
|
38733
38739
|
return chainId;
|
|
38734
38740
|
}
|
|
38735
38741
|
/**
|
|
38736
|
-
* Get
|
|
38742
|
+
* Get Permit402 contract address for network
|
|
38737
38743
|
*/
|
|
38738
|
-
function
|
|
38739
|
-
const addr =
|
|
38744
|
+
function getPermit402Address(network) {
|
|
38745
|
+
const addr = PERMIT402_ADDRESSES[network];
|
|
38740
38746
|
if (addr)
|
|
38741
38747
|
return addr;
|
|
38742
38748
|
// EVM fallback: zero address (not yet deployed)
|
|
@@ -38770,6 +38776,17 @@ const config_PAYMENT_SIGNATURE_HEADER = "PAYMENT-SIGNATURE";
|
|
|
38770
38776
|
const config_PAYMENT_REQUIRED_HEADER = "PAYMENT-REQUIRED";
|
|
38771
38777
|
const config_JSON_CONTENT_TYPE = "application/json";
|
|
38772
38778
|
//# sourceMappingURL=config.js.map
|
|
38779
|
+
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/setting.js
|
|
38780
|
+
// facilitator configure
|
|
38781
|
+
const FACILITATOR_ENDPOINTS = {
|
|
38782
|
+
popular: "https://www.cppay.finance/api/x402/facilitator",
|
|
38783
|
+
};
|
|
38784
|
+
// sheme exact
|
|
38785
|
+
const setting_SCHEMES = {
|
|
38786
|
+
erc3009: "transfer_auth",
|
|
38787
|
+
permit402: "permit402",
|
|
38788
|
+
};
|
|
38789
|
+
//# sourceMappingURL=setting.js.map
|
|
38773
38790
|
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/address.js
|
|
38774
38791
|
/**
|
|
38775
38792
|
* Address conversion utilities for x402 protocol
|
|
@@ -38875,7 +38892,7 @@ function toEvmHex(addr) {
|
|
|
38875
38892
|
return base58ToEvmHex(addr);
|
|
38876
38893
|
}
|
|
38877
38894
|
// Invalid format, return zero address
|
|
38878
|
-
|
|
38895
|
+
// Invalid format, return zero address
|
|
38879
38896
|
return ZERO_ADDRESS_HEX;
|
|
38880
38897
|
}
|
|
38881
38898
|
/**
|
|
@@ -38890,7 +38907,7 @@ function base58ToEvmHex(addr) {
|
|
|
38890
38907
|
for (const char of addr) {
|
|
38891
38908
|
const value = alphabetMap[char];
|
|
38892
38909
|
if (value === undefined) {
|
|
38893
|
-
|
|
38910
|
+
// Invalid Base58 character
|
|
38894
38911
|
return ZERO_ADDRESS_HEX;
|
|
38895
38912
|
}
|
|
38896
38913
|
num = num * BigInt(58) + BigInt(value);
|
|
@@ -39005,12 +39022,6 @@ class X402FetchClient {
|
|
|
39005
39022
|
}
|
|
39006
39023
|
}
|
|
39007
39024
|
//# sourceMappingURL=client.js.map
|
|
39008
|
-
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/setting.js
|
|
39009
|
-
// facilitator configure
|
|
39010
|
-
const FACILITATOR_ENDPOINTS = {
|
|
39011
|
-
popular: "https://www.cppay.finance/api/x402/facilitator",
|
|
39012
|
-
};
|
|
39013
|
-
//# sourceMappingURL=setting.js.map
|
|
39014
39025
|
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/server/facilitator.js
|
|
39015
39026
|
var _a;
|
|
39016
39027
|
|
|
@@ -39028,7 +39039,7 @@ class Facilitator {
|
|
|
39028
39039
|
}
|
|
39029
39040
|
async #request(url, init) {
|
|
39030
39041
|
try {
|
|
39031
|
-
const fullUrl = new URL(
|
|
39042
|
+
const fullUrl = new URL(`${this.endpoint}${url}`);
|
|
39032
39043
|
const response = await fetch(fullUrl, {
|
|
39033
39044
|
...init,
|
|
39034
39045
|
headers: { ...init?.headers, [_a.apikey_header]: this.apikey },
|
|
@@ -39046,10 +39057,23 @@ class Facilitator {
|
|
|
39046
39057
|
}
|
|
39047
39058
|
}
|
|
39048
39059
|
async feeQuote(accepts, context) {
|
|
39049
|
-
|
|
39060
|
+
const response = await this.#request("/fee/quote", {
|
|
39050
39061
|
method: "POST",
|
|
39051
|
-
body: JSON.stringify({ accepts,
|
|
39062
|
+
body: JSON.stringify({ accepts, permit402Context: context }),
|
|
39052
39063
|
});
|
|
39064
|
+
if (response == null) {
|
|
39065
|
+
return [];
|
|
39066
|
+
}
|
|
39067
|
+
if (Array.isArray(response)) {
|
|
39068
|
+
return response;
|
|
39069
|
+
}
|
|
39070
|
+
if (Array.isArray(response.quotes)) {
|
|
39071
|
+
return response.quotes;
|
|
39072
|
+
}
|
|
39073
|
+
if (Array.isArray(response.data)) {
|
|
39074
|
+
return response.data;
|
|
39075
|
+
}
|
|
39076
|
+
throw new FacilitatorFetchError('Request "/fee/quote" failed, invalid response format');
|
|
39053
39077
|
}
|
|
39054
39078
|
async supported() {
|
|
39055
39079
|
return await this.#request("/supported", { method: "GET" });
|
|
@@ -39075,6 +39099,7 @@ var external_node_crypto_ = __webpack_require__(7598);
|
|
|
39075
39099
|
var external_node_crypto_namespaceObject = /*#__PURE__*/__webpack_require__.t(external_node_crypto_, 2);
|
|
39076
39100
|
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/server/x402Server.js
|
|
39077
39101
|
|
|
39102
|
+
|
|
39078
39103
|
const x402Server_PAYMENT_ONLY = "PAYMENT_ONLY";
|
|
39079
39104
|
class x402Server_ResourceConfig {
|
|
39080
39105
|
scheme;
|
|
@@ -39150,13 +39175,16 @@ class X402Server {
|
|
|
39150
39175
|
if (!this.facilitator) {
|
|
39151
39176
|
throw new Error("Facilitator is not set");
|
|
39152
39177
|
}
|
|
39153
|
-
const permitReqs = requirementsList.filter((r) => r.scheme !==
|
|
39154
|
-
const exactReqs = requirementsList.filter((r) => r.scheme ===
|
|
39178
|
+
const permitReqs = requirementsList.filter((r) => r.scheme !== SCHEMES.erc3009);
|
|
39179
|
+
const exactReqs = requirementsList.filter((r) => r.scheme === SCHEMES.erc3009);
|
|
39155
39180
|
const supported = [...exactReqs];
|
|
39156
39181
|
if (permitReqs.length === 0) {
|
|
39157
39182
|
return supported;
|
|
39158
39183
|
}
|
|
39159
39184
|
const feeQuotes = await this.facilitator.feeQuote(permitReqs);
|
|
39185
|
+
if (!Array.isArray(feeQuotes)) {
|
|
39186
|
+
throw new Error("Facilitator feeQuote returned invalid response");
|
|
39187
|
+
}
|
|
39160
39188
|
const quoteMap = new Map();
|
|
39161
39189
|
for (const quote of feeQuotes) {
|
|
39162
39190
|
quoteMap.set(`${quote.scheme}|${quote.network}|${quote.asset}`.toLowerCase(), quote);
|
|
@@ -39172,7 +39200,6 @@ class X402Server {
|
|
|
39172
39200
|
facilitatorId: this.facilitator.facilitatorId,
|
|
39173
39201
|
feeTo: feeQuote.fee.feeTo,
|
|
39174
39202
|
feeAmount: feeQuote.fee.feeAmount,
|
|
39175
|
-
caller: feeQuote.fee.feeTo,
|
|
39176
39203
|
};
|
|
39177
39204
|
supported.push(req);
|
|
39178
39205
|
}
|
|
@@ -39189,9 +39216,9 @@ class X402Server {
|
|
|
39189
39216
|
resource: resourceInfo,
|
|
39190
39217
|
accepts: requirements,
|
|
39191
39218
|
extensions: {
|
|
39192
|
-
|
|
39219
|
+
permit402Context: {
|
|
39193
39220
|
meta: {
|
|
39194
|
-
|
|
39221
|
+
ptype: x402Server_PAYMENT_ONLY,
|
|
39195
39222
|
paymentId: paymentId ?? this.generatePaymentId(),
|
|
39196
39223
|
nonce: nonce ?? this.generateNonce(),
|
|
39197
39224
|
validAfter: validAfter ?? now,
|
|
@@ -39210,7 +39237,7 @@ class X402Server {
|
|
|
39210
39237
|
}
|
|
39211
39238
|
const mechanism = this.findMechanism(requirements.network, requirements.scheme);
|
|
39212
39239
|
if (mechanism?.verifySignature) {
|
|
39213
|
-
const isValid = await mechanism.verifySignature(payload.payload.
|
|
39240
|
+
const isValid = await mechanism.verifySignature(payload.payload.permit402, payload.payload.signature, requirements.network);
|
|
39214
39241
|
if (!isValid) {
|
|
39215
39242
|
return { isValid: false, invalidReason: "invalid_signature_server" };
|
|
39216
39243
|
}
|
|
@@ -39243,7 +39270,7 @@ class X402Server {
|
|
|
39243
39270
|
return networkMechanisms[scheme] ?? null;
|
|
39244
39271
|
}
|
|
39245
39272
|
validatePayloadMatchesRequirements(payload, requirements) {
|
|
39246
|
-
const permit = payload.payload.
|
|
39273
|
+
const permit = payload.payload.permit402;
|
|
39247
39274
|
if (permit.payment.payToken.toLowerCase() !== requirements.asset.toLowerCase()) {
|
|
39248
39275
|
return false;
|
|
39249
39276
|
}
|
|
@@ -39492,13 +39519,13 @@ function x402_protected(server, prices, schemes, network, pay_to, options) {
|
|
|
39492
39519
|
//# sourceMappingURL=index.js.map
|
|
39493
39520
|
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/mechanisms/exact.js
|
|
39494
39521
|
/**
|
|
39495
|
-
* ExactPermitTronClientMechanism - TRON client mechanism for "
|
|
39522
|
+
* ExactPermitTronClientMechanism - TRON client mechanism for "permit402" payment scheme
|
|
39496
39523
|
*
|
|
39497
|
-
* Uses TIP-712 (TRON's EIP-712 implementation) for signing
|
|
39524
|
+
* Uses TIP-712 (TRON's EIP-712 implementation) for signing Permit402.
|
|
39498
39525
|
*/
|
|
39499
39526
|
|
|
39500
39527
|
/**
|
|
39501
|
-
* TRON client mechanism for "
|
|
39528
|
+
* TRON client mechanism for "permit402" payment scheme
|
|
39502
39529
|
*/
|
|
39503
39530
|
class ExactPermitTronClientMechanism {
|
|
39504
39531
|
signer;
|
|
@@ -39510,25 +39537,24 @@ class ExactPermitTronClientMechanism {
|
|
|
39510
39537
|
return this.signer;
|
|
39511
39538
|
}
|
|
39512
39539
|
scheme() {
|
|
39513
|
-
return
|
|
39540
|
+
return setting_SCHEMES.permit402;
|
|
39514
39541
|
}
|
|
39515
39542
|
async createPaymentPayload(requirements, resource, extensions) {
|
|
39516
|
-
const context = extensions?.
|
|
39543
|
+
const context = extensions?.permit402Context;
|
|
39517
39544
|
if (!context) {
|
|
39518
|
-
throw new PermitValidationError("missing_context", "
|
|
39545
|
+
throw new PermitValidationError("missing_context", "permit402Context is required");
|
|
39519
39546
|
}
|
|
39520
39547
|
const buyerAddress = this.signer.getAddress();
|
|
39521
|
-
const zeroAddress = TRON_ZERO_ADDRESS;
|
|
39548
|
+
const zeroAddress = TRON_ZERO_ADDRESS;
|
|
39522
39549
|
const permit = {
|
|
39523
39550
|
meta: {
|
|
39524
|
-
|
|
39551
|
+
ptype: context.meta.ptype,
|
|
39525
39552
|
paymentId: context.meta.paymentId,
|
|
39526
39553
|
nonce: context.meta.nonce,
|
|
39527
39554
|
validAfter: context.meta.validAfter,
|
|
39528
39555
|
validBefore: context.meta.validBefore,
|
|
39529
39556
|
},
|
|
39530
39557
|
buyer: buyerAddress,
|
|
39531
|
-
caller: requirements.extra?.fee?.caller || zeroAddress,
|
|
39532
39558
|
payment: {
|
|
39533
39559
|
payToken: requirements.asset,
|
|
39534
39560
|
payAmount: requirements.amount,
|
|
@@ -39542,19 +39568,18 @@ class ExactPermitTronClientMechanism {
|
|
|
39542
39568
|
// Ensure allowance
|
|
39543
39569
|
const totalAmount = BigInt(permit.payment.payAmount) + BigInt(permit.fee.feeAmount);
|
|
39544
39570
|
await this.signer.ensureAllowance(permit.payment.payToken, totalAmount, requirements.network);
|
|
39545
|
-
// Build EIP-712 domain
|
|
39546
|
-
const permitAddress =
|
|
39571
|
+
// Build EIP-712 domain (no version field per contract spec)
|
|
39572
|
+
const permitAddress = getPermit402Address(requirements.network);
|
|
39547
39573
|
const domain = {
|
|
39548
39574
|
name: "Permit402",
|
|
39549
39575
|
chainId: getChainId(requirements.network),
|
|
39550
39576
|
verifyingContract: this.addressConverter.toEvmFormat(permitAddress),
|
|
39551
39577
|
};
|
|
39552
|
-
// Convert permit to EIP-712 format
|
|
39553
|
-
const ptype = KIND_MAP[permit.meta.kind] ?? 0;
|
|
39578
|
+
// Convert permit to EIP-712 compatible format
|
|
39554
39579
|
const permitForSigning = {
|
|
39555
39580
|
meta: {
|
|
39556
|
-
ptype,
|
|
39557
|
-
paymentId: permit.meta.paymentId
|
|
39581
|
+
ptype: PTYPE_MAP[permit.meta.ptype],
|
|
39582
|
+
paymentId: permit.meta.paymentId,
|
|
39558
39583
|
nonce: BigInt(permit.meta.nonce),
|
|
39559
39584
|
validAfter: BigInt(permit.meta.validAfter),
|
|
39560
39585
|
validBefore: BigInt(permit.meta.validBefore),
|
|
@@ -39570,29 +39595,14 @@ class ExactPermitTronClientMechanism {
|
|
|
39570
39595
|
feeAmount: BigInt(permit.fee.feeAmount),
|
|
39571
39596
|
},
|
|
39572
39597
|
};
|
|
39573
|
-
|
|
39574
|
-
console.log("[SIGN] Domain:", JSON.stringify(domain));
|
|
39575
|
-
console.log("[SIGN] Message:", JSON.stringify(permitForSigning, (key, value) => {
|
|
39576
|
-
if (value instanceof Uint8Array) {
|
|
39577
|
-
return ("0x" +
|
|
39578
|
-
Array.from(value)
|
|
39579
|
-
.map((b) => b.toString(16).padStart(2, "0"))
|
|
39580
|
-
.join(""));
|
|
39581
|
-
}
|
|
39582
|
-
if (typeof value === "bigint") {
|
|
39583
|
-
return value.toString();
|
|
39584
|
-
}
|
|
39585
|
-
return value;
|
|
39586
|
-
}));
|
|
39587
|
-
const signature = await this.signer.signTypedData(domain, PAYMENT_PERMIT_TYPES, permitForSigning);
|
|
39588
|
-
console.log("[SIGN] Signature:", signature);
|
|
39598
|
+
const signature = await this.signer.signTypedData(domain, PERMIT402_TYPES, permitForSigning);
|
|
39589
39599
|
return {
|
|
39590
39600
|
x402Version: 2,
|
|
39591
39601
|
resource: { url: resource },
|
|
39592
39602
|
accepted: requirements,
|
|
39593
39603
|
payload: {
|
|
39594
39604
|
signature,
|
|
39595
|
-
|
|
39605
|
+
permit402: permit,
|
|
39596
39606
|
},
|
|
39597
39607
|
extensions: {},
|
|
39598
39608
|
};
|
|
@@ -39601,11 +39611,11 @@ class ExactPermitTronClientMechanism {
|
|
|
39601
39611
|
//# sourceMappingURL=exact.js.map
|
|
39602
39612
|
;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/mechanisms/exactEvm.js
|
|
39603
39613
|
/**
|
|
39604
|
-
* ExactPermitEvmClientMechanism - EVM client mechanism for "
|
|
39614
|
+
* ExactPermitEvmClientMechanism - EVM client mechanism for "permit402" payment scheme
|
|
39605
39615
|
*/
|
|
39606
39616
|
|
|
39607
39617
|
/**
|
|
39608
|
-
* EVM client mechanism for "
|
|
39618
|
+
* EVM client mechanism for "permit402" payment scheme
|
|
39609
39619
|
*/
|
|
39610
39620
|
class ExactPermitEvmClientMechanism {
|
|
39611
39621
|
signer;
|
|
@@ -39617,25 +39627,24 @@ class ExactPermitEvmClientMechanism {
|
|
|
39617
39627
|
return this.signer;
|
|
39618
39628
|
}
|
|
39619
39629
|
scheme() {
|
|
39620
|
-
return
|
|
39630
|
+
return setting_SCHEMES.permit402;
|
|
39621
39631
|
}
|
|
39622
39632
|
async createPaymentPayload(requirements, resource, extensions) {
|
|
39623
|
-
const context = extensions?.
|
|
39633
|
+
const context = extensions?.permit402Context;
|
|
39624
39634
|
if (!context) {
|
|
39625
|
-
throw new PermitValidationError("missing_context", "
|
|
39635
|
+
throw new PermitValidationError("missing_context", "permit402Context is required");
|
|
39626
39636
|
}
|
|
39627
39637
|
const buyerAddress = this.signer.getAddress();
|
|
39628
39638
|
const zeroAddress = EVM_ZERO_ADDRESS;
|
|
39629
39639
|
const permit = {
|
|
39630
39640
|
meta: {
|
|
39631
|
-
|
|
39641
|
+
ptype: context.meta.ptype,
|
|
39632
39642
|
paymentId: context.meta.paymentId,
|
|
39633
39643
|
nonce: context.meta.nonce,
|
|
39634
39644
|
validAfter: context.meta.validAfter,
|
|
39635
39645
|
validBefore: context.meta.validBefore,
|
|
39636
39646
|
},
|
|
39637
39647
|
buyer: buyerAddress,
|
|
39638
|
-
caller: requirements.extra?.fee?.caller || zeroAddress,
|
|
39639
39648
|
payment: {
|
|
39640
39649
|
payToken: requirements.asset,
|
|
39641
39650
|
payAmount: requirements.amount,
|
|
@@ -39649,22 +39658,22 @@ class ExactPermitEvmClientMechanism {
|
|
|
39649
39658
|
// Ensure allowance
|
|
39650
39659
|
const totalAmount = BigInt(permit.payment.payAmount) + BigInt(permit.fee.feeAmount);
|
|
39651
39660
|
await this.signer.ensureAllowance(permit.payment.payToken, totalAmount, requirements.network);
|
|
39652
|
-
// Build EIP-712 domain
|
|
39653
|
-
const permitAddress =
|
|
39661
|
+
// Build EIP-712 domain
|
|
39662
|
+
const permitAddress = getPermit402Address(requirements.network);
|
|
39654
39663
|
const domain = {
|
|
39655
39664
|
name: "Permit402",
|
|
39656
39665
|
chainId: getChainId(requirements.network),
|
|
39657
39666
|
verifyingContract: this.addressConverter.toEvmFormat(permitAddress),
|
|
39658
39667
|
};
|
|
39659
39668
|
// Convert permit to EIP-712 format matching Permit402Details (meta, buyer, payment, fee - no caller)
|
|
39660
|
-
const ptype = KIND_MAP[permit.meta.kind] ?? 0;
|
|
39661
|
-
const paymentIdBytes = permit.meta.paymentId.startsWith("0x")
|
|
39662
|
-
|
|
39663
|
-
|
|
39669
|
+
// const ptype = KIND_MAP[permit.meta.kind] ?? 0;
|
|
39670
|
+
// const paymentIdBytes = permit.meta.paymentId.startsWith("0x")
|
|
39671
|
+
// ? permit.meta.paymentId
|
|
39672
|
+
// : `0x${permit.meta.paymentId}`;
|
|
39664
39673
|
const permitForSigning = {
|
|
39665
39674
|
meta: {
|
|
39666
|
-
ptype,
|
|
39667
|
-
paymentId:
|
|
39675
|
+
ptype: PTYPE_MAP[permit.meta.ptype],
|
|
39676
|
+
paymentId: permit.meta.paymentId,
|
|
39668
39677
|
nonce: BigInt(permit.meta.nonce),
|
|
39669
39678
|
validAfter: BigInt(permit.meta.validAfter),
|
|
39670
39679
|
validBefore: BigInt(permit.meta.validBefore),
|
|
@@ -39680,14 +39689,14 @@ class ExactPermitEvmClientMechanism {
|
|
|
39680
39689
|
feeAmount: BigInt(permit.fee.feeAmount),
|
|
39681
39690
|
},
|
|
39682
39691
|
};
|
|
39683
|
-
const signature = await this.signer.signTypedData(domain,
|
|
39692
|
+
const signature = await this.signer.signTypedData(domain, PERMIT402_TYPES, permitForSigning);
|
|
39684
39693
|
return {
|
|
39685
39694
|
x402Version: 2,
|
|
39686
39695
|
resource: { url: resource },
|
|
39687
39696
|
accepted: requirements,
|
|
39688
39697
|
payload: {
|
|
39689
39698
|
signature,
|
|
39690
|
-
|
|
39699
|
+
permit402: permit,
|
|
39691
39700
|
},
|
|
39692
39701
|
extensions: {},
|
|
39693
39702
|
};
|
|
@@ -39699,15 +39708,13 @@ class ExactPermitEvmClientMechanism {
|
|
|
39699
39708
|
* Shared types and helpers for transfer_auth mechanism.
|
|
39700
39709
|
*
|
|
39701
39710
|
* transfer_auth uses ERC-3009 TransferWithAuthorization for direct token transfers
|
|
39702
|
-
* without going through a
|
|
39711
|
+
* without going through a Permit402 contract.
|
|
39703
39712
|
*/
|
|
39704
|
-
/** Scheme name */
|
|
39705
|
-
const SCHEME_EXACT = "transfer_auth";
|
|
39706
39713
|
/** Default validity period (1 hour) */
|
|
39707
39714
|
const DEFAULT_VALIDITY_SECONDS = 3600;
|
|
39708
39715
|
/**
|
|
39709
39716
|
* EIP-712 type definitions for TransferWithAuthorization
|
|
39710
|
-
* Note: domain includes "version" field (unlike
|
|
39717
|
+
* Note: domain includes "version" field (unlike Permit402)
|
|
39711
39718
|
*/
|
|
39712
39719
|
const TRANSFER_AUTH_EIP712_TYPES = {
|
|
39713
39720
|
TransferWithAuthorization: [
|
|
@@ -39787,7 +39794,7 @@ class ExactTronClientMechanism {
|
|
|
39787
39794
|
return this.signer;
|
|
39788
39795
|
}
|
|
39789
39796
|
scheme() {
|
|
39790
|
-
return
|
|
39797
|
+
return setting_SCHEMES.erc3009;
|
|
39791
39798
|
}
|
|
39792
39799
|
async createPaymentPayload(requirements, resource) {
|
|
39793
39800
|
const converter = this.addressConverter;
|
|
@@ -39817,7 +39824,7 @@ class ExactTronClientMechanism {
|
|
|
39817
39824
|
accepted: requirements,
|
|
39818
39825
|
payload: {
|
|
39819
39826
|
signature,
|
|
39820
|
-
|
|
39827
|
+
permit402: undefined,
|
|
39821
39828
|
},
|
|
39822
39829
|
extensions: {
|
|
39823
39830
|
transferAuthorization: authorization,
|
|
@@ -39849,7 +39856,7 @@ class ExactEvmClientMechanism {
|
|
|
39849
39856
|
return this.signer;
|
|
39850
39857
|
}
|
|
39851
39858
|
scheme() {
|
|
39852
|
-
return
|
|
39859
|
+
return setting_SCHEMES.erc3009;
|
|
39853
39860
|
}
|
|
39854
39861
|
async createPaymentPayload(requirements, resource) {
|
|
39855
39862
|
const converter = this.addressConverter;
|
|
@@ -39879,7 +39886,7 @@ class ExactEvmClientMechanism {
|
|
|
39879
39886
|
accepted: requirements,
|
|
39880
39887
|
payload: {
|
|
39881
39888
|
signature,
|
|
39882
|
-
|
|
39889
|
+
permit402: undefined,
|
|
39883
39890
|
},
|
|
39884
39891
|
extensions: {
|
|
39885
39892
|
transferAuthorization: authorization,
|
|
@@ -39892,7 +39899,7 @@ class ExactEvmClientMechanism {
|
|
|
39892
39899
|
/**
|
|
39893
39900
|
* x402 Client Mechanisms
|
|
39894
39901
|
*/
|
|
39895
|
-
//
|
|
39902
|
+
// permit402 scheme
|
|
39896
39903
|
|
|
39897
39904
|
|
|
39898
39905
|
// exact scheme
|
|
@@ -75010,37 +75017,73 @@ class TronClientSigner {
|
|
|
75010
75017
|
privateKey;
|
|
75011
75018
|
address; // Base58 format
|
|
75012
75019
|
tronWebInstances = new Map();
|
|
75013
|
-
|
|
75020
|
+
rpcUrl;
|
|
75021
|
+
rpcUrls;
|
|
75022
|
+
rpcByNetwork;
|
|
75023
|
+
constructor(privateKey, options) {
|
|
75014
75024
|
const cleanKey = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
|
|
75015
75025
|
this.privateKey = cleanKey;
|
|
75026
|
+
this.rpcUrl = options?.rpcUrl;
|
|
75027
|
+
this.rpcUrls = options?.rpcUrls;
|
|
75028
|
+
this.rpcByNetwork = options?.rpcByNetwork;
|
|
75016
75029
|
// Derive address using a temporary TronWeb instance (pure crypto, no network needed)
|
|
75017
|
-
const tw = this.
|
|
75030
|
+
const tw = this.getDefaultTronWeb();
|
|
75018
75031
|
this.address = tw.address.fromPrivateKey(cleanKey);
|
|
75019
75032
|
}
|
|
75020
75033
|
/**
|
|
75021
75034
|
* Get or create a TronWeb instance for the given network.
|
|
75022
75035
|
*/
|
|
75023
75036
|
getTronWeb(network) {
|
|
75024
|
-
const host = network
|
|
75025
|
-
|
|
75026
|
-
|
|
75027
|
-
if (!tw) {
|
|
75028
|
-
if (!host) {
|
|
75029
|
-
throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
|
|
75030
|
-
}
|
|
75031
|
-
tw = this.createTronWeb(host);
|
|
75032
|
-
this.tronWebInstances.set(key, tw);
|
|
75037
|
+
const host = this.getRpcCandidates(network)[0];
|
|
75038
|
+
if (!host) {
|
|
75039
|
+
throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
|
|
75033
75040
|
}
|
|
75034
|
-
return
|
|
75041
|
+
return this.getOrCreateTronWeb(host);
|
|
75035
75042
|
}
|
|
75036
75043
|
getDefaultTronWeb() {
|
|
75037
|
-
|
|
75044
|
+
const host = this.getRpcCandidates("tron:nile")[0] ?? "https://nile.trongrid.io";
|
|
75045
|
+
return this.getOrCreateTronWeb(host);
|
|
75046
|
+
}
|
|
75047
|
+
getOrCreateTronWeb(host) {
|
|
75048
|
+
let tw = this.tronWebInstances.get(host);
|
|
75038
75049
|
if (!tw) {
|
|
75039
|
-
tw = this.createTronWeb(
|
|
75040
|
-
this.tronWebInstances.set(
|
|
75050
|
+
tw = this.createTronWeb(host);
|
|
75051
|
+
this.tronWebInstances.set(host, tw);
|
|
75041
75052
|
}
|
|
75042
75053
|
return tw;
|
|
75043
75054
|
}
|
|
75055
|
+
getRpcCandidates(network) {
|
|
75056
|
+
if (!network) {
|
|
75057
|
+
const global = this.rpcUrls?.length ? this.rpcUrls : this.rpcUrl ? [this.rpcUrl] : [];
|
|
75058
|
+
const deduped = global.filter((url, index) => global.indexOf(url) === index);
|
|
75059
|
+
return deduped.length > 0 ? deduped : ["https://nile.trongrid.io"];
|
|
75060
|
+
}
|
|
75061
|
+
const perNetwork = this.rpcByNetwork?.[network];
|
|
75062
|
+
const perNetworkList = Array.isArray(perNetwork) ? perNetwork : perNetwork ? [perNetwork] : [];
|
|
75063
|
+
const globalList = this.rpcUrls?.length ? this.rpcUrls : this.rpcUrl ? [this.rpcUrl] : [];
|
|
75064
|
+
const overrides = {
|
|
75065
|
+
...(this.rpcByNetwork ?? {}),
|
|
75066
|
+
[network]: [...perNetworkList, ...globalList],
|
|
75067
|
+
};
|
|
75068
|
+
return resolveRpcUrls(network, overrides);
|
|
75069
|
+
}
|
|
75070
|
+
async executeWithRpcFallback(network, action) {
|
|
75071
|
+
const candidates = this.getRpcCandidates(network);
|
|
75072
|
+
if (candidates.length === 0) {
|
|
75073
|
+
throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
|
|
75074
|
+
}
|
|
75075
|
+
let lastError;
|
|
75076
|
+
for (const host of candidates) {
|
|
75077
|
+
const tw = this.getOrCreateTronWeb(host);
|
|
75078
|
+
try {
|
|
75079
|
+
return await action(tw);
|
|
75080
|
+
}
|
|
75081
|
+
catch (error) {
|
|
75082
|
+
lastError = error;
|
|
75083
|
+
}
|
|
75084
|
+
}
|
|
75085
|
+
throw new Error(`All RPC endpoints failed for ${network}: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
75086
|
+
}
|
|
75044
75087
|
createTronWeb(fullHost) {
|
|
75045
75088
|
const apiKey = typeof process !== "undefined" ? process.env?.TRON_GRID_API_KEY : undefined;
|
|
75046
75089
|
const headers = apiKey ? { "TRON-PRO-API-KEY": apiKey } : undefined;
|
|
@@ -75080,25 +75123,20 @@ class TronClientSigner {
|
|
|
75080
75123
|
return signFn.call(tw.trx, typedDomain, types, message, this.privateKey);
|
|
75081
75124
|
}
|
|
75082
75125
|
async checkBalance(token, network) {
|
|
75083
|
-
|
|
75084
|
-
|
|
75085
|
-
const tw = this.getTronWeb(network);
|
|
75126
|
+
const ownerHex = toEvmHex(this.address);
|
|
75127
|
+
return this.executeWithRpcFallback(network, async (tw) => {
|
|
75086
75128
|
const result = await tw.transactionBuilder.triggerConstantContract(token, "balanceOf(address)", {}, [{ type: "address", value: ownerHex }], this.address);
|
|
75087
75129
|
if (result.result?.result && result.constant_result?.length) {
|
|
75088
75130
|
return BigInt("0x" + result.constant_result[0]);
|
|
75089
75131
|
}
|
|
75090
|
-
|
|
75091
|
-
|
|
75092
|
-
console.error(`[TronClientSigner] Failed to check balance: ${error}`);
|
|
75093
|
-
}
|
|
75094
|
-
return BigInt(0);
|
|
75132
|
+
throw new Error(`checkBalance failed for ${token} on ${network}: no result from RPC`);
|
|
75133
|
+
});
|
|
75095
75134
|
}
|
|
75096
75135
|
async checkAllowance(token, _amount, network) {
|
|
75097
|
-
const spender =
|
|
75098
|
-
|
|
75099
|
-
|
|
75100
|
-
|
|
75101
|
-
const tw = this.getTronWeb(network);
|
|
75136
|
+
const spender = getPermit402Address(network);
|
|
75137
|
+
const ownerHex = toEvmHex(this.address);
|
|
75138
|
+
const spenderHex = toEvmHex(spender);
|
|
75139
|
+
return this.executeWithRpcFallback(network, async (tw) => {
|
|
75102
75140
|
const result = await tw.transactionBuilder.triggerConstantContract(token, ERC20_ALLOWANCE_SELECTOR, {}, [
|
|
75103
75141
|
{ type: "address", value: ownerHex },
|
|
75104
75142
|
{ type: "address", value: spenderHex },
|
|
@@ -75106,11 +75144,8 @@ class TronClientSigner {
|
|
|
75106
75144
|
if (result.result?.result && result.constant_result?.length) {
|
|
75107
75145
|
return BigInt("0x" + result.constant_result[0]);
|
|
75108
75146
|
}
|
|
75109
|
-
|
|
75110
|
-
|
|
75111
|
-
console.error(`[TronClientSigner] Failed to check allowance: ${error}`);
|
|
75112
|
-
}
|
|
75113
|
-
return BigInt(0);
|
|
75147
|
+
throw new Error(`checkAllowance failed for ${token} on ${network}: no result from RPC`);
|
|
75148
|
+
});
|
|
75114
75149
|
}
|
|
75115
75150
|
async ensureAllowance(token, amount, network, mode = "auto") {
|
|
75116
75151
|
if (mode === "skip") {
|
|
@@ -75118,57 +75153,58 @@ class TronClientSigner {
|
|
|
75118
75153
|
}
|
|
75119
75154
|
const currentAllowance = await this.checkAllowance(token, amount, network);
|
|
75120
75155
|
if (currentAllowance >= amount) {
|
|
75121
|
-
console.log(`[ALLOWANCE] Sufficient allowance: ${currentAllowance} >= ${amount}`);
|
|
75122
75156
|
return true;
|
|
75123
75157
|
}
|
|
75124
75158
|
if (mode === "interactive") {
|
|
75125
75159
|
throw new InsufficientAllowanceError("Interactive approval not implemented - use wallet UI");
|
|
75126
75160
|
}
|
|
75127
75161
|
// Auto mode: send approve transaction
|
|
75128
|
-
|
|
75129
|
-
const spender = getPaymentPermitAddress(network);
|
|
75162
|
+
const spender = getPermit402Address(network);
|
|
75130
75163
|
const spenderHex = toEvmHex(spender);
|
|
75131
75164
|
// Use maxUint160 (2^160 - 1) to avoid repeated approvals
|
|
75132
75165
|
const maxUint160 = BigInt(2) ** BigInt(160) - BigInt(1);
|
|
75133
75166
|
try {
|
|
75134
|
-
|
|
75135
|
-
|
|
75136
|
-
|
|
75137
|
-
|
|
75138
|
-
|
|
75139
|
-
|
|
75140
|
-
|
|
75141
|
-
|
|
75142
|
-
|
|
75143
|
-
|
|
75144
|
-
|
|
75145
|
-
}
|
|
75146
|
-
// Sign transaction
|
|
75147
|
-
const signedTx = await tw.trx.sign(tx.transaction, this.privateKey);
|
|
75148
|
-
// Broadcast transaction
|
|
75149
|
-
const broadcast = await tw.trx.sendRawTransaction(signedTx);
|
|
75150
|
-
if (!broadcast.result) {
|
|
75151
|
-
throw new InsufficientAllowanceError(`Failed to broadcast approve transaction: ${JSON.stringify(broadcast)}`);
|
|
75152
|
-
}
|
|
75153
|
-
console.log(`[ALLOWANCE] Approve transaction sent: ${broadcast.txid}`);
|
|
75154
|
-
// Wait for confirmation (poll for ~30 seconds)
|
|
75155
|
-
const txid = broadcast.txid;
|
|
75156
|
-
for (let i = 0; i < 10; i++) {
|
|
75157
|
-
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
75158
|
-
try {
|
|
75159
|
-
const info = await tw.trx.getTransactionInfo(txid);
|
|
75160
|
-
if (info && info.blockNumber) {
|
|
75161
|
-
const success = info.receipt?.result === "SUCCESS";
|
|
75162
|
-
console.log(`[ALLOWANCE] Approve confirmed: ${success ? "SUCCESS" : "FAILED"}`);
|
|
75163
|
-
return success;
|
|
75164
|
-
}
|
|
75167
|
+
return await this.executeWithRpcFallback(network, async (tw) => {
|
|
75168
|
+
// Build approve transaction
|
|
75169
|
+
const tx = await tw.transactionBuilder.triggerSmartContract(token, ERC20_APPROVE_SELECTOR, {
|
|
75170
|
+
feeLimit: 100_000_000,
|
|
75171
|
+
callValue: 0,
|
|
75172
|
+
}, [
|
|
75173
|
+
{ type: "address", value: spenderHex },
|
|
75174
|
+
{ type: "uint256", value: maxUint160.toString() },
|
|
75175
|
+
], this.address);
|
|
75176
|
+
if (!tx.result?.result) {
|
|
75177
|
+
throw new InsufficientAllowanceError("Failed to build approve transaction");
|
|
75165
75178
|
}
|
|
75166
|
-
|
|
75167
|
-
|
|
75179
|
+
// Sign transaction
|
|
75180
|
+
const signedTx = await tw.trx.sign(tx.transaction, this.privateKey);
|
|
75181
|
+
// Broadcast transaction
|
|
75182
|
+
const broadcast = await tw.trx.sendRawTransaction(signedTx);
|
|
75183
|
+
if (!broadcast.result) {
|
|
75184
|
+
throw new InsufficientAllowanceError(`Failed to broadcast approve transaction: ${JSON.stringify(broadcast)}`);
|
|
75168
75185
|
}
|
|
75169
|
-
|
|
75170
|
-
|
|
75171
|
-
|
|
75186
|
+
// Wait for confirmation (poll for ~30 seconds)
|
|
75187
|
+
const txid = broadcast.txid;
|
|
75188
|
+
for (let i = 0; i < 10; i++) {
|
|
75189
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
75190
|
+
try {
|
|
75191
|
+
const info = await tw.trx.getTransactionInfo(txid);
|
|
75192
|
+
if (info && info.blockNumber) {
|
|
75193
|
+
if (info.receipt?.result === "SUCCESS") {
|
|
75194
|
+
return true;
|
|
75195
|
+
}
|
|
75196
|
+
throw new InsufficientAllowanceError(`Approve transaction failed on-chain for tx ${txid}: ${info.receipt?.result ?? "UNKNOWN"}`);
|
|
75197
|
+
}
|
|
75198
|
+
}
|
|
75199
|
+
catch (error) {
|
|
75200
|
+
if (error instanceof InsufficientAllowanceError) {
|
|
75201
|
+
throw error;
|
|
75202
|
+
}
|
|
75203
|
+
// Not confirmed yet, continue polling
|
|
75204
|
+
}
|
|
75205
|
+
}
|
|
75206
|
+
throw new InsufficientAllowanceError(`Approve transaction not confirmed within timeout: ${txid}`);
|
|
75207
|
+
});
|
|
75172
75208
|
}
|
|
75173
75209
|
catch (error) {
|
|
75174
75210
|
if (error instanceof InsufficientAllowanceError)
|
|
@@ -90471,6 +90507,167 @@ function createPublicClient(parameters) {
|
|
|
90471
90507
|
return client.extend(publicActions);
|
|
90472
90508
|
}
|
|
90473
90509
|
//# sourceMappingURL=createPublicClient.js.map
|
|
90510
|
+
;// CONCATENATED MODULE: ./node_modules/viem/_esm/clients/transports/fallback.js
|
|
90511
|
+
|
|
90512
|
+
|
|
90513
|
+
|
|
90514
|
+
|
|
90515
|
+
function fallback(transports_, config = {}) {
|
|
90516
|
+
const { key = 'fallback', name = 'Fallback', rank = false, shouldThrow: shouldThrow_ = shouldThrow, retryCount, retryDelay, } = config;
|
|
90517
|
+
return (({ chain, pollingInterval = 4_000, timeout, ...rest }) => {
|
|
90518
|
+
let transports = transports_;
|
|
90519
|
+
let onResponse = () => { };
|
|
90520
|
+
const transport = createTransport({
|
|
90521
|
+
key,
|
|
90522
|
+
name,
|
|
90523
|
+
async request({ method, params }) {
|
|
90524
|
+
let includes;
|
|
90525
|
+
const fetch = async (i = 0) => {
|
|
90526
|
+
const transport = transports[i]({
|
|
90527
|
+
...rest,
|
|
90528
|
+
chain,
|
|
90529
|
+
retryCount: 0,
|
|
90530
|
+
timeout,
|
|
90531
|
+
});
|
|
90532
|
+
try {
|
|
90533
|
+
const response = await transport.request({
|
|
90534
|
+
method,
|
|
90535
|
+
params,
|
|
90536
|
+
});
|
|
90537
|
+
onResponse({
|
|
90538
|
+
method,
|
|
90539
|
+
params: params,
|
|
90540
|
+
response,
|
|
90541
|
+
transport,
|
|
90542
|
+
status: 'success',
|
|
90543
|
+
});
|
|
90544
|
+
return response;
|
|
90545
|
+
}
|
|
90546
|
+
catch (err) {
|
|
90547
|
+
onResponse({
|
|
90548
|
+
error: err,
|
|
90549
|
+
method,
|
|
90550
|
+
params: params,
|
|
90551
|
+
transport,
|
|
90552
|
+
status: 'error',
|
|
90553
|
+
});
|
|
90554
|
+
if (shouldThrow_(err))
|
|
90555
|
+
throw err;
|
|
90556
|
+
// If we've reached the end of the fallbacks, throw the error.
|
|
90557
|
+
if (i === transports.length - 1)
|
|
90558
|
+
throw err;
|
|
90559
|
+
// Check if at least one other transport includes the method
|
|
90560
|
+
includes ??= transports.slice(i + 1).some((transport) => {
|
|
90561
|
+
const { include, exclude } = transport({ chain }).config.methods || {};
|
|
90562
|
+
if (include)
|
|
90563
|
+
return include.includes(method);
|
|
90564
|
+
if (exclude)
|
|
90565
|
+
return !exclude.includes(method);
|
|
90566
|
+
return true;
|
|
90567
|
+
});
|
|
90568
|
+
if (!includes)
|
|
90569
|
+
throw err;
|
|
90570
|
+
// Otherwise, try the next fallback.
|
|
90571
|
+
return fetch(i + 1);
|
|
90572
|
+
}
|
|
90573
|
+
};
|
|
90574
|
+
return fetch();
|
|
90575
|
+
},
|
|
90576
|
+
retryCount,
|
|
90577
|
+
retryDelay,
|
|
90578
|
+
type: 'fallback',
|
|
90579
|
+
}, {
|
|
90580
|
+
onResponse: (fn) => (onResponse = fn),
|
|
90581
|
+
transports: transports.map((fn) => fn({ chain, retryCount: 0 })),
|
|
90582
|
+
});
|
|
90583
|
+
if (rank) {
|
|
90584
|
+
const rankOptions = (typeof rank === 'object' ? rank : {});
|
|
90585
|
+
rankTransports({
|
|
90586
|
+
chain,
|
|
90587
|
+
interval: rankOptions.interval ?? pollingInterval,
|
|
90588
|
+
onTransports: (transports_) => (transports = transports_),
|
|
90589
|
+
ping: rankOptions.ping,
|
|
90590
|
+
sampleCount: rankOptions.sampleCount,
|
|
90591
|
+
timeout: rankOptions.timeout,
|
|
90592
|
+
transports,
|
|
90593
|
+
weights: rankOptions.weights,
|
|
90594
|
+
});
|
|
90595
|
+
}
|
|
90596
|
+
return transport;
|
|
90597
|
+
});
|
|
90598
|
+
}
|
|
90599
|
+
function shouldThrow(error) {
|
|
90600
|
+
if ('code' in error && typeof error.code === 'number') {
|
|
90601
|
+
if (error.code === TransactionRejectedRpcError.code ||
|
|
90602
|
+
error.code === UserRejectedRequestError.code ||
|
|
90603
|
+
error.code === WalletConnectSessionSettlementError.code ||
|
|
90604
|
+
errors_node/* ExecutionRevertedError */.A7.nodeMessage.test(error.message) ||
|
|
90605
|
+
error.code === 5000 // CAIP UserRejectedRequestError
|
|
90606
|
+
)
|
|
90607
|
+
return true;
|
|
90608
|
+
}
|
|
90609
|
+
return false;
|
|
90610
|
+
}
|
|
90611
|
+
/** @internal */
|
|
90612
|
+
function rankTransports({ chain, interval = 4_000, onTransports, ping, sampleCount = 10, timeout = 1_000, transports, weights = {}, }) {
|
|
90613
|
+
const { stability: stabilityWeight = 0.7, latency: latencyWeight = 0.3 } = weights;
|
|
90614
|
+
const samples = [];
|
|
90615
|
+
const rankTransports_ = async () => {
|
|
90616
|
+
// 1. Take a sample from each Transport.
|
|
90617
|
+
const sample = await Promise.all(transports.map(async (transport) => {
|
|
90618
|
+
const transport_ = transport({ chain, retryCount: 0, timeout });
|
|
90619
|
+
const start = Date.now();
|
|
90620
|
+
let end;
|
|
90621
|
+
let success;
|
|
90622
|
+
try {
|
|
90623
|
+
await (ping
|
|
90624
|
+
? ping({ transport: transport_ })
|
|
90625
|
+
: transport_.request({ method: 'net_listening' }));
|
|
90626
|
+
success = 1;
|
|
90627
|
+
}
|
|
90628
|
+
catch {
|
|
90629
|
+
success = 0;
|
|
90630
|
+
}
|
|
90631
|
+
finally {
|
|
90632
|
+
end = Date.now();
|
|
90633
|
+
}
|
|
90634
|
+
const latency = end - start;
|
|
90635
|
+
return { latency, success };
|
|
90636
|
+
}));
|
|
90637
|
+
// 2. Store the sample. If we have more than `sampleCount` samples, remove
|
|
90638
|
+
// the oldest sample.
|
|
90639
|
+
samples.push(sample);
|
|
90640
|
+
if (samples.length > sampleCount)
|
|
90641
|
+
samples.shift();
|
|
90642
|
+
// 3. Calculate the max latency from samples.
|
|
90643
|
+
const maxLatency = Math.max(...samples.map((sample) => Math.max(...sample.map(({ latency }) => latency))));
|
|
90644
|
+
// 4. Calculate the score for each Transport.
|
|
90645
|
+
const scores = transports
|
|
90646
|
+
.map((_, i) => {
|
|
90647
|
+
const latencies = samples.map((sample) => sample[i].latency);
|
|
90648
|
+
const meanLatency = latencies.reduce((acc, latency) => acc + latency, 0) /
|
|
90649
|
+
latencies.length;
|
|
90650
|
+
const latencyScore = 1 - meanLatency / maxLatency;
|
|
90651
|
+
const successes = samples.map((sample) => sample[i].success);
|
|
90652
|
+
const stabilityScore = successes.reduce((acc, success) => acc + success, 0) /
|
|
90653
|
+
successes.length;
|
|
90654
|
+
if (stabilityScore === 0)
|
|
90655
|
+
return [0, i];
|
|
90656
|
+
return [
|
|
90657
|
+
latencyWeight * latencyScore + stabilityWeight * stabilityScore,
|
|
90658
|
+
i,
|
|
90659
|
+
];
|
|
90660
|
+
})
|
|
90661
|
+
.sort((a, b) => b[0] - a[0]);
|
|
90662
|
+
// 5. Sort the Transports by score.
|
|
90663
|
+
onTransports(scores.map(([, i]) => transports[i]));
|
|
90664
|
+
// 6. Wait, and then rank again.
|
|
90665
|
+
await wait(interval);
|
|
90666
|
+
rankTransports_();
|
|
90667
|
+
};
|
|
90668
|
+
rankTransports_();
|
|
90669
|
+
}
|
|
90670
|
+
//# sourceMappingURL=fallback.js.map
|
|
90474
90671
|
;// CONCATENATED MODULE: ./node_modules/viem/_esm/accounts/toAccount.js
|
|
90475
90672
|
// TODO(v3): Rename to `toLocalAccount` + add `source` property to define source (privateKey, mnemonic, hdKey, etc).
|
|
90476
90673
|
|
|
@@ -91189,9 +91386,15 @@ class EvmClientSigner {
|
|
|
91189
91386
|
walletClient;
|
|
91190
91387
|
publicClients = new Map();
|
|
91191
91388
|
account;
|
|
91192
|
-
|
|
91389
|
+
rpcUrl;
|
|
91390
|
+
rpcUrls;
|
|
91391
|
+
rpcByNetwork;
|
|
91392
|
+
constructor(privateKey, options) {
|
|
91193
91393
|
const hexKey = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
|
|
91194
91394
|
this.account = privateKeyToAccount(hexKey);
|
|
91395
|
+
this.rpcUrl = options?.rpcUrl;
|
|
91396
|
+
this.rpcUrls = options?.rpcUrls;
|
|
91397
|
+
this.rpcByNetwork = options?.rpcByNetwork;
|
|
91195
91398
|
this.walletClient = createWalletClient({
|
|
91196
91399
|
account: this.account,
|
|
91197
91400
|
chain: mainnet,
|
|
@@ -91210,7 +91413,6 @@ class EvmClientSigner {
|
|
|
91210
91413
|
});
|
|
91211
91414
|
}
|
|
91212
91415
|
async signTypedData(domain, types, message) {
|
|
91213
|
-
// TODO: Add explicit primaryType to ClientSigner interface
|
|
91214
91416
|
const primaryType = types.Permit402Details ? "Permit402Details" : Object.keys(types).pop();
|
|
91215
91417
|
if (!primaryType) {
|
|
91216
91418
|
throw new Error("No primary type found in types definition");
|
|
@@ -91225,35 +91427,23 @@ class EvmClientSigner {
|
|
|
91225
91427
|
async checkBalance(token, network) {
|
|
91226
91428
|
const chainId = this.parseNetworkToChainId(network);
|
|
91227
91429
|
const client = this.getPublicClient(chainId, network);
|
|
91228
|
-
|
|
91229
|
-
|
|
91230
|
-
|
|
91231
|
-
|
|
91232
|
-
|
|
91233
|
-
|
|
91234
|
-
});
|
|
91235
|
-
}
|
|
91236
|
-
catch (error) {
|
|
91237
|
-
console.error(`[EvmClientSigner] checkBalance failed for ${token} on ${network}:`, error);
|
|
91238
|
-
return 0n;
|
|
91239
|
-
}
|
|
91430
|
+
return await client.readContract({
|
|
91431
|
+
address: token,
|
|
91432
|
+
abi: evmSigner_ERC20_ABI,
|
|
91433
|
+
functionName: "balanceOf",
|
|
91434
|
+
args: [this.account.address],
|
|
91435
|
+
});
|
|
91240
91436
|
}
|
|
91241
91437
|
async checkAllowance(token, _amount, network) {
|
|
91242
91438
|
const chainId = this.parseNetworkToChainId(network);
|
|
91243
91439
|
const client = this.getPublicClient(chainId, network);
|
|
91244
|
-
const spender =
|
|
91245
|
-
|
|
91246
|
-
|
|
91247
|
-
|
|
91248
|
-
|
|
91249
|
-
|
|
91250
|
-
|
|
91251
|
-
});
|
|
91252
|
-
}
|
|
91253
|
-
catch (error) {
|
|
91254
|
-
console.error(`[EvmClientSigner] checkAllowance failed for ${token} on ${network}:`, error);
|
|
91255
|
-
return 0n;
|
|
91256
|
-
}
|
|
91440
|
+
const spender = getPermit402Address(network);
|
|
91441
|
+
return await client.readContract({
|
|
91442
|
+
address: token,
|
|
91443
|
+
abi: evmSigner_ERC20_ABI,
|
|
91444
|
+
functionName: "allowance",
|
|
91445
|
+
args: [this.account.address, spender],
|
|
91446
|
+
});
|
|
91257
91447
|
}
|
|
91258
91448
|
async ensureAllowance(token, amount, network, mode = "auto") {
|
|
91259
91449
|
if (mode === "skip")
|
|
@@ -91266,14 +91456,14 @@ class EvmClientSigner {
|
|
|
91266
91456
|
}
|
|
91267
91457
|
const chainId = this.parseNetworkToChainId(network);
|
|
91268
91458
|
const client = this.getPublicClient(chainId, network);
|
|
91269
|
-
const spender =
|
|
91459
|
+
const spender = getPermit402Address(network);
|
|
91270
91460
|
const chain = this.getChain(chainId);
|
|
91271
91461
|
try {
|
|
91272
|
-
const
|
|
91462
|
+
const transport = this.createTransport(network);
|
|
91273
91463
|
const walletClient = createWalletClient({
|
|
91274
91464
|
account: this.account,
|
|
91275
91465
|
chain: chain,
|
|
91276
|
-
transport
|
|
91466
|
+
transport,
|
|
91277
91467
|
});
|
|
91278
91468
|
const hash = await walletClient.writeContract({
|
|
91279
91469
|
address: token,
|
|
@@ -91282,29 +91472,44 @@ class EvmClientSigner {
|
|
|
91282
91472
|
args: [spender, BigInt(2) ** BigInt(256) - BigInt(1)],
|
|
91283
91473
|
});
|
|
91284
91474
|
const receipt = await client.waitForTransactionReceipt({ hash });
|
|
91285
|
-
|
|
91286
|
-
if (success) {
|
|
91287
|
-
console.info(`[EvmClientSigner] ERC20 approval confirmed for ${token}, tx: ${hash}`);
|
|
91288
|
-
}
|
|
91289
|
-
return success;
|
|
91475
|
+
return receipt.status === "success";
|
|
91290
91476
|
}
|
|
91291
91477
|
catch (error) {
|
|
91292
|
-
console.error(`[EvmClientSigner] ERC20 approval failed for ${token}:`, error);
|
|
91293
91478
|
throw new InsufficientAllowanceError(`ERC20 approval transaction failed for ${token}: ${error instanceof Error ? error.message : String(error)}`);
|
|
91294
91479
|
}
|
|
91295
91480
|
}
|
|
91296
91481
|
getPublicClient(chainId, network) {
|
|
91297
91482
|
let client = this.publicClients.get(chainId);
|
|
91298
91483
|
if (!client) {
|
|
91299
|
-
const
|
|
91484
|
+
const transport = this.createTransport(network);
|
|
91300
91485
|
client = createPublicClient({
|
|
91301
91486
|
chain: this.getChain(chainId),
|
|
91302
|
-
transport
|
|
91487
|
+
transport,
|
|
91303
91488
|
});
|
|
91304
91489
|
this.publicClients.set(chainId, client);
|
|
91305
91490
|
}
|
|
91306
91491
|
return client;
|
|
91307
91492
|
}
|
|
91493
|
+
createTransport(network) {
|
|
91494
|
+
const candidates = this.getRpcCandidates(network);
|
|
91495
|
+
if (candidates.length === 0) {
|
|
91496
|
+
throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
|
|
91497
|
+
}
|
|
91498
|
+
if (candidates.length === 1) {
|
|
91499
|
+
return http_http(candidates[0]);
|
|
91500
|
+
}
|
|
91501
|
+
return fallback(candidates.map((url) => http_http(url)), { rank: false, retryCount: 1 });
|
|
91502
|
+
}
|
|
91503
|
+
getRpcCandidates(network) {
|
|
91504
|
+
const perNetwork = this.rpcByNetwork?.[network];
|
|
91505
|
+
const perNetworkList = Array.isArray(perNetwork) ? perNetwork : perNetwork ? [perNetwork] : [];
|
|
91506
|
+
const globalList = this.rpcUrls?.length ? this.rpcUrls : this.rpcUrl ? [this.rpcUrl] : [];
|
|
91507
|
+
const overrides = {
|
|
91508
|
+
...(this.rpcByNetwork ?? {}),
|
|
91509
|
+
[network]: [...perNetworkList, ...globalList],
|
|
91510
|
+
};
|
|
91511
|
+
return resolveRpcUrls(network, overrides);
|
|
91512
|
+
}
|
|
91308
91513
|
getChain(chainId) {
|
|
91309
91514
|
const chains = {
|
|
91310
91515
|
1: mainnet,
|
|
@@ -91345,6 +91550,7 @@ class EvmClientSigner {
|
|
|
91345
91550
|
|
|
91346
91551
|
|
|
91347
91552
|
|
|
91553
|
+
|
|
91348
91554
|
// HTTP Client
|
|
91349
91555
|
|
|
91350
91556
|
// Server helpers
|