@dcentralab/d402-client 0.2.2 → 0.2.4
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/index.d.mts +152 -5
- package/dist/index.d.ts +152 -5
- package/dist/index.js +510 -135
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +509 -137
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -511,139 +511,6 @@ function sortPaymentRequirements(requirements, preferredNetwork) {
|
|
|
511
511
|
});
|
|
512
512
|
}
|
|
513
513
|
|
|
514
|
-
// src/client.ts
|
|
515
|
-
var D402Client = class {
|
|
516
|
-
/**
|
|
517
|
-
* Create a new D402 Client.
|
|
518
|
-
*
|
|
519
|
-
* @param config - Client configuration
|
|
520
|
-
*
|
|
521
|
-
* @example
|
|
522
|
-
* ```ts
|
|
523
|
-
* const client = new D402Client({
|
|
524
|
-
* operatorAccount: walletClient.account, // User's wallet from wagmi
|
|
525
|
-
* iatpWalletAddress: userWallet, // From createIATPWallet() or getWalletsByOwner()
|
|
526
|
-
* maxValue: 1000000n // Safety limit: 1 USDC max
|
|
527
|
-
* })
|
|
528
|
-
* ```
|
|
529
|
-
*/
|
|
530
|
-
constructor(config) {
|
|
531
|
-
this.operatorAccount = config.operatorAccount;
|
|
532
|
-
this.iatpWalletAddress = config.iatpWalletAddress || config.operatorAccount.address;
|
|
533
|
-
this.maxValue = config.maxValue;
|
|
534
|
-
this.networkFilter = config.networkFilter;
|
|
535
|
-
this.schemeFilter = config.schemeFilter || "exact";
|
|
536
|
-
this.paymentRequirementsSelector = config.paymentRequirementsSelector || selectPaymentRequirement;
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Select payment requirement from list of options.
|
|
540
|
-
*
|
|
541
|
-
* Applies configured filters (network, scheme, maxValue) to choose
|
|
542
|
-
* the appropriate payment option from the server's requirements list.
|
|
543
|
-
*
|
|
544
|
-
* @param requirements - List of payment requirements from 402 response
|
|
545
|
-
* @returns Selected payment requirement
|
|
546
|
-
*/
|
|
547
|
-
selectPaymentRequirement(requirements) {
|
|
548
|
-
return this.paymentRequirementsSelector(requirements, {
|
|
549
|
-
network: this.networkFilter,
|
|
550
|
-
scheme: this.schemeFilter,
|
|
551
|
-
maxAmount: this.maxValue
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Get the IATP wallet address used for payments.
|
|
556
|
-
*
|
|
557
|
-
* @returns IATPWallet contract address, or user's EOA address if no wallet configured
|
|
558
|
-
*/
|
|
559
|
-
getIATPWalletAddress() {
|
|
560
|
-
return this.iatpWalletAddress;
|
|
561
|
-
}
|
|
562
|
-
/**
|
|
563
|
-
* Get the user's account used for signing payments.
|
|
564
|
-
*
|
|
565
|
-
* @returns User's wallet account
|
|
566
|
-
*/
|
|
567
|
-
getOperatorAccount() {
|
|
568
|
-
return this.operatorAccount;
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
* Get the maximum payment value limit.
|
|
572
|
-
*
|
|
573
|
-
* @returns Maximum value in base units, or undefined if no limit
|
|
574
|
-
*/
|
|
575
|
-
getMaxValue() {
|
|
576
|
-
return this.maxValue;
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Fetch with automatic 402 payment handling.
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
* Flow:
|
|
583
|
-
* 1. Make request without payment
|
|
584
|
-
* 2. If 402 response, parse payment requirements
|
|
585
|
-
* 3. Select appropriate payment option
|
|
586
|
-
* 4. Sign payment with EIP-712
|
|
587
|
-
* 5. Retry request with X-Payment header
|
|
588
|
-
* 6. Return final response
|
|
589
|
-
*
|
|
590
|
-
* @param url - URL to fetch
|
|
591
|
-
* @param init - Fetch options (method, headers, body, etc.)
|
|
592
|
-
* @returns Response object (after payment if 402)
|
|
593
|
-
*
|
|
594
|
-
* @example
|
|
595
|
-
* ```ts
|
|
596
|
-
* const client = new D402Client({ operatorAccount, iatpWalletAddress })
|
|
597
|
-
*
|
|
598
|
-
* const response = await client.fetch('http://api.example.com/analyze', {
|
|
599
|
-
* method: 'POST',
|
|
600
|
-
* headers: { 'Content-Type': 'application/json' },
|
|
601
|
-
* body: JSON.stringify({ text: 'Analyze this' })
|
|
602
|
-
* })
|
|
603
|
-
*
|
|
604
|
-
* const data = await response.json()
|
|
605
|
-
* ```
|
|
606
|
-
*/
|
|
607
|
-
async fetch(url, init) {
|
|
608
|
-
const { parseAllPaymentRequirements: parseAllPaymentRequirements2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
|
|
609
|
-
const { signD402Payment: signD402Payment2 } = await Promise.resolve().then(() => (init_signer(), signer_exports));
|
|
610
|
-
const { encodePayment: encodePayment2 } = await Promise.resolve().then(() => (init_encoder(), encoder_exports));
|
|
611
|
-
let response = await fetch(url, init);
|
|
612
|
-
if (response.status !== 402) {
|
|
613
|
-
return response;
|
|
614
|
-
}
|
|
615
|
-
try {
|
|
616
|
-
const requirements = await parseAllPaymentRequirements2(response);
|
|
617
|
-
const selectedRequirement = this.selectPaymentRequirement(requirements);
|
|
618
|
-
const signedPayment = await signD402Payment2({
|
|
619
|
-
operatorAccount: this.operatorAccount,
|
|
620
|
-
paymentRequirement: selectedRequirement,
|
|
621
|
-
iatpWalletAddress: this.iatpWalletAddress
|
|
622
|
-
});
|
|
623
|
-
const paymentHeader = encodePayment2(signedPayment);
|
|
624
|
-
response = await fetch(url, {
|
|
625
|
-
...init,
|
|
626
|
-
headers: {
|
|
627
|
-
...init?.headers,
|
|
628
|
-
"X-Payment": paymentHeader,
|
|
629
|
-
"Access-Control-Expose-Headers": "X-Payment-Response"
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
return response;
|
|
633
|
-
} catch (error) {
|
|
634
|
-
throw error;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
|
|
639
|
-
// src/index.ts
|
|
640
|
-
init_signer();
|
|
641
|
-
init_parser();
|
|
642
|
-
init_encoder();
|
|
643
|
-
init_utils();
|
|
644
|
-
init_errors();
|
|
645
|
-
init_constants();
|
|
646
|
-
|
|
647
514
|
// src/contracts/abis/sepolia.json
|
|
648
515
|
var sepolia_default = {
|
|
649
516
|
sepolia: {
|
|
@@ -1213,6 +1080,25 @@ var sepolia_default = {
|
|
|
1213
1080
|
stateMutability: "nonpayable",
|
|
1214
1081
|
type: "function"
|
|
1215
1082
|
},
|
|
1083
|
+
{
|
|
1084
|
+
inputs: [
|
|
1085
|
+
{
|
|
1086
|
+
internalType: "address",
|
|
1087
|
+
name: "token",
|
|
1088
|
+
type: "address"
|
|
1089
|
+
}
|
|
1090
|
+
],
|
|
1091
|
+
name: "getAvailableBalance",
|
|
1092
|
+
outputs: [
|
|
1093
|
+
{
|
|
1094
|
+
internalType: "uint256",
|
|
1095
|
+
name: "",
|
|
1096
|
+
type: "uint256"
|
|
1097
|
+
}
|
|
1098
|
+
],
|
|
1099
|
+
stateMutability: "view",
|
|
1100
|
+
type: "function"
|
|
1101
|
+
},
|
|
1216
1102
|
{
|
|
1217
1103
|
inputs: [
|
|
1218
1104
|
{
|
|
@@ -1325,6 +1211,50 @@ var sepolia_default = {
|
|
|
1325
1211
|
stateMutability: "view",
|
|
1326
1212
|
type: "function"
|
|
1327
1213
|
},
|
|
1214
|
+
{
|
|
1215
|
+
inputs: [
|
|
1216
|
+
{
|
|
1217
|
+
internalType: "address",
|
|
1218
|
+
name: "token",
|
|
1219
|
+
type: "address"
|
|
1220
|
+
},
|
|
1221
|
+
{
|
|
1222
|
+
internalType: "uint256",
|
|
1223
|
+
name: "amount",
|
|
1224
|
+
type: "uint256"
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
internalType: "address",
|
|
1228
|
+
name: "provider",
|
|
1229
|
+
type: "address"
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
internalType: "uint256",
|
|
1233
|
+
name: "deadline",
|
|
1234
|
+
type: "uint256"
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
internalType: "string",
|
|
1238
|
+
name: "requestPath",
|
|
1239
|
+
type: "string"
|
|
1240
|
+
},
|
|
1241
|
+
{
|
|
1242
|
+
internalType: "bytes",
|
|
1243
|
+
name: "signature",
|
|
1244
|
+
type: "bytes"
|
|
1245
|
+
}
|
|
1246
|
+
],
|
|
1247
|
+
name: "isValidSettlementRequest",
|
|
1248
|
+
outputs: [
|
|
1249
|
+
{
|
|
1250
|
+
internalType: "bool",
|
|
1251
|
+
name: "",
|
|
1252
|
+
type: "bool"
|
|
1253
|
+
}
|
|
1254
|
+
],
|
|
1255
|
+
stateMutability: "view",
|
|
1256
|
+
type: "function"
|
|
1257
|
+
},
|
|
1328
1258
|
{
|
|
1329
1259
|
inputs: [],
|
|
1330
1260
|
name: "operatorAddress",
|
|
@@ -1565,6 +1495,11 @@ var sepolia_default = {
|
|
|
1565
1495
|
internalType: "address",
|
|
1566
1496
|
name: "token",
|
|
1567
1497
|
type: "address"
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
internalType: "bool",
|
|
1501
|
+
name: "sendToOwner",
|
|
1502
|
+
type: "bool"
|
|
1568
1503
|
}
|
|
1569
1504
|
],
|
|
1570
1505
|
name: "withdrawAllFromSettlement",
|
|
@@ -2554,6 +2489,31 @@ var sepolia_default = {
|
|
|
2554
2489
|
name: "EpochReleased",
|
|
2555
2490
|
type: "event"
|
|
2556
2491
|
},
|
|
2492
|
+
{
|
|
2493
|
+
anonymous: false,
|
|
2494
|
+
inputs: [
|
|
2495
|
+
{
|
|
2496
|
+
indexed: true,
|
|
2497
|
+
internalType: "address",
|
|
2498
|
+
name: "facilitator",
|
|
2499
|
+
type: "address"
|
|
2500
|
+
},
|
|
2501
|
+
{
|
|
2502
|
+
indexed: true,
|
|
2503
|
+
internalType: "address",
|
|
2504
|
+
name: "token",
|
|
2505
|
+
type: "address"
|
|
2506
|
+
},
|
|
2507
|
+
{
|
|
2508
|
+
indexed: false,
|
|
2509
|
+
internalType: "uint256",
|
|
2510
|
+
name: "amount",
|
|
2511
|
+
type: "uint256"
|
|
2512
|
+
}
|
|
2513
|
+
],
|
|
2514
|
+
name: "FacilitatorEarningsWithdrawn",
|
|
2515
|
+
type: "event"
|
|
2516
|
+
},
|
|
2557
2517
|
{
|
|
2558
2518
|
anonymous: false,
|
|
2559
2519
|
inputs: [
|
|
@@ -2972,6 +2932,11 @@ var sepolia_default = {
|
|
|
2972
2932
|
internalType: "struct IIATPSettlementLayer.SettlementRequest",
|
|
2973
2933
|
name: "req",
|
|
2974
2934
|
type: "tuple"
|
|
2935
|
+
},
|
|
2936
|
+
{
|
|
2937
|
+
internalType: "address",
|
|
2938
|
+
name: "facilitator",
|
|
2939
|
+
type: "address"
|
|
2975
2940
|
}
|
|
2976
2941
|
],
|
|
2977
2942
|
name: "_settleRequest",
|
|
@@ -3184,6 +3149,30 @@ var sepolia_default = {
|
|
|
3184
3149
|
stateMutability: "view",
|
|
3185
3150
|
type: "function"
|
|
3186
3151
|
},
|
|
3152
|
+
{
|
|
3153
|
+
inputs: [
|
|
3154
|
+
{
|
|
3155
|
+
internalType: "address",
|
|
3156
|
+
name: "",
|
|
3157
|
+
type: "address"
|
|
3158
|
+
},
|
|
3159
|
+
{
|
|
3160
|
+
internalType: "address",
|
|
3161
|
+
name: "",
|
|
3162
|
+
type: "address"
|
|
3163
|
+
}
|
|
3164
|
+
],
|
|
3165
|
+
name: "facilitatorFeeBalances",
|
|
3166
|
+
outputs: [
|
|
3167
|
+
{
|
|
3168
|
+
internalType: "uint256",
|
|
3169
|
+
name: "",
|
|
3170
|
+
type: "uint256"
|
|
3171
|
+
}
|
|
3172
|
+
],
|
|
3173
|
+
stateMutability: "view",
|
|
3174
|
+
type: "function"
|
|
3175
|
+
},
|
|
3187
3176
|
{
|
|
3188
3177
|
inputs: [
|
|
3189
3178
|
{
|
|
@@ -3304,6 +3293,30 @@ var sepolia_default = {
|
|
|
3304
3293
|
stateMutability: "view",
|
|
3305
3294
|
type: "function"
|
|
3306
3295
|
},
|
|
3296
|
+
{
|
|
3297
|
+
inputs: [
|
|
3298
|
+
{
|
|
3299
|
+
internalType: "address",
|
|
3300
|
+
name: "facilitator",
|
|
3301
|
+
type: "address"
|
|
3302
|
+
},
|
|
3303
|
+
{
|
|
3304
|
+
internalType: "address",
|
|
3305
|
+
name: "token",
|
|
3306
|
+
type: "address"
|
|
3307
|
+
}
|
|
3308
|
+
],
|
|
3309
|
+
name: "getFacilitatorEarnings",
|
|
3310
|
+
outputs: [
|
|
3311
|
+
{
|
|
3312
|
+
internalType: "uint256",
|
|
3313
|
+
name: "",
|
|
3314
|
+
type: "uint256"
|
|
3315
|
+
}
|
|
3316
|
+
],
|
|
3317
|
+
stateMutability: "view",
|
|
3318
|
+
type: "function"
|
|
3319
|
+
},
|
|
3307
3320
|
{
|
|
3308
3321
|
inputs: [
|
|
3309
3322
|
{
|
|
@@ -4012,6 +4025,30 @@ var sepolia_default = {
|
|
|
4012
4025
|
stateMutability: "view",
|
|
4013
4026
|
type: "function"
|
|
4014
4027
|
},
|
|
4028
|
+
{
|
|
4029
|
+
inputs: [
|
|
4030
|
+
{
|
|
4031
|
+
internalType: "uint256",
|
|
4032
|
+
name: "amount",
|
|
4033
|
+
type: "uint256"
|
|
4034
|
+
},
|
|
4035
|
+
{
|
|
4036
|
+
internalType: "uint256",
|
|
4037
|
+
name: "facilitatorFeePercent",
|
|
4038
|
+
type: "uint256"
|
|
4039
|
+
}
|
|
4040
|
+
],
|
|
4041
|
+
name: "validatePaymentAmount",
|
|
4042
|
+
outputs: [
|
|
4043
|
+
{
|
|
4044
|
+
internalType: "bool",
|
|
4045
|
+
name: "isValid",
|
|
4046
|
+
type: "bool"
|
|
4047
|
+
}
|
|
4048
|
+
],
|
|
4049
|
+
stateMutability: "view",
|
|
4050
|
+
type: "function"
|
|
4051
|
+
},
|
|
4015
4052
|
{
|
|
4016
4053
|
inputs: [
|
|
4017
4054
|
{
|
|
@@ -4042,6 +4079,19 @@ var sepolia_default = {
|
|
|
4042
4079
|
outputs: [],
|
|
4043
4080
|
stateMutability: "nonpayable",
|
|
4044
4081
|
type: "function"
|
|
4082
|
+
},
|
|
4083
|
+
{
|
|
4084
|
+
inputs: [
|
|
4085
|
+
{
|
|
4086
|
+
internalType: "address[]",
|
|
4087
|
+
name: "tokens",
|
|
4088
|
+
type: "address[]"
|
|
4089
|
+
}
|
|
4090
|
+
],
|
|
4091
|
+
name: "withdrawFacilitatorEarnings",
|
|
4092
|
+
outputs: [],
|
|
4093
|
+
stateMutability: "nonpayable",
|
|
4094
|
+
type: "function"
|
|
4045
4095
|
}
|
|
4046
4096
|
],
|
|
4047
4097
|
IATPWalletFactory: [
|
|
@@ -4751,9 +4801,9 @@ var implementations_default = {
|
|
|
4751
4801
|
sepolia: {
|
|
4752
4802
|
Congress: "0x94Fc9eddBd1779542b78eb92F0569762603876e2",
|
|
4753
4803
|
TraiaCongressMembersRegistry: "0x3B685403b195f16D103b42FCf56F848A278d6049",
|
|
4754
|
-
IATPWalletImplementation: "
|
|
4804
|
+
IATPWalletImplementation: "0xfE32B4ae6606F70342749AD0C62E1C7e5F84E1B4",
|
|
4755
4805
|
RoleManagerImplementation: "0x585AD85FCFBec3B1503E50b46407bF65d4006560",
|
|
4756
|
-
IATPSettlementLayerImplementation: "
|
|
4806
|
+
IATPSettlementLayerImplementation: "0x0fDd39d323EE3538c800d4A13730eecE3F0bA975",
|
|
4757
4807
|
IATPWalletFactoryImplementation: "0xA1E5a53cE5b4e78801d9394EC60D0B53390CA240"
|
|
4758
4808
|
}
|
|
4759
4809
|
};
|
|
@@ -4802,6 +4852,8 @@ function isContractDeployed(contractName, network) {
|
|
|
4802
4852
|
const abi = getContractAbi(contractName, network);
|
|
4803
4853
|
return address !== null && abi !== null;
|
|
4804
4854
|
}
|
|
4855
|
+
|
|
4856
|
+
// src/wallet.ts
|
|
4805
4857
|
async function createIATPWallet(params) {
|
|
4806
4858
|
const { ownerAccount, network = "sepolia", rpcUrl } = params;
|
|
4807
4859
|
const factoryConfig = getContractConfig("IATPWalletFactory" /* IATP_WALLET_FACTORY */, network);
|
|
@@ -4889,6 +4941,326 @@ async function getWalletsByOwner(params) {
|
|
|
4889
4941
|
});
|
|
4890
4942
|
return wallets;
|
|
4891
4943
|
}
|
|
4944
|
+
async function getAvailableBalance(params) {
|
|
4945
|
+
const { publicClient, walletAddress, tokenAddress, network = "sepolia" } = params;
|
|
4946
|
+
const walletConfig = getContractConfig("IATPWallet" /* IATP_WALLET */, network);
|
|
4947
|
+
if (!walletConfig) {
|
|
4948
|
+
throw new Error(`IATPWallet contract not found for network: ${network}`);
|
|
4949
|
+
}
|
|
4950
|
+
const balance = await publicClient.readContract({
|
|
4951
|
+
address: walletAddress,
|
|
4952
|
+
abi: walletConfig.abi,
|
|
4953
|
+
functionName: "getAvailableBalance",
|
|
4954
|
+
args: [tokenAddress]
|
|
4955
|
+
});
|
|
4956
|
+
return balance;
|
|
4957
|
+
}
|
|
4958
|
+
async function getWithdrawalRequest(params) {
|
|
4959
|
+
const { publicClient, walletAddress, tokenAddress, network = "sepolia" } = params;
|
|
4960
|
+
const walletConfig = getContractConfig("IATPWallet" /* IATP_WALLET */, network);
|
|
4961
|
+
if (!walletConfig) {
|
|
4962
|
+
throw new Error(`IATPWallet contract not found for network: ${network}`);
|
|
4963
|
+
}
|
|
4964
|
+
const result = await publicClient.readContract({
|
|
4965
|
+
address: walletAddress,
|
|
4966
|
+
abi: walletConfig.abi,
|
|
4967
|
+
functionName: "getWithdrawalRequest",
|
|
4968
|
+
args: [tokenAddress]
|
|
4969
|
+
});
|
|
4970
|
+
if (result[0] === 0n) {
|
|
4971
|
+
return null;
|
|
4972
|
+
}
|
|
4973
|
+
return result;
|
|
4974
|
+
}
|
|
4975
|
+
async function requestWithdrawal(params) {
|
|
4976
|
+
const { walletClient, publicClient, walletAddress, tokenAddress, amount, account, network = "sepolia" } = params;
|
|
4977
|
+
const walletConfig = getContractConfig("IATPWallet" /* IATP_WALLET */, network);
|
|
4978
|
+
if (!walletConfig) {
|
|
4979
|
+
throw new Error(`IATPWallet contract not found for network: ${network}`);
|
|
4980
|
+
}
|
|
4981
|
+
const data = viem.encodeFunctionData({
|
|
4982
|
+
abi: walletConfig.abi,
|
|
4983
|
+
functionName: "requestWithdrawal",
|
|
4984
|
+
args: [tokenAddress, amount]
|
|
4985
|
+
});
|
|
4986
|
+
const estimatedGas = await publicClient.estimateGas({
|
|
4987
|
+
account: account.address,
|
|
4988
|
+
to: walletAddress,
|
|
4989
|
+
data
|
|
4990
|
+
});
|
|
4991
|
+
const gasLimit = estimatedGas + estimatedGas * BigInt(20) / BigInt(100);
|
|
4992
|
+
const { request } = await publicClient.simulateContract({
|
|
4993
|
+
account,
|
|
4994
|
+
address: walletAddress,
|
|
4995
|
+
abi: walletConfig.abi,
|
|
4996
|
+
functionName: "requestWithdrawal",
|
|
4997
|
+
args: [tokenAddress, amount]
|
|
4998
|
+
});
|
|
4999
|
+
const hash = await walletClient.writeContract({
|
|
5000
|
+
...request,
|
|
5001
|
+
gas: gasLimit
|
|
5002
|
+
});
|
|
5003
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
5004
|
+
return hash;
|
|
5005
|
+
}
|
|
5006
|
+
async function executeWithdrawal(params) {
|
|
5007
|
+
const { walletClient, publicClient, walletAddress, tokenAddress, account, network = "sepolia" } = params;
|
|
5008
|
+
const walletConfig = getContractConfig("IATPWallet" /* IATP_WALLET */, network);
|
|
5009
|
+
if (!walletConfig) {
|
|
5010
|
+
throw new Error(`IATPWallet contract not found for network: ${network}`);
|
|
5011
|
+
}
|
|
5012
|
+
const data = viem.encodeFunctionData({
|
|
5013
|
+
abi: walletConfig.abi,
|
|
5014
|
+
functionName: "executeWithdrawal",
|
|
5015
|
+
args: [tokenAddress]
|
|
5016
|
+
});
|
|
5017
|
+
const estimatedGas = await publicClient.estimateGas({
|
|
5018
|
+
account: account.address,
|
|
5019
|
+
to: walletAddress,
|
|
5020
|
+
data
|
|
5021
|
+
});
|
|
5022
|
+
const gasLimit = estimatedGas + estimatedGas * BigInt(20) / BigInt(100);
|
|
5023
|
+
const { request } = await publicClient.simulateContract({
|
|
5024
|
+
account,
|
|
5025
|
+
address: walletAddress,
|
|
5026
|
+
abi: walletConfig.abi,
|
|
5027
|
+
functionName: "executeWithdrawal",
|
|
5028
|
+
args: [tokenAddress]
|
|
5029
|
+
});
|
|
5030
|
+
const hash = await walletClient.writeContract({
|
|
5031
|
+
...request,
|
|
5032
|
+
gas: gasLimit
|
|
5033
|
+
});
|
|
5034
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
5035
|
+
return hash;
|
|
5036
|
+
}
|
|
5037
|
+
|
|
5038
|
+
// src/client.ts
|
|
5039
|
+
var D402Client = class {
|
|
5040
|
+
/**
|
|
5041
|
+
* Create a new D402 Client.
|
|
5042
|
+
*
|
|
5043
|
+
* @param config - Client configuration
|
|
5044
|
+
*
|
|
5045
|
+
* @example
|
|
5046
|
+
* ```ts
|
|
5047
|
+
* const client = new D402Client({
|
|
5048
|
+
* operatorAccount: walletClient.account, // User's wallet from wagmi
|
|
5049
|
+
* iatpWalletAddress: userWallet, // From createIATPWallet() or getWalletsByOwner()
|
|
5050
|
+
* maxValue: 1000000n // Safety limit: 1 USDC max
|
|
5051
|
+
* })
|
|
5052
|
+
* ```
|
|
5053
|
+
*/
|
|
5054
|
+
constructor(config) {
|
|
5055
|
+
this.operatorAccount = config.operatorAccount;
|
|
5056
|
+
this.iatpWalletAddress = config.iatpWalletAddress;
|
|
5057
|
+
this.maxValue = config.maxValue;
|
|
5058
|
+
this.networkFilter = config.networkFilter;
|
|
5059
|
+
this.schemeFilter = config.schemeFilter || "exact";
|
|
5060
|
+
this.paymentRequirementsSelector = config.paymentRequirementsSelector || selectPaymentRequirement;
|
|
5061
|
+
}
|
|
5062
|
+
/**
|
|
5063
|
+
* Select payment requirement from list of options.
|
|
5064
|
+
*
|
|
5065
|
+
* Applies configured filters (network, scheme, maxValue) to choose
|
|
5066
|
+
* the appropriate payment option from the server's requirements list.
|
|
5067
|
+
*
|
|
5068
|
+
* @param requirements - List of payment requirements from 402 response
|
|
5069
|
+
* @returns Selected payment requirement
|
|
5070
|
+
*/
|
|
5071
|
+
selectPaymentRequirement(requirements) {
|
|
5072
|
+
return this.paymentRequirementsSelector(requirements, {
|
|
5073
|
+
network: this.networkFilter,
|
|
5074
|
+
scheme: this.schemeFilter,
|
|
5075
|
+
maxAmount: this.maxValue
|
|
5076
|
+
});
|
|
5077
|
+
}
|
|
5078
|
+
/**
|
|
5079
|
+
* Get the IATP wallet address used for payments.
|
|
5080
|
+
*
|
|
5081
|
+
* @returns IATPWallet contract address, or user's EOA address if no wallet configured
|
|
5082
|
+
*/
|
|
5083
|
+
getIATPWalletAddress() {
|
|
5084
|
+
return this.iatpWalletAddress;
|
|
5085
|
+
}
|
|
5086
|
+
/**
|
|
5087
|
+
* Get the user's account used for signing payments.
|
|
5088
|
+
*
|
|
5089
|
+
* @returns User's wallet account
|
|
5090
|
+
*/
|
|
5091
|
+
getOperatorAccount() {
|
|
5092
|
+
return this.operatorAccount;
|
|
5093
|
+
}
|
|
5094
|
+
/**
|
|
5095
|
+
* Get the maximum payment value limit.
|
|
5096
|
+
*
|
|
5097
|
+
* @returns Maximum value in base units, or undefined if no limit
|
|
5098
|
+
*/
|
|
5099
|
+
getMaxValue() {
|
|
5100
|
+
return this.maxValue;
|
|
5101
|
+
}
|
|
5102
|
+
/**
|
|
5103
|
+
* Get available balance for a token in the IATP wallet.
|
|
5104
|
+
*
|
|
5105
|
+
* @param publicClient - Viem PublicClient (from wagmi usePublicClient)
|
|
5106
|
+
* @param tokenAddress - Token contract address
|
|
5107
|
+
* @returns Available balance in token's base units (wei)
|
|
5108
|
+
*/
|
|
5109
|
+
async getAvailableBalance(publicClient, tokenAddress) {
|
|
5110
|
+
return getAvailableBalance({
|
|
5111
|
+
publicClient,
|
|
5112
|
+
walletAddress: this.iatpWalletAddress,
|
|
5113
|
+
tokenAddress
|
|
5114
|
+
});
|
|
5115
|
+
}
|
|
5116
|
+
/**
|
|
5117
|
+
* Get withdrawal request for a token.
|
|
5118
|
+
*
|
|
5119
|
+
* @param publicClient - Viem PublicClient
|
|
5120
|
+
* @param tokenAddress - Token contract address
|
|
5121
|
+
* @returns Withdrawal request: [amount, unlockTimestamp] or null if no request exists
|
|
5122
|
+
*/
|
|
5123
|
+
async getWithdrawalRequest(publicClient, tokenAddress) {
|
|
5124
|
+
return getWithdrawalRequest({
|
|
5125
|
+
publicClient,
|
|
5126
|
+
walletAddress: this.iatpWalletAddress,
|
|
5127
|
+
tokenAddress
|
|
5128
|
+
});
|
|
5129
|
+
}
|
|
5130
|
+
/**
|
|
5131
|
+
* Request a withdrawal from the IATP wallet.
|
|
5132
|
+
*
|
|
5133
|
+
* @param walletClient - Viem WalletClient (from wagmi useWalletClient)
|
|
5134
|
+
* @param publicClient - Viem PublicClient (from wagmi usePublicClient)
|
|
5135
|
+
* @param tokenAddress - Token contract address
|
|
5136
|
+
* @param amount - Amount in token's base units (wei)
|
|
5137
|
+
* @returns Transaction hash
|
|
5138
|
+
*/
|
|
5139
|
+
async requestWithdrawal(walletClient, publicClient, tokenAddress, amount) {
|
|
5140
|
+
return requestWithdrawal({
|
|
5141
|
+
walletClient,
|
|
5142
|
+
publicClient,
|
|
5143
|
+
walletAddress: this.iatpWalletAddress,
|
|
5144
|
+
tokenAddress,
|
|
5145
|
+
amount,
|
|
5146
|
+
account: this.operatorAccount
|
|
5147
|
+
});
|
|
5148
|
+
}
|
|
5149
|
+
/**
|
|
5150
|
+
* Execute a withdrawal for a token (after unlock period).
|
|
5151
|
+
*
|
|
5152
|
+
* @param walletClient - Viem WalletClient
|
|
5153
|
+
* @param publicClient - Viem PublicClient
|
|
5154
|
+
* @param tokenAddress - Token contract address
|
|
5155
|
+
* @returns Transaction hash
|
|
5156
|
+
*/
|
|
5157
|
+
async executeWithdrawal(walletClient, publicClient, tokenAddress) {
|
|
5158
|
+
return executeWithdrawal({
|
|
5159
|
+
walletClient,
|
|
5160
|
+
publicClient,
|
|
5161
|
+
walletAddress: this.iatpWalletAddress,
|
|
5162
|
+
tokenAddress,
|
|
5163
|
+
account: this.operatorAccount
|
|
5164
|
+
});
|
|
5165
|
+
}
|
|
5166
|
+
/**
|
|
5167
|
+
* Fetch with automatic 402 payment handling.
|
|
5168
|
+
*
|
|
5169
|
+
*
|
|
5170
|
+
* Flow:
|
|
5171
|
+
* 1. Make request without payment
|
|
5172
|
+
* 2. If 402 response, parse payment requirements
|
|
5173
|
+
* 3. Select appropriate payment option
|
|
5174
|
+
* 4. Sign payment with EIP-712
|
|
5175
|
+
* 5. Retry request with X-Payment header
|
|
5176
|
+
* 6. Return final response
|
|
5177
|
+
*
|
|
5178
|
+
* @param url - URL to fetch
|
|
5179
|
+
* @param init - Fetch options (method, headers, body, etc.)
|
|
5180
|
+
* @returns Response object (after payment if 402)
|
|
5181
|
+
*
|
|
5182
|
+
* @example
|
|
5183
|
+
* ```ts
|
|
5184
|
+
* const client = new D402Client({ operatorAccount, iatpWalletAddress })
|
|
5185
|
+
*
|
|
5186
|
+
* const response = await client.fetch('http://api.example.com/analyze', {
|
|
5187
|
+
* method: 'POST',
|
|
5188
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
5189
|
+
* body: JSON.stringify({ text: 'Analyze this' })
|
|
5190
|
+
* })
|
|
5191
|
+
*
|
|
5192
|
+
* const data = await response.json()
|
|
5193
|
+
* ```
|
|
5194
|
+
*/
|
|
5195
|
+
async fetch(url, init) {
|
|
5196
|
+
const { parseAllPaymentRequirements: parseAllPaymentRequirements2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
|
|
5197
|
+
const { signD402Payment: signD402Payment2 } = await Promise.resolve().then(() => (init_signer(), signer_exports));
|
|
5198
|
+
const { encodePayment: encodePayment2 } = await Promise.resolve().then(() => (init_encoder(), encoder_exports));
|
|
5199
|
+
let response = await fetch(url, init);
|
|
5200
|
+
if (response.status !== 402) {
|
|
5201
|
+
return response;
|
|
5202
|
+
}
|
|
5203
|
+
try {
|
|
5204
|
+
const requirements = await parseAllPaymentRequirements2(response);
|
|
5205
|
+
const selectedRequirement = this.selectPaymentRequirement(requirements);
|
|
5206
|
+
const signedPayment = await signD402Payment2({
|
|
5207
|
+
operatorAccount: this.operatorAccount,
|
|
5208
|
+
paymentRequirement: selectedRequirement,
|
|
5209
|
+
iatpWalletAddress: this.iatpWalletAddress
|
|
5210
|
+
});
|
|
5211
|
+
const paymentHeader = encodePayment2(signedPayment);
|
|
5212
|
+
response = await fetch(url, {
|
|
5213
|
+
...init,
|
|
5214
|
+
headers: {
|
|
5215
|
+
...init?.headers,
|
|
5216
|
+
"X-Payment": paymentHeader,
|
|
5217
|
+
"Access-Control-Expose-Headers": "X-Payment-Response"
|
|
5218
|
+
}
|
|
5219
|
+
});
|
|
5220
|
+
return response;
|
|
5221
|
+
} catch (error) {
|
|
5222
|
+
throw error;
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
};
|
|
5226
|
+
|
|
5227
|
+
// src/index.ts
|
|
5228
|
+
init_signer();
|
|
5229
|
+
init_parser();
|
|
5230
|
+
init_encoder();
|
|
5231
|
+
init_utils();
|
|
5232
|
+
init_errors();
|
|
5233
|
+
init_constants();
|
|
5234
|
+
|
|
5235
|
+
// src/settlement.ts
|
|
5236
|
+
async function getLockedBalanceForProvider(params) {
|
|
5237
|
+
const { publicClient, settlementLayerAddress, providerAddress, tokenAddress, network = "sepolia" } = params;
|
|
5238
|
+
const settlementConfig = getContractConfig("IATPSettlementLayer" /* IATP_SETTLEMENT_LAYER */, network);
|
|
5239
|
+
if (!settlementConfig) {
|
|
5240
|
+
throw new Error(`IATPSettlementLayer contract not found for network: ${network}`);
|
|
5241
|
+
}
|
|
5242
|
+
const balance = await publicClient.readContract({
|
|
5243
|
+
address: settlementLayerAddress,
|
|
5244
|
+
abi: settlementConfig.abi,
|
|
5245
|
+
functionName: "getLockedBalanceForProvider",
|
|
5246
|
+
args: [providerAddress, tokenAddress]
|
|
5247
|
+
});
|
|
5248
|
+
return balance;
|
|
5249
|
+
}
|
|
5250
|
+
async function getUnlockedBalanceForProvider(params) {
|
|
5251
|
+
const { publicClient, settlementLayerAddress, providerAddress, tokenAddress, network = "sepolia" } = params;
|
|
5252
|
+
const settlementConfig = getContractConfig("IATPSettlementLayer" /* IATP_SETTLEMENT_LAYER */, network);
|
|
5253
|
+
if (!settlementConfig) {
|
|
5254
|
+
throw new Error(`IATPSettlementLayer contract not found for network: ${network}`);
|
|
5255
|
+
}
|
|
5256
|
+
const balance = await publicClient.readContract({
|
|
5257
|
+
address: settlementLayerAddress,
|
|
5258
|
+
abi: settlementConfig.abi,
|
|
5259
|
+
functionName: "getUnlockedBalanceForProvider",
|
|
5260
|
+
args: [providerAddress, tokenAddress]
|
|
5261
|
+
});
|
|
5262
|
+
return balance;
|
|
5263
|
+
}
|
|
4892
5264
|
|
|
4893
5265
|
exports.ContractName = ContractName;
|
|
4894
5266
|
exports.D402Client = D402Client;
|
|
@@ -4901,11 +5273,14 @@ exports.findMatchingPaymentRequirement = findMatchingPaymentRequirement;
|
|
|
4901
5273
|
exports.formatMoney = formatMoney;
|
|
4902
5274
|
exports.generateNonce = generateNonce;
|
|
4903
5275
|
exports.getAllContractAddresses = getAllContractAddresses;
|
|
5276
|
+
exports.getAvailableBalance = getAvailableBalance;
|
|
4904
5277
|
exports.getChainId = getChainId;
|
|
4905
5278
|
exports.getContractAbi = getContractAbi;
|
|
4906
5279
|
exports.getContractAddress = getContractAddress;
|
|
4907
5280
|
exports.getContractConfig = getContractConfig;
|
|
4908
5281
|
exports.getCurrentTimestamp = getCurrentTimestamp;
|
|
5282
|
+
exports.getLockedBalanceForProvider = getLockedBalanceForProvider;
|
|
5283
|
+
exports.getUnlockedBalanceForProvider = getUnlockedBalanceForProvider;
|
|
4909
5284
|
exports.getUsdcAddress = getUsdcAddress;
|
|
4910
5285
|
exports.getWalletsByOwner = getWalletsByOwner;
|
|
4911
5286
|
exports.isContractDeployed = isContractDeployed;
|