@veil-cash/sdk 0.6.4 → 0.7.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/README.md +47 -5
- package/SDK.md +77 -11
- package/dist/cli/index.cjs +229 -237
- package/dist/index.cjs +386 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +131 -38
- package/dist/index.d.ts +131 -38
- package/dist/index.js +355 -40
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/skills/veil/SKILL.md +1 -3
- package/skills/veil/reference.md +3 -3
- package/src/abi.ts +0 -8
- package/src/balance.ts +0 -48
- package/src/cli/commands/deposit.ts +8 -27
- package/src/compat.ts +23 -0
- package/src/ffjavascript.d.ts +13 -8
- package/src/index.ts +21 -1
- package/src/keypair.ts +1 -1
- package/src/types.ts +5 -0
- package/src/utils.ts +4 -2
- package/src/withdraw.ts +2 -1
- package/src/x402.ts +546 -0
package/dist/index.cjs
CHANGED
|
@@ -3,23 +3,53 @@
|
|
|
3
3
|
var ethers = require('ethers');
|
|
4
4
|
var buffer = require('buffer');
|
|
5
5
|
var accounts = require('viem/accounts');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var _ethSigUtil = require('eth-sig-util');
|
|
7
|
+
var _circomlib = require('circomlib');
|
|
8
8
|
var viem = require('viem');
|
|
9
9
|
var chains = require('viem/chains');
|
|
10
10
|
var MerkleTree = require('fixed-merkle-tree-legacy');
|
|
11
11
|
var snarkjs = require('snarkjs');
|
|
12
12
|
var ffjavascript = require('ffjavascript');
|
|
13
|
+
var client = require('@x402/core/client');
|
|
14
|
+
var client$1 = require('@x402/evm/exact/client');
|
|
15
|
+
var evm = require('@x402/evm');
|
|
13
16
|
|
|
14
17
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
function _interopNamespace(e) {
|
|
21
|
+
if (e && e.__esModule) return e;
|
|
22
|
+
var n = Object.create(null);
|
|
23
|
+
if (e) {
|
|
24
|
+
Object.keys(e).forEach(function (k) {
|
|
25
|
+
if (k !== 'default') {
|
|
26
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
27
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return e[k]; }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
n.default = e;
|
|
35
|
+
return Object.freeze(n);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
var _ethSigUtil__namespace = /*#__PURE__*/_interopNamespace(_ethSigUtil);
|
|
39
|
+
var _circomlib__namespace = /*#__PURE__*/_interopNamespace(_circomlib);
|
|
19
40
|
var MerkleTree__default = /*#__PURE__*/_interopDefault(MerkleTree);
|
|
20
41
|
|
|
21
42
|
// src/keypair.ts
|
|
22
|
-
|
|
43
|
+
function resolveInterop(mod) {
|
|
44
|
+
if (mod && typeof mod === "object" && "default" in mod) {
|
|
45
|
+
const defaultVal = mod.default;
|
|
46
|
+
if (defaultVal != null) return defaultVal;
|
|
47
|
+
}
|
|
48
|
+
return mod;
|
|
49
|
+
}
|
|
50
|
+
var ethSigUtil = resolveInterop(_ethSigUtil__namespace);
|
|
51
|
+
var circomlib = resolveInterop(_circomlib__namespace);
|
|
52
|
+
var poseidon = circomlib.poseidon;
|
|
23
53
|
var FIELD_SIZE = BigInt(
|
|
24
54
|
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
|
25
55
|
);
|
|
@@ -28,7 +58,9 @@ var poseidonHash2 = (a, b) => poseidonHash([a, b]);
|
|
|
28
58
|
var randomBN = (nbytes = 31) => {
|
|
29
59
|
const cryptoApi = globalThis.crypto;
|
|
30
60
|
if (!cryptoApi?.getRandomValues) {
|
|
31
|
-
throw new Error(
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Secure random number generation is unavailable. Provide globalThis.crypto.getRandomValues in this runtime."
|
|
63
|
+
);
|
|
32
64
|
}
|
|
33
65
|
const bytes = cryptoApi.getRandomValues(new Uint8Array(nbytes));
|
|
34
66
|
let hex = "0x";
|
|
@@ -127,7 +159,7 @@ var Keypair = class _Keypair {
|
|
|
127
159
|
constructor(privkey = ethers.ethers.Wallet.createRandom().privateKey) {
|
|
128
160
|
this.privkey = privkey;
|
|
129
161
|
this.pubkey = poseidonHash([this.privkey]);
|
|
130
|
-
this.encryptionKey =
|
|
162
|
+
this.encryptionKey = ethSigUtil.getEncryptionPublicKey(privkey.slice(2));
|
|
131
163
|
}
|
|
132
164
|
/**
|
|
133
165
|
* Get the deposit key for this keypair
|
|
@@ -245,7 +277,7 @@ var Keypair = class _Keypair {
|
|
|
245
277
|
*/
|
|
246
278
|
encrypt(bytes) {
|
|
247
279
|
return packEncryptedMessage(
|
|
248
|
-
|
|
280
|
+
ethSigUtil.encrypt(
|
|
249
281
|
this.encryptionKey,
|
|
250
282
|
{ data: bytes.toString("base64") },
|
|
251
283
|
"x25519-xsalsa20-poly1305"
|
|
@@ -262,7 +294,7 @@ var Keypair = class _Keypair {
|
|
|
262
294
|
throw new Error("Cannot decrypt without private key");
|
|
263
295
|
}
|
|
264
296
|
return buffer.Buffer.from(
|
|
265
|
-
|
|
297
|
+
ethSigUtil.decrypt(unpackEncryptedMessage(data), this.privkey.slice(2)),
|
|
266
298
|
"base64"
|
|
267
299
|
);
|
|
268
300
|
}
|
|
@@ -600,14 +632,6 @@ var QUEUE_ABI = [
|
|
|
600
632
|
outputs: [{ name: "count", type: "uint256" }],
|
|
601
633
|
stateMutability: "view",
|
|
602
634
|
type: "function"
|
|
603
|
-
},
|
|
604
|
-
// Get remaining daily free deposits for an address (V3+)
|
|
605
|
-
{
|
|
606
|
-
inputs: [{ name: "_depositor", type: "address" }],
|
|
607
|
-
name: "getDailyFreeRemaining",
|
|
608
|
-
outputs: [{ name: "remaining", type: "uint256" }],
|
|
609
|
-
stateMutability: "view",
|
|
610
|
-
type: "function"
|
|
611
635
|
}
|
|
612
636
|
];
|
|
613
637
|
var POOL_ABI = [
|
|
@@ -1325,25 +1349,6 @@ async function getQueueBalance(options) {
|
|
|
1325
1349
|
pendingCount: pendingDeposits.length
|
|
1326
1350
|
};
|
|
1327
1351
|
}
|
|
1328
|
-
async function getDailyFreeRemaining(options) {
|
|
1329
|
-
const { address, pool = "eth", rpcUrl } = options;
|
|
1330
|
-
const queueAddress = getQueueAddress(pool);
|
|
1331
|
-
const publicClient = viem.createPublicClient({
|
|
1332
|
-
chain: chains.base,
|
|
1333
|
-
transport: viem.http(rpcUrl)
|
|
1334
|
-
});
|
|
1335
|
-
try {
|
|
1336
|
-
const remaining = await publicClient.readContract({
|
|
1337
|
-
address: queueAddress,
|
|
1338
|
-
abi: QUEUE_ABI,
|
|
1339
|
-
functionName: "getDailyFreeRemaining",
|
|
1340
|
-
args: [address]
|
|
1341
|
-
});
|
|
1342
|
-
return Number(remaining);
|
|
1343
|
-
} catch {
|
|
1344
|
-
return 0;
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
1352
|
async function getPrivateBalance(options) {
|
|
1348
1353
|
const { keypair, pool = "eth", rpcUrl, onProgress } = options;
|
|
1349
1354
|
const poolAddress = getPoolAddress(pool);
|
|
@@ -1923,12 +1928,13 @@ async function buildWithdrawProof(options) {
|
|
|
1923
1928
|
};
|
|
1924
1929
|
}
|
|
1925
1930
|
async function withdraw(options) {
|
|
1926
|
-
const { amount, recipient, pool = "eth", onProgress } = options;
|
|
1931
|
+
const { amount, recipient, pool = "eth", onProgress, relayUrl } = options;
|
|
1927
1932
|
const proof = await buildWithdrawProof(options);
|
|
1928
1933
|
onProgress?.("Submitting to relay...");
|
|
1929
1934
|
const relayResult = await submitRelay({
|
|
1930
1935
|
type: "withdraw",
|
|
1931
1936
|
pool,
|
|
1937
|
+
relayUrl,
|
|
1932
1938
|
proofArgs: proof.proofArgs,
|
|
1933
1939
|
extData: proof.extData,
|
|
1934
1940
|
metadata: {
|
|
@@ -1946,6 +1952,333 @@ async function withdraw(options) {
|
|
|
1946
1952
|
recipient
|
|
1947
1953
|
};
|
|
1948
1954
|
}
|
|
1955
|
+
var X402_PAYER_DOMAIN = "veil-x402-payer";
|
|
1956
|
+
var BASE_NETWORK = `eip155:${ADDRESSES.chainId}`;
|
|
1957
|
+
var USDC_DECIMALS = POOL_CONFIG.usdc.decimals;
|
|
1958
|
+
var X402_MIN_WITHDRAW_ATOMIC = 1000n;
|
|
1959
|
+
function assertPrivateKey(value, label) {
|
|
1960
|
+
if (!/^0x[a-fA-F0-9]{64}$/.test(value)) {
|
|
1961
|
+
throw new Error(`${label} must be a 0x-prefixed 32-byte hex string`);
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
function normalizePayerIndex(index) {
|
|
1965
|
+
const normalized = typeof index === "bigint" ? index : typeof index === "number" ? BigInt(index) : BigInt(index);
|
|
1966
|
+
if (normalized < 0n) {
|
|
1967
|
+
throw new Error("payerIndex must be non-negative");
|
|
1968
|
+
}
|
|
1969
|
+
return normalized;
|
|
1970
|
+
}
|
|
1971
|
+
function normalizeAtomicAmount(amount) {
|
|
1972
|
+
if (!/^\d+$/.test(amount)) {
|
|
1973
|
+
throw new Error(`x402 amount must be an atomic integer string, received: ${amount}`);
|
|
1974
|
+
}
|
|
1975
|
+
if (BigInt(amount) <= 0n) {
|
|
1976
|
+
throw new Error("x402 amount must be greater than 0");
|
|
1977
|
+
}
|
|
1978
|
+
return amount;
|
|
1979
|
+
}
|
|
1980
|
+
function usdcAtomicToDecimalString(amountAtomic) {
|
|
1981
|
+
const atomic = typeof amountAtomic === "bigint" ? amountAtomic.toString() : normalizeAtomicAmount(amountAtomic);
|
|
1982
|
+
return viem.formatUnits(BigInt(atomic), USDC_DECIMALS);
|
|
1983
|
+
}
|
|
1984
|
+
function usdcDecimalToAtomic(amount) {
|
|
1985
|
+
if (!/^\d+(\.\d+)?$/.test(amount.trim())) {
|
|
1986
|
+
throw new Error(`Invalid USDC amount: ${amount}`);
|
|
1987
|
+
}
|
|
1988
|
+
return viem.parseUnits(amount.trim(), USDC_DECIMALS);
|
|
1989
|
+
}
|
|
1990
|
+
function deriveX402PayerKey(rootPrivateKey, index) {
|
|
1991
|
+
assertPrivateKey(rootPrivateKey, "rootPrivateKey");
|
|
1992
|
+
const normalizedIndex = normalizePayerIndex(index);
|
|
1993
|
+
return viem.keccak256(
|
|
1994
|
+
viem.encodePacked(
|
|
1995
|
+
["bytes32", "string", "uint256"],
|
|
1996
|
+
[rootPrivateKey, X402_PAYER_DOMAIN, normalizedIndex]
|
|
1997
|
+
)
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
function deriveX402PayerAddress(rootPrivateKey, index) {
|
|
2001
|
+
return accounts.privateKeyToAddress(deriveX402PayerKey(rootPrivateKey, index));
|
|
2002
|
+
}
|
|
2003
|
+
function selectBaseUsdcExactRequirement(paymentRequired) {
|
|
2004
|
+
if (paymentRequired.x402Version !== 2) {
|
|
2005
|
+
throw new Error(`Unsupported x402 version ${paymentRequired.x402Version}; expected v2`);
|
|
2006
|
+
}
|
|
2007
|
+
const requirement = paymentRequired.accepts.find(
|
|
2008
|
+
(candidate) => candidate.scheme === "exact" && candidate.network === BASE_NETWORK && candidate.asset.toLowerCase() === ADDRESSES.usdcToken.toLowerCase()
|
|
2009
|
+
);
|
|
2010
|
+
if (!requirement) {
|
|
2011
|
+
throw new Error("No supported x402 payment requirement found. Veil supports x402 v2 exact Base USDC only.");
|
|
2012
|
+
}
|
|
2013
|
+
if (!viem.isAddress(requirement.payTo)) {
|
|
2014
|
+
throw new Error("Selected x402 requirement has an invalid payTo address");
|
|
2015
|
+
}
|
|
2016
|
+
normalizeAtomicAmount(requirement.amount);
|
|
2017
|
+
return requirement;
|
|
2018
|
+
}
|
|
2019
|
+
async function parsePaymentRequired(response, httpClient) {
|
|
2020
|
+
let body;
|
|
2021
|
+
try {
|
|
2022
|
+
body = await response.clone().json();
|
|
2023
|
+
} catch {
|
|
2024
|
+
body = void 0;
|
|
2025
|
+
}
|
|
2026
|
+
return httpClient.getPaymentRequiredResponse(
|
|
2027
|
+
(name) => response.headers.get(name),
|
|
2028
|
+
body
|
|
2029
|
+
);
|
|
2030
|
+
}
|
|
2031
|
+
async function payX402Resource(options) {
|
|
2032
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
2033
|
+
if (!fetchImpl) {
|
|
2034
|
+
throw new Error("fetch is not available; pass fetchImpl");
|
|
2035
|
+
}
|
|
2036
|
+
const payerIndex = normalizePayerIndex(options.payerIndex);
|
|
2037
|
+
const payerPrivateKey = deriveX402PayerKey(options.rootPrivateKey, payerIndex);
|
|
2038
|
+
const payerAccount = accounts.privateKeyToAccount(payerPrivateKey);
|
|
2039
|
+
const publicClient = viem.createPublicClient({
|
|
2040
|
+
chain: chains.base,
|
|
2041
|
+
transport: viem.http(options.rpcUrl)
|
|
2042
|
+
});
|
|
2043
|
+
const signer = evm.toClientEvmSigner(payerAccount, publicClient);
|
|
2044
|
+
const client$2 = new client.x402Client(
|
|
2045
|
+
(_version, requirements) => selectBaseUsdcExactRequirement({
|
|
2046
|
+
x402Version: 2,
|
|
2047
|
+
resource: { url: options.url },
|
|
2048
|
+
accepts: requirements
|
|
2049
|
+
})
|
|
2050
|
+
);
|
|
2051
|
+
client$1.registerExactEvmScheme(client$2, {
|
|
2052
|
+
signer,
|
|
2053
|
+
networks: [BASE_NETWORK],
|
|
2054
|
+
schemeOptions: options.rpcUrl ? { rpcUrl: options.rpcUrl } : void 0
|
|
2055
|
+
});
|
|
2056
|
+
const httpClient = new client.x402HTTPClient(client$2);
|
|
2057
|
+
options.onProgress?.("Fetching x402 requirement...");
|
|
2058
|
+
const initialResponse = await fetchImpl(options.url, options.init);
|
|
2059
|
+
if (initialResponse.status !== 402) {
|
|
2060
|
+
return {
|
|
2061
|
+
response: initialResponse,
|
|
2062
|
+
payerAddress: payerAccount.address,
|
|
2063
|
+
payerIndex: payerIndex.toString(),
|
|
2064
|
+
amount: "0",
|
|
2065
|
+
amountAtomic: "0",
|
|
2066
|
+
relayTransactionHash: "",
|
|
2067
|
+
relayBlockNumber: ""
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2070
|
+
const paymentRequired = await parsePaymentRequired(initialResponse, httpClient);
|
|
2071
|
+
const requirement = selectBaseUsdcExactRequirement(paymentRequired);
|
|
2072
|
+
const amountAtomic = normalizeAtomicAmount(requirement.amount);
|
|
2073
|
+
const amount = usdcAtomicToDecimalString(amountAtomic);
|
|
2074
|
+
if (options.maxPayment !== void 0) {
|
|
2075
|
+
const maxAtomic = usdcDecimalToAtomic(options.maxPayment);
|
|
2076
|
+
if (BigInt(amountAtomic) > maxAtomic) {
|
|
2077
|
+
throw new Error(
|
|
2078
|
+
`x402 payment of ${amount} USDC exceeds maxPayment cap of ${usdcAtomicToDecimalString(maxAtomic)} USDC. Payment was not sent.`
|
|
2079
|
+
);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
let relayTransactionHash = "";
|
|
2083
|
+
let relayBlockNumber = "";
|
|
2084
|
+
let fundAtomic = BigInt(amountAtomic);
|
|
2085
|
+
if (options.reuseExistingBalance) {
|
|
2086
|
+
const payerBalance = await publicClient.readContract({
|
|
2087
|
+
address: ADDRESSES.usdcToken,
|
|
2088
|
+
abi: ERC20_ABI,
|
|
2089
|
+
functionName: "balanceOf",
|
|
2090
|
+
args: [payerAccount.address]
|
|
2091
|
+
});
|
|
2092
|
+
if (payerBalance >= BigInt(amountAtomic)) {
|
|
2093
|
+
fundAtomic = 0n;
|
|
2094
|
+
} else if (options.reuseExistingBalance === "topup") {
|
|
2095
|
+
fundAtomic = BigInt(amountAtomic) - payerBalance;
|
|
2096
|
+
} else {
|
|
2097
|
+
throw new Error(
|
|
2098
|
+
`Cannot reuse payer index ${payerIndex.toString()}: holds ${viem.formatUnits(payerBalance, USDC_DECIMALS)} USDC but the resource requires ${amount} USDC. Pass reuseExistingBalance: 'topup' to fund the shortfall.`
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
if (fundAtomic === 0n) {
|
|
2103
|
+
options.onProgress?.("Reusing funded x402 payer...", `${amount} USDC on ${payerAccount.address}`);
|
|
2104
|
+
} else {
|
|
2105
|
+
if (fundAtomic < X402_MIN_WITHDRAW_ATOMIC) {
|
|
2106
|
+
fundAtomic = X402_MIN_WITHDRAW_ATOMIC;
|
|
2107
|
+
}
|
|
2108
|
+
const fundAmount = usdcAtomicToDecimalString(fundAtomic);
|
|
2109
|
+
options.onProgress?.("Funding x402 payer...", `${fundAmount} USDC to ${payerAccount.address}`);
|
|
2110
|
+
const proof = await buildWithdrawProof({
|
|
2111
|
+
amount: fundAmount,
|
|
2112
|
+
recipient: payerAccount.address,
|
|
2113
|
+
keypair: new Keypair(options.rootPrivateKey),
|
|
2114
|
+
pool: "usdc",
|
|
2115
|
+
rpcUrl: options.rpcUrl,
|
|
2116
|
+
provingKeyPath: options.provingKeyPath,
|
|
2117
|
+
onProgress: options.onProgress
|
|
2118
|
+
});
|
|
2119
|
+
const relayResult = await submitRelay({
|
|
2120
|
+
type: "withdraw",
|
|
2121
|
+
pool: "usdc",
|
|
2122
|
+
// x402 funding must target the low-minimum /x402 relay route. Default to it
|
|
2123
|
+
// so direct SDK consumers do not silently hit the main relay's 5 USDC floor.
|
|
2124
|
+
relayUrl: options.relayUrl ?? `${getRelayUrl()}/x402`,
|
|
2125
|
+
proofArgs: proof.proofArgs,
|
|
2126
|
+
extData: proof.extData,
|
|
2127
|
+
metadata: {
|
|
2128
|
+
amount: fundAmount,
|
|
2129
|
+
amountAtomic: fundAtomic.toString(),
|
|
2130
|
+
recipient: payerAccount.address,
|
|
2131
|
+
inputUtxoCount: proof.inputCount,
|
|
2132
|
+
outputUtxoCount: proof.outputCount,
|
|
2133
|
+
x402: true,
|
|
2134
|
+
payerIndex: payerIndex.toString()
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
relayTransactionHash = relayResult.transactionHash;
|
|
2138
|
+
relayBlockNumber = relayResult.blockNumber;
|
|
2139
|
+
if (options.onPayerFunded) {
|
|
2140
|
+
try {
|
|
2141
|
+
options.onPayerFunded({
|
|
2142
|
+
payerAddress: payerAccount.address,
|
|
2143
|
+
payerIndex: payerIndex.toString(),
|
|
2144
|
+
amount,
|
|
2145
|
+
amountAtomic,
|
|
2146
|
+
relayTransactionHash,
|
|
2147
|
+
relayBlockNumber
|
|
2148
|
+
});
|
|
2149
|
+
} catch {
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
options.onProgress?.("Signing x402 payment...");
|
|
2154
|
+
const paymentPayload = await httpClient.createPaymentPayload({
|
|
2155
|
+
...paymentRequired,
|
|
2156
|
+
accepts: [requirement]
|
|
2157
|
+
});
|
|
2158
|
+
const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload);
|
|
2159
|
+
const headers = new Headers(options.init?.headers);
|
|
2160
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
2161
|
+
headers.set(key, value);
|
|
2162
|
+
}
|
|
2163
|
+
options.onProgress?.("Requesting paid resource...");
|
|
2164
|
+
const paidResponse = await fetchImpl(options.url, {
|
|
2165
|
+
...options.init,
|
|
2166
|
+
headers
|
|
2167
|
+
});
|
|
2168
|
+
let paymentResponse;
|
|
2169
|
+
try {
|
|
2170
|
+
paymentResponse = httpClient.getPaymentSettleResponse((name) => paidResponse.headers.get(name));
|
|
2171
|
+
} catch {
|
|
2172
|
+
paymentResponse = void 0;
|
|
2173
|
+
}
|
|
2174
|
+
return {
|
|
2175
|
+
response: paidResponse,
|
|
2176
|
+
payerAddress: payerAccount.address,
|
|
2177
|
+
payerIndex: payerIndex.toString(),
|
|
2178
|
+
amount,
|
|
2179
|
+
amountAtomic,
|
|
2180
|
+
relayTransactionHash,
|
|
2181
|
+
relayBlockNumber,
|
|
2182
|
+
paymentResponse,
|
|
2183
|
+
paymentTransactionHash: paymentResponse?.transaction
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2186
|
+
async function quoteX402Resource(options) {
|
|
2187
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
2188
|
+
if (!fetchImpl) {
|
|
2189
|
+
throw new Error("fetch is not available; pass fetchImpl");
|
|
2190
|
+
}
|
|
2191
|
+
const client$1 = new client.x402Client(
|
|
2192
|
+
(_version, requirements) => selectBaseUsdcExactRequirement({
|
|
2193
|
+
x402Version: 2,
|
|
2194
|
+
resource: { url: options.url },
|
|
2195
|
+
accepts: requirements
|
|
2196
|
+
})
|
|
2197
|
+
);
|
|
2198
|
+
const httpClient = new client.x402HTTPClient(client$1);
|
|
2199
|
+
const initialResponse = await fetchImpl(options.url, options.init);
|
|
2200
|
+
if (initialResponse.status !== 402) {
|
|
2201
|
+
let body;
|
|
2202
|
+
try {
|
|
2203
|
+
body = await initialResponse.clone().json();
|
|
2204
|
+
} catch {
|
|
2205
|
+
try {
|
|
2206
|
+
body = await initialResponse.clone().text();
|
|
2207
|
+
} catch {
|
|
2208
|
+
body = void 0;
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
return {
|
|
2212
|
+
requiresPayment: false,
|
|
2213
|
+
supported: false,
|
|
2214
|
+
status: initialResponse.status,
|
|
2215
|
+
body
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
let requirement;
|
|
2219
|
+
try {
|
|
2220
|
+
const paymentRequired = await parsePaymentRequired(initialResponse, httpClient);
|
|
2221
|
+
requirement = selectBaseUsdcExactRequirement(paymentRequired);
|
|
2222
|
+
} catch (error) {
|
|
2223
|
+
return {
|
|
2224
|
+
requiresPayment: true,
|
|
2225
|
+
supported: false,
|
|
2226
|
+
status: 402,
|
|
2227
|
+
error: error instanceof Error ? error.message : "Unsupported x402 requirement"
|
|
2228
|
+
};
|
|
2229
|
+
}
|
|
2230
|
+
const amountAtomic = normalizeAtomicAmount(requirement.amount);
|
|
2231
|
+
const amount = usdcAtomicToDecimalString(amountAtomic);
|
|
2232
|
+
let exceedsMax;
|
|
2233
|
+
if (options.maxPayment !== void 0) {
|
|
2234
|
+
exceedsMax = BigInt(amountAtomic) > usdcDecimalToAtomic(options.maxPayment);
|
|
2235
|
+
}
|
|
2236
|
+
return {
|
|
2237
|
+
requiresPayment: true,
|
|
2238
|
+
supported: true,
|
|
2239
|
+
status: 402,
|
|
2240
|
+
amount,
|
|
2241
|
+
amountAtomic,
|
|
2242
|
+
payTo: requirement.payTo,
|
|
2243
|
+
network: requirement.network,
|
|
2244
|
+
asset: requirement.asset,
|
|
2245
|
+
exceedsMax,
|
|
2246
|
+
maxPayment: options.maxPayment
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2249
|
+
async function getX402PayerBalances(options) {
|
|
2250
|
+
assertPrivateKey(options.rootPrivateKey, "rootPrivateKey");
|
|
2251
|
+
const start = normalizePayerIndex(options.startIndex ?? 0n);
|
|
2252
|
+
const count = options.count ?? 16;
|
|
2253
|
+
if (!Number.isInteger(count) || count <= 0 || count > 256) {
|
|
2254
|
+
throw new Error("count must be an integer between 1 and 256");
|
|
2255
|
+
}
|
|
2256
|
+
const publicClient = viem.createPublicClient({
|
|
2257
|
+
chain: chains.base,
|
|
2258
|
+
transport: viem.http(options.rpcUrl)
|
|
2259
|
+
});
|
|
2260
|
+
const results = [];
|
|
2261
|
+
for (let i = 0; i < count; i++) {
|
|
2262
|
+
const index = start + BigInt(i);
|
|
2263
|
+
const payerAddress = deriveX402PayerAddress(options.rootPrivateKey, index);
|
|
2264
|
+
const balance = await publicClient.readContract({
|
|
2265
|
+
address: ADDRESSES.usdcToken,
|
|
2266
|
+
abi: ERC20_ABI,
|
|
2267
|
+
functionName: "balanceOf",
|
|
2268
|
+
args: [payerAddress]
|
|
2269
|
+
});
|
|
2270
|
+
if (options.nonZeroOnly && balance === 0n) {
|
|
2271
|
+
continue;
|
|
2272
|
+
}
|
|
2273
|
+
results.push({
|
|
2274
|
+
payerIndex: index.toString(),
|
|
2275
|
+
payerAddress,
|
|
2276
|
+
usdc: viem.formatUnits(balance, USDC_DECIMALS),
|
|
2277
|
+
usdcAtomic: balance.toString()
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
2280
|
+
return results;
|
|
2281
|
+
}
|
|
1949
2282
|
async function checkRecipientRegistration(address, rpcUrl) {
|
|
1950
2283
|
const addresses = getAddresses();
|
|
1951
2284
|
const publicClient = viem.createPublicClient({
|
|
@@ -2234,7 +2567,7 @@ function createBaseClient(rpcUrl) {
|
|
|
2234
2567
|
transport: viem.http(rpcUrl)
|
|
2235
2568
|
});
|
|
2236
2569
|
}
|
|
2237
|
-
function
|
|
2570
|
+
function assertPrivateKey2(value, label) {
|
|
2238
2571
|
if (!/^0x[a-fA-F0-9]{64}$/.test(value)) {
|
|
2239
2572
|
throw new Error(`${label} must be a 0x-prefixed 32-byte hex string`);
|
|
2240
2573
|
}
|
|
@@ -2269,7 +2602,7 @@ function normalizeDeadline(deadline) {
|
|
|
2269
2602
|
return nextDeadline;
|
|
2270
2603
|
}
|
|
2271
2604
|
function deriveSubaccountChildPrivateKey(rootPrivateKey, slot) {
|
|
2272
|
-
|
|
2605
|
+
assertPrivateKey2(rootPrivateKey, "rootPrivateKey");
|
|
2273
2606
|
const normalizedSlot = normalizeSlot(slot);
|
|
2274
2607
|
return viem.keccak256(
|
|
2275
2608
|
viem.encodePacked(
|
|
@@ -2279,7 +2612,7 @@ function deriveSubaccountChildPrivateKey(rootPrivateKey, slot) {
|
|
|
2279
2612
|
);
|
|
2280
2613
|
}
|
|
2281
2614
|
function deriveSubaccountSalt(rootPrivateKey, slot) {
|
|
2282
|
-
|
|
2615
|
+
assertPrivateKey2(rootPrivateKey, "rootPrivateKey");
|
|
2283
2616
|
const normalizedSlot = normalizeSlot(slot);
|
|
2284
2617
|
return viem.keccak256(
|
|
2285
2618
|
viem.encodePacked(
|
|
@@ -2289,11 +2622,11 @@ function deriveSubaccountSalt(rootPrivateKey, slot) {
|
|
|
2289
2622
|
);
|
|
2290
2623
|
}
|
|
2291
2624
|
function deriveSubaccountChildOwner(childPrivateKey) {
|
|
2292
|
-
|
|
2625
|
+
assertPrivateKey2(childPrivateKey, "childPrivateKey");
|
|
2293
2626
|
return accounts.privateKeyToAddress(childPrivateKey);
|
|
2294
2627
|
}
|
|
2295
2628
|
function deriveSubaccountChildDepositKey(childPrivateKey) {
|
|
2296
|
-
|
|
2629
|
+
assertPrivateKey2(childPrivateKey, "childPrivateKey");
|
|
2297
2630
|
return new Keypair(childPrivateKey).depositKey();
|
|
2298
2631
|
}
|
|
2299
2632
|
async function predictSubaccountForwarder(options) {
|
|
@@ -2386,7 +2719,7 @@ function toPrivateBalanceStatus(result) {
|
|
|
2386
2719
|
}
|
|
2387
2720
|
async function getSubaccountPrivateBalance(options) {
|
|
2388
2721
|
const normalizedSlot = normalizeSlot(options.slot);
|
|
2389
|
-
|
|
2722
|
+
assertPrivateKey2(options.rootPrivateKey, "rootPrivateKey");
|
|
2390
2723
|
const childPrivateKey = deriveSubaccountChildPrivateKey(options.rootPrivateKey, normalizedSlot);
|
|
2391
2724
|
const childKeypair = new Keypair(childPrivateKey);
|
|
2392
2725
|
return getPrivateBalance({
|
|
@@ -2496,7 +2829,7 @@ function buildSubaccountWithdrawTypedData(options) {
|
|
|
2496
2829
|
};
|
|
2497
2830
|
}
|
|
2498
2831
|
async function signSubaccountWithdraw(options) {
|
|
2499
|
-
|
|
2832
|
+
assertPrivateKey2(options.childPrivateKey, "childPrivateKey");
|
|
2500
2833
|
const account = accounts.privateKeyToAccount(options.childPrivateKey);
|
|
2501
2834
|
return account.signTypedData({
|
|
2502
2835
|
domain: options.typedData.domain,
|
|
@@ -2609,7 +2942,7 @@ async function mergeSubaccount(options) {
|
|
|
2609
2942
|
onProgress
|
|
2610
2943
|
} = options;
|
|
2611
2944
|
const normalizedSlot = normalizeSlot(slot);
|
|
2612
|
-
|
|
2945
|
+
assertPrivateKey2(rootPrivateKey, "rootPrivateKey");
|
|
2613
2946
|
const poolConfig = POOL_CONFIG[pool];
|
|
2614
2947
|
const poolAddress = getPoolAddress(pool);
|
|
2615
2948
|
const childPrivateKey = deriveSubaccountChildPrivateKey(rootPrivateKey, normalizedSlot);
|
|
@@ -2768,9 +3101,10 @@ exports.deriveSubaccountChildOwner = deriveSubaccountChildOwner;
|
|
|
2768
3101
|
exports.deriveSubaccountChildPrivateKey = deriveSubaccountChildPrivateKey;
|
|
2769
3102
|
exports.deriveSubaccountSalt = deriveSubaccountSalt;
|
|
2770
3103
|
exports.deriveSubaccountSlot = deriveSubaccountSlot;
|
|
3104
|
+
exports.deriveX402PayerAddress = deriveX402PayerAddress;
|
|
3105
|
+
exports.deriveX402PayerKey = deriveX402PayerKey;
|
|
2771
3106
|
exports.findNextSubaccountWithdrawNonce = findNextSubaccountWithdrawNonce;
|
|
2772
3107
|
exports.getAddresses = getAddresses;
|
|
2773
|
-
exports.getDailyFreeRemaining = getDailyFreeRemaining;
|
|
2774
3108
|
exports.getExtDataHash = getExtDataHash;
|
|
2775
3109
|
exports.getForwarderFactoryAddress = getForwarderFactoryAddress;
|
|
2776
3110
|
exports.getMerklePath = getMerklePath;
|
|
@@ -2782,17 +3116,21 @@ exports.getRelayInfo = getRelayInfo;
|
|
|
2782
3116
|
exports.getRelayUrl = getRelayUrl;
|
|
2783
3117
|
exports.getSubaccountPrivateBalance = getSubaccountPrivateBalance;
|
|
2784
3118
|
exports.getSubaccountStatus = getSubaccountStatus;
|
|
3119
|
+
exports.getX402PayerBalances = getX402PayerBalances;
|
|
2785
3120
|
exports.isSubaccountForwarderDeployed = isSubaccountForwarderDeployed;
|
|
2786
3121
|
exports.isSubaccountWithdrawNonceUsed = isSubaccountWithdrawNonceUsed;
|
|
2787
3122
|
exports.mergeSubaccount = mergeSubaccount;
|
|
2788
3123
|
exports.mergeUtxos = mergeUtxos;
|
|
2789
3124
|
exports.packEncryptedMessage = packEncryptedMessage;
|
|
3125
|
+
exports.payX402Resource = payX402Resource;
|
|
2790
3126
|
exports.poseidonHash = poseidonHash;
|
|
2791
3127
|
exports.poseidonHash2 = poseidonHash2;
|
|
2792
3128
|
exports.predictSubaccountForwarder = predictSubaccountForwarder;
|
|
2793
3129
|
exports.prepareTransaction = prepareTransaction;
|
|
2794
3130
|
exports.prove = prove;
|
|
3131
|
+
exports.quoteX402Resource = quoteX402Resource;
|
|
2795
3132
|
exports.randomBN = randomBN;
|
|
3133
|
+
exports.selectBaseUsdcExactRequirement = selectBaseUsdcExactRequirement;
|
|
2796
3134
|
exports.selectCircuit = selectCircuit;
|
|
2797
3135
|
exports.selectUtxosForWithdraw = selectUtxosForWithdraw;
|
|
2798
3136
|
exports.shuffle = shuffle;
|
|
@@ -2803,6 +3141,8 @@ exports.toBuffer = toBuffer;
|
|
|
2803
3141
|
exports.toFixedHex = toFixedHex;
|
|
2804
3142
|
exports.transfer = transfer;
|
|
2805
3143
|
exports.unpackEncryptedMessage = unpackEncryptedMessage;
|
|
3144
|
+
exports.usdcAtomicToDecimalString = usdcAtomicToDecimalString;
|
|
3145
|
+
exports.usdcDecimalToAtomic = usdcDecimalToAtomic;
|
|
2806
3146
|
exports.withdraw = withdraw;
|
|
2807
3147
|
//# sourceMappingURL=index.cjs.map
|
|
2808
3148
|
//# sourceMappingURL=index.cjs.map
|