uvd-x402-sdk 2.17.0 → 2.19.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/dist/adapters/index.d.mts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/backend/index.d.mts +220 -4
- package/dist/backend/index.d.ts +220 -4
- package/dist/backend/index.js +437 -5
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/index.mjs +431 -6
- package/dist/backend/index.mjs.map +1 -1
- package/dist/{index-BE5cH7oS.d.mts → index-B49n9gXd.d.mts} +1 -1
- package/dist/{index-BE5cH7oS.d.ts → index-B49n9gXd.d.ts} +1 -1
- package/dist/{index-DDrvK4em.d.ts → index-BNDjK-t2.d.ts} +2 -2
- package/dist/{index-BDLgm-Sg.d.mts → index-Df7wrPNp.d.mts} +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/providers/algorand/index.d.mts +1 -1
- package/dist/providers/algorand/index.d.ts +1 -1
- package/dist/providers/evm/index.d.mts +1 -1
- package/dist/providers/evm/index.d.ts +1 -1
- package/dist/providers/near/index.d.mts +1 -1
- package/dist/providers/near/index.d.ts +1 -1
- package/dist/providers/solana/index.d.mts +1 -1
- package/dist/providers/solana/index.d.ts +1 -1
- package/dist/providers/stellar/index.d.mts +1 -1
- package/dist/providers/stellar/index.d.ts +1 -1
- package/dist/providers/sui/index.d.mts +1 -1
- package/dist/providers/sui/index.d.ts +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/package.json +200 -200
- package/src/backend/index.ts +3444 -2825
package/dist/backend/index.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
|
|
3
10
|
// src/types/index.ts
|
|
4
11
|
var CAIP2_IDENTIFIERS = {
|
|
5
12
|
// EVM chains
|
|
@@ -1901,15 +1908,66 @@ function escrowTimeRemaining(escrow) {
|
|
|
1901
1908
|
return new Date(escrow.expiresAt).getTime() - Date.now();
|
|
1902
1909
|
}
|
|
1903
1910
|
var ERC8004_EXTENSION_ID = "8004-reputation";
|
|
1911
|
+
var MAINNET_IDENTITY = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
|
|
1912
|
+
var MAINNET_REPUTATION = "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63";
|
|
1913
|
+
var TESTNET_IDENTITY = "0x8004A818BFB912233c491871b3d84c89A494BD9e";
|
|
1914
|
+
var TESTNET_REPUTATION = "0x8004B663056A597Dffe9eCcC1965A193B7388713";
|
|
1915
|
+
var TESTNET_VALIDATION = "0x8004Cb1BF31DAf7788923b405b754f57acEB4272";
|
|
1904
1916
|
var ERC8004_CONTRACTS = {
|
|
1917
|
+
// Mainnets (7)
|
|
1905
1918
|
ethereum: {
|
|
1906
|
-
identityRegistry:
|
|
1907
|
-
reputationRegistry:
|
|
1919
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1920
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1921
|
+
},
|
|
1922
|
+
"base-mainnet": {
|
|
1923
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1924
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1925
|
+
},
|
|
1926
|
+
polygon: {
|
|
1927
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1928
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1908
1929
|
},
|
|
1930
|
+
arbitrum: {
|
|
1931
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1932
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1933
|
+
},
|
|
1934
|
+
celo: {
|
|
1935
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1936
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1937
|
+
},
|
|
1938
|
+
bsc: {
|
|
1939
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1940
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1941
|
+
},
|
|
1942
|
+
monad: {
|
|
1943
|
+
identityRegistry: MAINNET_IDENTITY,
|
|
1944
|
+
reputationRegistry: MAINNET_REPUTATION
|
|
1945
|
+
},
|
|
1946
|
+
// Testnets (5)
|
|
1909
1947
|
"ethereum-sepolia": {
|
|
1910
|
-
identityRegistry:
|
|
1911
|
-
reputationRegistry:
|
|
1912
|
-
validationRegistry:
|
|
1948
|
+
identityRegistry: TESTNET_IDENTITY,
|
|
1949
|
+
reputationRegistry: TESTNET_REPUTATION,
|
|
1950
|
+
validationRegistry: TESTNET_VALIDATION
|
|
1951
|
+
},
|
|
1952
|
+
"base-sepolia": {
|
|
1953
|
+
identityRegistry: TESTNET_IDENTITY,
|
|
1954
|
+
reputationRegistry: TESTNET_REPUTATION,
|
|
1955
|
+
validationRegistry: TESTNET_VALIDATION
|
|
1956
|
+
},
|
|
1957
|
+
"polygon-amoy": {
|
|
1958
|
+
identityRegistry: TESTNET_IDENTITY,
|
|
1959
|
+
reputationRegistry: TESTNET_REPUTATION,
|
|
1960
|
+
validationRegistry: TESTNET_VALIDATION
|
|
1961
|
+
},
|
|
1962
|
+
"arbitrum-sepolia": {
|
|
1963
|
+
identityRegistry: TESTNET_IDENTITY,
|
|
1964
|
+
reputationRegistry: TESTNET_REPUTATION,
|
|
1965
|
+
validationRegistry: TESTNET_VALIDATION
|
|
1966
|
+
},
|
|
1967
|
+
"celo-sepolia": {
|
|
1968
|
+
identityRegistry: TESTNET_IDENTITY,
|
|
1969
|
+
reputationRegistry: TESTNET_REPUTATION,
|
|
1970
|
+
validationRegistry: TESTNET_VALIDATION
|
|
1913
1971
|
}
|
|
1914
1972
|
};
|
|
1915
1973
|
var Erc8004Client = class {
|
|
@@ -2241,15 +2299,389 @@ function buildErc8004PaymentRequirements(options) {
|
|
|
2241
2299
|
}
|
|
2242
2300
|
};
|
|
2243
2301
|
}
|
|
2302
|
+
var PAYMENT_INFO_TYPEHASH = "0xae68ac7ce30c86ece8196b61a7c486d8f0061f575037fbd34e7fe4e2820c6591";
|
|
2303
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
2304
|
+
var DEPOSIT_LIMIT_USDC = "100000000";
|
|
2305
|
+
var BASE_MAINNET_CONTRACTS = {
|
|
2306
|
+
operator: "0xa06958D93135BEd7e43893897C0d9fA931EF051C",
|
|
2307
|
+
escrow: "0x320a3c35F131E5D2Fb36af56345726B298936037",
|
|
2308
|
+
tokenCollector: "0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6",
|
|
2309
|
+
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
|
|
2310
|
+
};
|
|
2311
|
+
var TIER_TIMINGS = {
|
|
2312
|
+
micro: { pre: 3600, auth: 7200, refund: 86400 },
|
|
2313
|
+
standard: { pre: 7200, auth: 86400, refund: 604800 },
|
|
2314
|
+
premium: { pre: 14400, auth: 172800, refund: 1209600 },
|
|
2315
|
+
enterprise: { pre: 86400, auth: 604800, refund: 2592e3 }
|
|
2316
|
+
};
|
|
2317
|
+
var OPERATOR_ABI = [
|
|
2318
|
+
"function release(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount)",
|
|
2319
|
+
"function refundInEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint120 amount)",
|
|
2320
|
+
"function charge(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)",
|
|
2321
|
+
"function refundPostEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)"
|
|
2322
|
+
];
|
|
2323
|
+
var AdvancedEscrowClient = class {
|
|
2324
|
+
facilitatorUrl;
|
|
2325
|
+
chainId;
|
|
2326
|
+
gasLimit;
|
|
2327
|
+
contracts;
|
|
2328
|
+
signer;
|
|
2329
|
+
// ethers.Signer
|
|
2330
|
+
payerAddress = "";
|
|
2331
|
+
constructor(signer, options = {}) {
|
|
2332
|
+
this.signer = signer;
|
|
2333
|
+
this.facilitatorUrl = (options.facilitatorUrl || "https://facilitator.ultravioletadao.xyz").replace(/\/$/, "");
|
|
2334
|
+
this.chainId = options.chainId || 8453;
|
|
2335
|
+
this.gasLimit = options.gasLimit || 3e5;
|
|
2336
|
+
this.contracts = options.contracts || BASE_MAINNET_CONTRACTS;
|
|
2337
|
+
}
|
|
2338
|
+
/**
|
|
2339
|
+
* Initialize the client (resolves signer address).
|
|
2340
|
+
* Call this before using any methods.
|
|
2341
|
+
*/
|
|
2342
|
+
async init() {
|
|
2343
|
+
this.payerAddress = await this.signer.getAddress();
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* Build a PaymentInfo struct with appropriate timing for the task tier.
|
|
2347
|
+
*
|
|
2348
|
+
* @param receiver - Worker's wallet address
|
|
2349
|
+
* @param amount - Amount in token atomic units (e.g., '5000000' for $5 USDC)
|
|
2350
|
+
* @param tier - Task tier determines timing parameters
|
|
2351
|
+
* @param salt - Random salt (auto-generated if not provided)
|
|
2352
|
+
*/
|
|
2353
|
+
buildPaymentInfo(receiver, amount, tier = "standard", salt) {
|
|
2354
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2355
|
+
const t = TIER_TIMINGS[tier];
|
|
2356
|
+
let generatedSalt = salt;
|
|
2357
|
+
if (!generatedSalt) {
|
|
2358
|
+
const bytes = new Uint8Array(32);
|
|
2359
|
+
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.getRandomValues) {
|
|
2360
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
2361
|
+
} else {
|
|
2362
|
+
const nodeCrypto = __require("crypto");
|
|
2363
|
+
const buf = nodeCrypto.randomBytes(32);
|
|
2364
|
+
bytes.set(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
|
|
2365
|
+
}
|
|
2366
|
+
generatedSalt = "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2367
|
+
}
|
|
2368
|
+
return {
|
|
2369
|
+
operator: this.contracts.operator,
|
|
2370
|
+
receiver,
|
|
2371
|
+
token: this.contracts.usdc,
|
|
2372
|
+
maxAmount: amount,
|
|
2373
|
+
preApprovalExpiry: now + t.pre,
|
|
2374
|
+
authorizationExpiry: now + t.auth,
|
|
2375
|
+
refundExpiry: now + t.refund,
|
|
2376
|
+
minFeeBps: 0,
|
|
2377
|
+
maxFeeBps: 800,
|
|
2378
|
+
feeReceiver: this.contracts.operator,
|
|
2379
|
+
salt: generatedSalt
|
|
2380
|
+
};
|
|
2381
|
+
}
|
|
2382
|
+
/**
|
|
2383
|
+
* Compute the correct nonce (with PAYMENT_INFO_TYPEHASH).
|
|
2384
|
+
* Matches the on-chain AuthCaptureEscrow nonce derivation.
|
|
2385
|
+
*/
|
|
2386
|
+
async computeNonce(paymentInfo) {
|
|
2387
|
+
const { ethers } = await import('ethers');
|
|
2388
|
+
const piTuple = ethers.AbiCoder.defaultAbiCoder().encode(
|
|
2389
|
+
["bytes32", "tuple(address,address,address,address,uint120,uint48,uint48,uint48,uint16,uint16,address,uint256)"],
|
|
2390
|
+
[
|
|
2391
|
+
PAYMENT_INFO_TYPEHASH,
|
|
2392
|
+
[
|
|
2393
|
+
paymentInfo.operator,
|
|
2394
|
+
ZERO_ADDRESS,
|
|
2395
|
+
// payer = 0 for payer-agnostic hash
|
|
2396
|
+
paymentInfo.receiver,
|
|
2397
|
+
paymentInfo.token,
|
|
2398
|
+
paymentInfo.maxAmount,
|
|
2399
|
+
paymentInfo.preApprovalExpiry,
|
|
2400
|
+
paymentInfo.authorizationExpiry,
|
|
2401
|
+
paymentInfo.refundExpiry,
|
|
2402
|
+
paymentInfo.minFeeBps,
|
|
2403
|
+
paymentInfo.maxFeeBps,
|
|
2404
|
+
paymentInfo.feeReceiver,
|
|
2405
|
+
paymentInfo.salt
|
|
2406
|
+
]
|
|
2407
|
+
]
|
|
2408
|
+
);
|
|
2409
|
+
const piHash = ethers.keccak256(piTuple);
|
|
2410
|
+
const finalEncoded = ethers.AbiCoder.defaultAbiCoder().encode(
|
|
2411
|
+
["uint256", "address", "bytes32"],
|
|
2412
|
+
[this.chainId, this.contracts.escrow, piHash]
|
|
2413
|
+
);
|
|
2414
|
+
return ethers.keccak256(finalEncoded);
|
|
2415
|
+
}
|
|
2416
|
+
/**
|
|
2417
|
+
* Sign ReceiveWithAuthorization for ERC-3009.
|
|
2418
|
+
*/
|
|
2419
|
+
async signErc3009(auth) {
|
|
2420
|
+
const domain = {
|
|
2421
|
+
name: "USD Coin",
|
|
2422
|
+
version: "2",
|
|
2423
|
+
chainId: this.chainId,
|
|
2424
|
+
verifyingContract: this.contracts.usdc
|
|
2425
|
+
};
|
|
2426
|
+
const types = {
|
|
2427
|
+
ReceiveWithAuthorization: [
|
|
2428
|
+
{ name: "from", type: "address" },
|
|
2429
|
+
{ name: "to", type: "address" },
|
|
2430
|
+
{ name: "value", type: "uint256" },
|
|
2431
|
+
{ name: "validAfter", type: "uint256" },
|
|
2432
|
+
{ name: "validBefore", type: "uint256" },
|
|
2433
|
+
{ name: "nonce", type: "bytes32" }
|
|
2434
|
+
]
|
|
2435
|
+
};
|
|
2436
|
+
const message = {
|
|
2437
|
+
from: auth.from,
|
|
2438
|
+
to: auth.to,
|
|
2439
|
+
value: auth.value,
|
|
2440
|
+
validAfter: auth.validAfter,
|
|
2441
|
+
validBefore: auth.validBefore,
|
|
2442
|
+
nonce: auth.nonce
|
|
2443
|
+
};
|
|
2444
|
+
return this.signer.signTypedData(domain, types, message);
|
|
2445
|
+
}
|
|
2446
|
+
/**
|
|
2447
|
+
* Build the on-chain PaymentInfo tuple for contract calls.
|
|
2448
|
+
*/
|
|
2449
|
+
buildTuple(pi) {
|
|
2450
|
+
return [
|
|
2451
|
+
pi.operator,
|
|
2452
|
+
this.payerAddress,
|
|
2453
|
+
pi.receiver,
|
|
2454
|
+
pi.token,
|
|
2455
|
+
pi.maxAmount,
|
|
2456
|
+
pi.preApprovalExpiry,
|
|
2457
|
+
pi.authorizationExpiry,
|
|
2458
|
+
pi.refundExpiry,
|
|
2459
|
+
pi.minFeeBps,
|
|
2460
|
+
pi.maxFeeBps,
|
|
2461
|
+
pi.feeReceiver,
|
|
2462
|
+
pi.salt
|
|
2463
|
+
];
|
|
2464
|
+
}
|
|
2465
|
+
/**
|
|
2466
|
+
* AUTHORIZE: Lock funds in escrow via the facilitator.
|
|
2467
|
+
*
|
|
2468
|
+
* Sends an ERC-3009 ReceiveWithAuthorization to the facilitator,
|
|
2469
|
+
* which calls PaymentOperator.authorize() on-chain.
|
|
2470
|
+
*/
|
|
2471
|
+
async authorize(paymentInfo) {
|
|
2472
|
+
if (!this.payerAddress) await this.init();
|
|
2473
|
+
try {
|
|
2474
|
+
const nonce = await this.computeNonce(paymentInfo);
|
|
2475
|
+
const auth = {
|
|
2476
|
+
from: this.payerAddress,
|
|
2477
|
+
to: this.contracts.tokenCollector,
|
|
2478
|
+
value: paymentInfo.maxAmount,
|
|
2479
|
+
validAfter: "0",
|
|
2480
|
+
validBefore: String(paymentInfo.preApprovalExpiry),
|
|
2481
|
+
nonce
|
|
2482
|
+
};
|
|
2483
|
+
const signature = await this.signErc3009(auth);
|
|
2484
|
+
const payload = {
|
|
2485
|
+
x402Version: 2,
|
|
2486
|
+
scheme: "escrow",
|
|
2487
|
+
payload: {
|
|
2488
|
+
authorization: auth,
|
|
2489
|
+
signature,
|
|
2490
|
+
paymentInfo
|
|
2491
|
+
},
|
|
2492
|
+
paymentRequirements: {
|
|
2493
|
+
scheme: "escrow",
|
|
2494
|
+
network: `eip155:${this.chainId}`,
|
|
2495
|
+
maxAmountRequired: paymentInfo.maxAmount,
|
|
2496
|
+
asset: this.contracts.usdc,
|
|
2497
|
+
payTo: paymentInfo.receiver,
|
|
2498
|
+
extra: {
|
|
2499
|
+
escrowAddress: this.contracts.escrow,
|
|
2500
|
+
operatorAddress: this.contracts.operator,
|
|
2501
|
+
tokenCollector: this.contracts.tokenCollector
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
};
|
|
2505
|
+
const response = await fetch(`${this.facilitatorUrl}/settle`, {
|
|
2506
|
+
method: "POST",
|
|
2507
|
+
headers: { "Content-Type": "application/json" },
|
|
2508
|
+
body: JSON.stringify(payload)
|
|
2509
|
+
});
|
|
2510
|
+
const result = await response.json();
|
|
2511
|
+
if (result.success) {
|
|
2512
|
+
return {
|
|
2513
|
+
success: true,
|
|
2514
|
+
transactionHash: result.transaction,
|
|
2515
|
+
paymentInfo,
|
|
2516
|
+
salt: paymentInfo.salt
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
return { success: false, error: result.errorReason };
|
|
2520
|
+
} catch (e) {
|
|
2521
|
+
return { success: false, error: e.message || String(e) };
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
/**
|
|
2525
|
+
* RELEASE: Capture escrowed funds to receiver (worker gets paid).
|
|
2526
|
+
*
|
|
2527
|
+
* Calls PaymentOperator.release() -> escrow.capture()
|
|
2528
|
+
*
|
|
2529
|
+
* @param paymentInfo - PaymentInfo from the authorize step
|
|
2530
|
+
* @param amount - Amount to release (defaults to maxAmount)
|
|
2531
|
+
*/
|
|
2532
|
+
async release(paymentInfo, amount) {
|
|
2533
|
+
if (!this.payerAddress) await this.init();
|
|
2534
|
+
try {
|
|
2535
|
+
const { ethers } = await import('ethers');
|
|
2536
|
+
const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);
|
|
2537
|
+
const amt = amount || paymentInfo.maxAmount;
|
|
2538
|
+
const tuple = this.buildTuple(paymentInfo);
|
|
2539
|
+
const tx = await contract.release(tuple, amt, { gasLimit: this.gasLimit });
|
|
2540
|
+
const receipt = await tx.wait();
|
|
2541
|
+
return {
|
|
2542
|
+
success: receipt.status === 1,
|
|
2543
|
+
transactionHash: receipt.hash,
|
|
2544
|
+
gasUsed: Number(receipt.gasUsed),
|
|
2545
|
+
error: receipt.status !== 1 ? "Transaction reverted" : void 0
|
|
2546
|
+
};
|
|
2547
|
+
} catch (e) {
|
|
2548
|
+
return { success: false, error: e.message || String(e) };
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
/**
|
|
2552
|
+
* REFUND IN ESCROW: Return escrowed funds to payer (cancel task).
|
|
2553
|
+
*
|
|
2554
|
+
* Calls PaymentOperator.refundInEscrow() -> escrow.partialVoid()
|
|
2555
|
+
*
|
|
2556
|
+
* @param paymentInfo - PaymentInfo from the authorize step
|
|
2557
|
+
* @param amount - Amount to refund (defaults to maxAmount)
|
|
2558
|
+
*/
|
|
2559
|
+
async refundInEscrow(paymentInfo, amount) {
|
|
2560
|
+
if (!this.payerAddress) await this.init();
|
|
2561
|
+
try {
|
|
2562
|
+
const { ethers } = await import('ethers');
|
|
2563
|
+
const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);
|
|
2564
|
+
const amt = amount || paymentInfo.maxAmount;
|
|
2565
|
+
const tuple = this.buildTuple(paymentInfo);
|
|
2566
|
+
const tx = await contract.refundInEscrow(tuple, amt, { gasLimit: this.gasLimit });
|
|
2567
|
+
const receipt = await tx.wait();
|
|
2568
|
+
return {
|
|
2569
|
+
success: receipt.status === 1,
|
|
2570
|
+
transactionHash: receipt.hash,
|
|
2571
|
+
gasUsed: Number(receipt.gasUsed),
|
|
2572
|
+
error: receipt.status !== 1 ? "Transaction reverted" : void 0
|
|
2573
|
+
};
|
|
2574
|
+
} catch (e) {
|
|
2575
|
+
return { success: false, error: e.message || String(e) };
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
/**
|
|
2579
|
+
* CHARGE: Direct instant payment (no escrow hold).
|
|
2580
|
+
*
|
|
2581
|
+
* Calls PaymentOperator.charge() -> escrow.charge()
|
|
2582
|
+
* Funds go directly from payer to receiver.
|
|
2583
|
+
*
|
|
2584
|
+
* @param paymentInfo - PaymentInfo with receiver and amount
|
|
2585
|
+
* @param amount - Amount to charge (defaults to maxAmount)
|
|
2586
|
+
*/
|
|
2587
|
+
async charge(paymentInfo, amount) {
|
|
2588
|
+
if (!this.payerAddress) await this.init();
|
|
2589
|
+
try {
|
|
2590
|
+
const { ethers } = await import('ethers');
|
|
2591
|
+
const nonce = await this.computeNonce(paymentInfo);
|
|
2592
|
+
const amt = amount || paymentInfo.maxAmount;
|
|
2593
|
+
const auth = {
|
|
2594
|
+
from: this.payerAddress,
|
|
2595
|
+
to: this.contracts.tokenCollector,
|
|
2596
|
+
value: String(amt),
|
|
2597
|
+
validAfter: "0",
|
|
2598
|
+
validBefore: String(paymentInfo.preApprovalExpiry),
|
|
2599
|
+
nonce
|
|
2600
|
+
};
|
|
2601
|
+
const signature = await this.signErc3009(auth);
|
|
2602
|
+
const collectorData = ethers.getBytes(signature);
|
|
2603
|
+
const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);
|
|
2604
|
+
const tuple = this.buildTuple(paymentInfo);
|
|
2605
|
+
const tx = await contract.charge(
|
|
2606
|
+
tuple,
|
|
2607
|
+
amt,
|
|
2608
|
+
this.contracts.tokenCollector,
|
|
2609
|
+
collectorData,
|
|
2610
|
+
{ gasLimit: this.gasLimit }
|
|
2611
|
+
);
|
|
2612
|
+
const receipt = await tx.wait();
|
|
2613
|
+
return {
|
|
2614
|
+
success: receipt.status === 1,
|
|
2615
|
+
transactionHash: receipt.hash,
|
|
2616
|
+
gasUsed: Number(receipt.gasUsed),
|
|
2617
|
+
error: receipt.status !== 1 ? "Transaction reverted" : void 0
|
|
2618
|
+
};
|
|
2619
|
+
} catch (e) {
|
|
2620
|
+
return { success: false, error: e.message || String(e) };
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
/**
|
|
2624
|
+
* REFUND POST ESCROW: Dispute refund after funds were released.
|
|
2625
|
+
*
|
|
2626
|
+
* Calls PaymentOperator.refundPostEscrow() -> escrow.refund()
|
|
2627
|
+
*
|
|
2628
|
+
* WARNING: NOT FUNCTIONAL IN PRODUCTION (as of 2026-02-03).
|
|
2629
|
+
* The protocol team has not implemented the required tokenCollector
|
|
2630
|
+
* contract. This call will fail on-chain.
|
|
2631
|
+
*
|
|
2632
|
+
* For dispute resolution, use refundInEscrow() instead: keep funds
|
|
2633
|
+
* in escrow and refund before releasing. This guarantees funds are
|
|
2634
|
+
* available and under arbiter control.
|
|
2635
|
+
*
|
|
2636
|
+
* Kept for future use when tokenCollector is implemented.
|
|
2637
|
+
*
|
|
2638
|
+
* @param paymentInfo - PaymentInfo from the original authorization
|
|
2639
|
+
* @param amount - Amount to refund (defaults to maxAmount)
|
|
2640
|
+
* @param tokenCollector - Address of token collector for refund sourcing
|
|
2641
|
+
* @param collectorData - Data for the token collector
|
|
2642
|
+
*/
|
|
2643
|
+
async refundPostEscrow(paymentInfo, amount, tokenCollector, collectorData) {
|
|
2644
|
+
if (!this.payerAddress) await this.init();
|
|
2645
|
+
try {
|
|
2646
|
+
const { ethers } = await import('ethers');
|
|
2647
|
+
const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);
|
|
2648
|
+
const amt = amount || paymentInfo.maxAmount;
|
|
2649
|
+
const tuple = this.buildTuple(paymentInfo);
|
|
2650
|
+
const tx = await contract.refundPostEscrow(
|
|
2651
|
+
tuple,
|
|
2652
|
+
amt,
|
|
2653
|
+
tokenCollector || ZERO_ADDRESS,
|
|
2654
|
+
collectorData || "0x",
|
|
2655
|
+
{ gasLimit: this.gasLimit }
|
|
2656
|
+
);
|
|
2657
|
+
const receipt = await tx.wait();
|
|
2658
|
+
return {
|
|
2659
|
+
success: receipt.status === 1,
|
|
2660
|
+
transactionHash: receipt.hash,
|
|
2661
|
+
gasUsed: Number(receipt.gasUsed),
|
|
2662
|
+
error: receipt.status !== 1 ? "Transaction reverted" : void 0
|
|
2663
|
+
};
|
|
2664
|
+
} catch (e) {
|
|
2665
|
+
return { success: false, error: e.message || String(e) };
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
};
|
|
2244
2669
|
|
|
2670
|
+
exports.AdvancedEscrowClient = AdvancedEscrowClient;
|
|
2671
|
+
exports.BASE_MAINNET_CONTRACTS = BASE_MAINNET_CONTRACTS;
|
|
2245
2672
|
exports.BazaarClient = BazaarClient;
|
|
2673
|
+
exports.DEPOSIT_LIMIT_USDC = DEPOSIT_LIMIT_USDC;
|
|
2246
2674
|
exports.ERC8004_CONTRACTS = ERC8004_CONTRACTS;
|
|
2247
2675
|
exports.ERC8004_EXTENSION_ID = ERC8004_EXTENSION_ID;
|
|
2248
2676
|
exports.Erc8004Client = Erc8004Client;
|
|
2249
2677
|
exports.EscrowClient = EscrowClient;
|
|
2250
2678
|
exports.FacilitatorClient = FacilitatorClient;
|
|
2679
|
+
exports.OPERATOR_ABI = OPERATOR_ABI;
|
|
2680
|
+
exports.PAYMENT_INFO_TYPEHASH = PAYMENT_INFO_TYPEHASH;
|
|
2681
|
+
exports.TIER_TIMINGS = TIER_TIMINGS;
|
|
2251
2682
|
exports.X402_CORS_HEADERS = X402_CORS_HEADERS;
|
|
2252
2683
|
exports.X402_HEADER_NAMES = X402_HEADER_NAMES;
|
|
2684
|
+
exports.ZERO_ADDRESS = ZERO_ADDRESS;
|
|
2253
2685
|
exports.buildErc8004PaymentRequirements = buildErc8004PaymentRequirements;
|
|
2254
2686
|
exports.buildPaymentRequirements = buildPaymentRequirements;
|
|
2255
2687
|
exports.buildSettleRequest = buildSettleRequest;
|