@dexterai/x402 2.1.0 → 3.0.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.cjs +80 -12
- package/dist/adapters/index.d.cts +2 -2
- package/dist/adapters/index.d.ts +2 -2
- package/dist/adapters/index.js +80 -12
- package/dist/client/index.cjs +166 -54
- package/dist/client/index.d.cts +182 -61
- package/dist/client/index.d.ts +182 -61
- package/dist/client/index.js +165 -53
- package/dist/react/index.cjs +86 -12
- package/dist/react/index.d.cts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +86 -12
- package/dist/{sponsored-access-Lxa11w_X.d.ts → sponsored-access-BVoucsEW.d.ts} +1 -1
- package/dist/{sponsored-access-DAVzu4x6.d.cts → sponsored-access-CE7WpV5b.d.cts} +1 -1
- package/dist/{types-D1u7iu8n.d.cts → types-C_aQh02s.d.cts} +24 -0
- package/dist/{types-YQlJI5E3.d.ts → types-DBS0XOsH.d.ts} +24 -0
- package/package.json +1 -1
package/dist/adapters/index.cjs
CHANGED
|
@@ -656,21 +656,51 @@ var EvmAdapter = class {
|
|
|
656
656
|
});
|
|
657
657
|
const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
|
|
658
658
|
const currentAllowance = await this.readAllowance(url, asset, wallet.address, PERMIT2_ADDRESS);
|
|
659
|
+
let approvalExtension;
|
|
659
660
|
if (currentAllowance < BigInt(amount)) {
|
|
660
|
-
|
|
661
|
+
const approveData = this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256);
|
|
662
|
+
if (wallet.signTransaction) {
|
|
663
|
+
this.log(`Signing Permit2 approval for relay (current allowance: ${currentAllowance})`);
|
|
664
|
+
const chainId2 = this.getChainId(accept.network);
|
|
665
|
+
const gasPrice = await this.readGasPrice(url);
|
|
666
|
+
const nonce2 = await this.readNonce(url, wallet.address);
|
|
667
|
+
const signedTx = await wallet.signTransaction({
|
|
668
|
+
to: asset,
|
|
669
|
+
data: approveData,
|
|
670
|
+
chainId: chainId2,
|
|
671
|
+
gas: 50000n,
|
|
672
|
+
// standard ERC-20 approve
|
|
673
|
+
gasPrice,
|
|
674
|
+
nonce: nonce2
|
|
675
|
+
});
|
|
676
|
+
approvalExtension = {
|
|
677
|
+
erc20ApprovalGasSponsoring: {
|
|
678
|
+
info: {
|
|
679
|
+
from: wallet.address,
|
|
680
|
+
asset,
|
|
681
|
+
spender: PERMIT2_ADDRESS,
|
|
682
|
+
amount: MAX_UINT256.toString(),
|
|
683
|
+
signedTransaction: signedTx,
|
|
684
|
+
version: "1"
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
this.log("Permit2 approval signed for facilitator relay");
|
|
689
|
+
} else if (wallet.sendTransaction) {
|
|
690
|
+
this.log(`Approving Permit2 directly (current allowance: ${currentAllowance})`);
|
|
691
|
+
const approveTxHash = await wallet.sendTransaction({
|
|
692
|
+
to: asset,
|
|
693
|
+
data: approveData,
|
|
694
|
+
value: 0n
|
|
695
|
+
});
|
|
696
|
+
this.log(`Permit2 approval tx sent: ${approveTxHash}`);
|
|
697
|
+
await this.waitForReceipt(url, approveTxHash);
|
|
698
|
+
this.log("Permit2 approval confirmed");
|
|
699
|
+
} else {
|
|
661
700
|
throw new Error(
|
|
662
|
-
"Permit2 payments require a wallet that supports sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
|
|
701
|
+
"Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
|
|
663
702
|
);
|
|
664
703
|
}
|
|
665
|
-
this.log(`Approving Permit2 for ${asset} (current allowance: ${currentAllowance})`);
|
|
666
|
-
const approveTxHash = await wallet.sendTransaction({
|
|
667
|
-
to: asset,
|
|
668
|
-
data: this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256),
|
|
669
|
-
value: 0n
|
|
670
|
-
});
|
|
671
|
-
this.log(`Permit2 approval tx sent: ${approveTxHash}`);
|
|
672
|
-
await this.waitForReceipt(url, approveTxHash);
|
|
673
|
-
this.log("Permit2 approval confirmed");
|
|
674
704
|
} else {
|
|
675
705
|
this.log("Sufficient Permit2 allowance, skipping approval");
|
|
676
706
|
}
|
|
@@ -725,7 +755,8 @@ var EvmAdapter = class {
|
|
|
725
755
|
};
|
|
726
756
|
return {
|
|
727
757
|
serialized: JSON.stringify(payload),
|
|
728
|
-
signature
|
|
758
|
+
signature,
|
|
759
|
+
extensions: approvalExtension
|
|
729
760
|
};
|
|
730
761
|
}
|
|
731
762
|
/**
|
|
@@ -794,6 +825,43 @@ var EvmAdapter = class {
|
|
|
794
825
|
}
|
|
795
826
|
throw new Error(`Approval transaction receipt timeout after ${timeoutMs}ms: ${txHash}`);
|
|
796
827
|
}
|
|
828
|
+
/**
|
|
829
|
+
* Read gas price via eth_gasPrice RPC call.
|
|
830
|
+
*/
|
|
831
|
+
async readGasPrice(rpcUrl) {
|
|
832
|
+
try {
|
|
833
|
+
const response = await fetch(rpcUrl, {
|
|
834
|
+
method: "POST",
|
|
835
|
+
headers: { "Content-Type": "application/json" },
|
|
836
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_gasPrice", params: [] })
|
|
837
|
+
});
|
|
838
|
+
const result = await response.json();
|
|
839
|
+
return result.result ? BigInt(result.result) : 50000000n;
|
|
840
|
+
} catch {
|
|
841
|
+
return 50000000n;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Read transaction count (nonce) via eth_getTransactionCount RPC call.
|
|
846
|
+
*/
|
|
847
|
+
async readNonce(rpcUrl, address) {
|
|
848
|
+
try {
|
|
849
|
+
const response = await fetch(rpcUrl, {
|
|
850
|
+
method: "POST",
|
|
851
|
+
headers: { "Content-Type": "application/json" },
|
|
852
|
+
body: JSON.stringify({
|
|
853
|
+
jsonrpc: "2.0",
|
|
854
|
+
id: 1,
|
|
855
|
+
method: "eth_getTransactionCount",
|
|
856
|
+
params: [address, "latest"]
|
|
857
|
+
})
|
|
858
|
+
});
|
|
859
|
+
const result = await response.json();
|
|
860
|
+
return result.result ? parseInt(result.result, 16) : 0;
|
|
861
|
+
} catch {
|
|
862
|
+
return 0;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
797
865
|
/**
|
|
798
866
|
* Calculate how much to approve based on the facilitator's approval strategy.
|
|
799
867
|
* Buffered approvals reduce the number of on-chain approval txs for micropayments.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { e as SolanaAdapter, f as EvmAdapter, C as ChainAdapter } from '../types-
|
|
2
|
-
export { q as ARBITRUM_ONE, s as AVALANCHE, A as AdapterConfig, B as BASE_MAINNET, p as BASE_SEPOLIA, l as BSC_MAINNET, o as BSC_STABLECOIN_ADDRESSES, n as BSC_USDC, m as BSC_USDT, d as BalanceInfo, v as ETHEREUM_MAINNET, E as EvmWallet, G as GenericWallet, O as OPTIMISM, P as PERMIT2_ADDRESS, r as POLYGON, t as SKALE_BASE, u as SKALE_BASE_SEPOLIA, h as SOLANA_DEVNET, b as SOLANA_MAINNET, j as SOLANA_TESTNET, g as SignedTransaction, S as SolanaWallet, U as USDC_ADDRESSES, W as WalletSet, X as X402_EXACT_PERMIT2_PROXY, a as createEvmAdapter, c as createSolanaAdapter, k as isEvmWallet, i as isSolanaWallet } from '../types-
|
|
1
|
+
import { e as SolanaAdapter, f as EvmAdapter, C as ChainAdapter } from '../types-C_aQh02s.cjs';
|
|
2
|
+
export { q as ARBITRUM_ONE, s as AVALANCHE, A as AdapterConfig, B as BASE_MAINNET, p as BASE_SEPOLIA, l as BSC_MAINNET, o as BSC_STABLECOIN_ADDRESSES, n as BSC_USDC, m as BSC_USDT, d as BalanceInfo, v as ETHEREUM_MAINNET, E as EvmWallet, G as GenericWallet, O as OPTIMISM, P as PERMIT2_ADDRESS, r as POLYGON, t as SKALE_BASE, u as SKALE_BASE_SEPOLIA, h as SOLANA_DEVNET, b as SOLANA_MAINNET, j as SOLANA_TESTNET, g as SignedTransaction, S as SolanaWallet, U as USDC_ADDRESSES, W as WalletSet, X as X402_EXACT_PERMIT2_PROXY, a as createEvmAdapter, c as createSolanaAdapter, k as isEvmWallet, i as isSolanaWallet } from '../types-C_aQh02s.cjs';
|
|
3
3
|
import '../types-_iT11DL0.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { e as SolanaAdapter, f as EvmAdapter, C as ChainAdapter } from '../types-
|
|
2
|
-
export { q as ARBITRUM_ONE, s as AVALANCHE, A as AdapterConfig, B as BASE_MAINNET, p as BASE_SEPOLIA, l as BSC_MAINNET, o as BSC_STABLECOIN_ADDRESSES, n as BSC_USDC, m as BSC_USDT, d as BalanceInfo, v as ETHEREUM_MAINNET, E as EvmWallet, G as GenericWallet, O as OPTIMISM, P as PERMIT2_ADDRESS, r as POLYGON, t as SKALE_BASE, u as SKALE_BASE_SEPOLIA, h as SOLANA_DEVNET, b as SOLANA_MAINNET, j as SOLANA_TESTNET, g as SignedTransaction, S as SolanaWallet, U as USDC_ADDRESSES, W as WalletSet, X as X402_EXACT_PERMIT2_PROXY, a as createEvmAdapter, c as createSolanaAdapter, k as isEvmWallet, i as isSolanaWallet } from '../types-
|
|
1
|
+
import { e as SolanaAdapter, f as EvmAdapter, C as ChainAdapter } from '../types-DBS0XOsH.js';
|
|
2
|
+
export { q as ARBITRUM_ONE, s as AVALANCHE, A as AdapterConfig, B as BASE_MAINNET, p as BASE_SEPOLIA, l as BSC_MAINNET, o as BSC_STABLECOIN_ADDRESSES, n as BSC_USDC, m as BSC_USDT, d as BalanceInfo, v as ETHEREUM_MAINNET, E as EvmWallet, G as GenericWallet, O as OPTIMISM, P as PERMIT2_ADDRESS, r as POLYGON, t as SKALE_BASE, u as SKALE_BASE_SEPOLIA, h as SOLANA_DEVNET, b as SOLANA_MAINNET, j as SOLANA_TESTNET, g as SignedTransaction, S as SolanaWallet, U as USDC_ADDRESSES, W as WalletSet, X as X402_EXACT_PERMIT2_PROXY, a as createEvmAdapter, c as createSolanaAdapter, k as isEvmWallet, i as isSolanaWallet } from '../types-DBS0XOsH.js';
|
|
3
3
|
import '../types-_iT11DL0.js';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/adapters/index.js
CHANGED
|
@@ -606,21 +606,51 @@ var EvmAdapter = class {
|
|
|
606
606
|
});
|
|
607
607
|
const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
|
|
608
608
|
const currentAllowance = await this.readAllowance(url, asset, wallet.address, PERMIT2_ADDRESS);
|
|
609
|
+
let approvalExtension;
|
|
609
610
|
if (currentAllowance < BigInt(amount)) {
|
|
610
|
-
|
|
611
|
+
const approveData = this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256);
|
|
612
|
+
if (wallet.signTransaction) {
|
|
613
|
+
this.log(`Signing Permit2 approval for relay (current allowance: ${currentAllowance})`);
|
|
614
|
+
const chainId2 = this.getChainId(accept.network);
|
|
615
|
+
const gasPrice = await this.readGasPrice(url);
|
|
616
|
+
const nonce2 = await this.readNonce(url, wallet.address);
|
|
617
|
+
const signedTx = await wallet.signTransaction({
|
|
618
|
+
to: asset,
|
|
619
|
+
data: approveData,
|
|
620
|
+
chainId: chainId2,
|
|
621
|
+
gas: 50000n,
|
|
622
|
+
// standard ERC-20 approve
|
|
623
|
+
gasPrice,
|
|
624
|
+
nonce: nonce2
|
|
625
|
+
});
|
|
626
|
+
approvalExtension = {
|
|
627
|
+
erc20ApprovalGasSponsoring: {
|
|
628
|
+
info: {
|
|
629
|
+
from: wallet.address,
|
|
630
|
+
asset,
|
|
631
|
+
spender: PERMIT2_ADDRESS,
|
|
632
|
+
amount: MAX_UINT256.toString(),
|
|
633
|
+
signedTransaction: signedTx,
|
|
634
|
+
version: "1"
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
this.log("Permit2 approval signed for facilitator relay");
|
|
639
|
+
} else if (wallet.sendTransaction) {
|
|
640
|
+
this.log(`Approving Permit2 directly (current allowance: ${currentAllowance})`);
|
|
641
|
+
const approveTxHash = await wallet.sendTransaction({
|
|
642
|
+
to: asset,
|
|
643
|
+
data: approveData,
|
|
644
|
+
value: 0n
|
|
645
|
+
});
|
|
646
|
+
this.log(`Permit2 approval tx sent: ${approveTxHash}`);
|
|
647
|
+
await this.waitForReceipt(url, approveTxHash);
|
|
648
|
+
this.log("Permit2 approval confirmed");
|
|
649
|
+
} else {
|
|
611
650
|
throw new Error(
|
|
612
|
-
"Permit2 payments require a wallet that supports sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
|
|
651
|
+
"Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
|
|
613
652
|
);
|
|
614
653
|
}
|
|
615
|
-
this.log(`Approving Permit2 for ${asset} (current allowance: ${currentAllowance})`);
|
|
616
|
-
const approveTxHash = await wallet.sendTransaction({
|
|
617
|
-
to: asset,
|
|
618
|
-
data: this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256),
|
|
619
|
-
value: 0n
|
|
620
|
-
});
|
|
621
|
-
this.log(`Permit2 approval tx sent: ${approveTxHash}`);
|
|
622
|
-
await this.waitForReceipt(url, approveTxHash);
|
|
623
|
-
this.log("Permit2 approval confirmed");
|
|
624
654
|
} else {
|
|
625
655
|
this.log("Sufficient Permit2 allowance, skipping approval");
|
|
626
656
|
}
|
|
@@ -675,7 +705,8 @@ var EvmAdapter = class {
|
|
|
675
705
|
};
|
|
676
706
|
return {
|
|
677
707
|
serialized: JSON.stringify(payload),
|
|
678
|
-
signature
|
|
708
|
+
signature,
|
|
709
|
+
extensions: approvalExtension
|
|
679
710
|
};
|
|
680
711
|
}
|
|
681
712
|
/**
|
|
@@ -744,6 +775,43 @@ var EvmAdapter = class {
|
|
|
744
775
|
}
|
|
745
776
|
throw new Error(`Approval transaction receipt timeout after ${timeoutMs}ms: ${txHash}`);
|
|
746
777
|
}
|
|
778
|
+
/**
|
|
779
|
+
* Read gas price via eth_gasPrice RPC call.
|
|
780
|
+
*/
|
|
781
|
+
async readGasPrice(rpcUrl) {
|
|
782
|
+
try {
|
|
783
|
+
const response = await fetch(rpcUrl, {
|
|
784
|
+
method: "POST",
|
|
785
|
+
headers: { "Content-Type": "application/json" },
|
|
786
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_gasPrice", params: [] })
|
|
787
|
+
});
|
|
788
|
+
const result = await response.json();
|
|
789
|
+
return result.result ? BigInt(result.result) : 50000000n;
|
|
790
|
+
} catch {
|
|
791
|
+
return 50000000n;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Read transaction count (nonce) via eth_getTransactionCount RPC call.
|
|
796
|
+
*/
|
|
797
|
+
async readNonce(rpcUrl, address) {
|
|
798
|
+
try {
|
|
799
|
+
const response = await fetch(rpcUrl, {
|
|
800
|
+
method: "POST",
|
|
801
|
+
headers: { "Content-Type": "application/json" },
|
|
802
|
+
body: JSON.stringify({
|
|
803
|
+
jsonrpc: "2.0",
|
|
804
|
+
id: 1,
|
|
805
|
+
method: "eth_getTransactionCount",
|
|
806
|
+
params: [address, "latest"]
|
|
807
|
+
})
|
|
808
|
+
});
|
|
809
|
+
const result = await response.json();
|
|
810
|
+
return result.result ? parseInt(result.result, 16) : 0;
|
|
811
|
+
} catch {
|
|
812
|
+
return 0;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
747
815
|
/**
|
|
748
816
|
* Calculate how much to approve based on the facilitator's approval strategy.
|
|
749
817
|
* Buffered approvals reduce the number of on-chain approval txs for micropayments.
|
package/dist/client/index.cjs
CHANGED
|
@@ -191,6 +191,7 @@ __export(client_exports, {
|
|
|
191
191
|
SOLANA_MAINNET: () => SOLANA_MAINNET,
|
|
192
192
|
USDC_MINT: () => USDC_MINT,
|
|
193
193
|
X402Error: () => X402Error,
|
|
194
|
+
capabilitySearch: () => capabilitySearch,
|
|
194
195
|
createBudgetAccount: () => createBudgetAccount,
|
|
195
196
|
createEvmAdapter: () => createEvmAdapter,
|
|
196
197
|
createEvmKeypairWallet: () => createEvmKeypairWallet,
|
|
@@ -203,7 +204,6 @@ __export(client_exports, {
|
|
|
203
204
|
getSponsoredRecommendations: () => getSponsoredRecommendations,
|
|
204
205
|
isEvmKeypairWallet: () => isEvmKeypairWallet,
|
|
205
206
|
isKeypairWallet: () => isKeypairWallet,
|
|
206
|
-
searchAPIs: () => searchAPIs,
|
|
207
207
|
wrapFetch: () => wrapFetch
|
|
208
208
|
});
|
|
209
209
|
module.exports = __toCommonJS(client_exports);
|
|
@@ -820,21 +820,51 @@ var EvmAdapter = class {
|
|
|
820
820
|
});
|
|
821
821
|
const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
|
|
822
822
|
const currentAllowance = await this.readAllowance(url, asset, wallet.address, PERMIT2_ADDRESS);
|
|
823
|
+
let approvalExtension;
|
|
823
824
|
if (currentAllowance < BigInt(amount)) {
|
|
824
|
-
|
|
825
|
+
const approveData = this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256);
|
|
826
|
+
if (wallet.signTransaction) {
|
|
827
|
+
this.log(`Signing Permit2 approval for relay (current allowance: ${currentAllowance})`);
|
|
828
|
+
const chainId2 = this.getChainId(accept.network);
|
|
829
|
+
const gasPrice = await this.readGasPrice(url);
|
|
830
|
+
const nonce2 = await this.readNonce(url, wallet.address);
|
|
831
|
+
const signedTx = await wallet.signTransaction({
|
|
832
|
+
to: asset,
|
|
833
|
+
data: approveData,
|
|
834
|
+
chainId: chainId2,
|
|
835
|
+
gas: 50000n,
|
|
836
|
+
// standard ERC-20 approve
|
|
837
|
+
gasPrice,
|
|
838
|
+
nonce: nonce2
|
|
839
|
+
});
|
|
840
|
+
approvalExtension = {
|
|
841
|
+
erc20ApprovalGasSponsoring: {
|
|
842
|
+
info: {
|
|
843
|
+
from: wallet.address,
|
|
844
|
+
asset,
|
|
845
|
+
spender: PERMIT2_ADDRESS,
|
|
846
|
+
amount: MAX_UINT256.toString(),
|
|
847
|
+
signedTransaction: signedTx,
|
|
848
|
+
version: "1"
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
this.log("Permit2 approval signed for facilitator relay");
|
|
853
|
+
} else if (wallet.sendTransaction) {
|
|
854
|
+
this.log(`Approving Permit2 directly (current allowance: ${currentAllowance})`);
|
|
855
|
+
const approveTxHash = await wallet.sendTransaction({
|
|
856
|
+
to: asset,
|
|
857
|
+
data: approveData,
|
|
858
|
+
value: 0n
|
|
859
|
+
});
|
|
860
|
+
this.log(`Permit2 approval tx sent: ${approveTxHash}`);
|
|
861
|
+
await this.waitForReceipt(url, approveTxHash);
|
|
862
|
+
this.log("Permit2 approval confirmed");
|
|
863
|
+
} else {
|
|
825
864
|
throw new Error(
|
|
826
|
-
"Permit2 payments require a wallet that supports sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
|
|
865
|
+
"Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
|
|
827
866
|
);
|
|
828
867
|
}
|
|
829
|
-
this.log(`Approving Permit2 for ${asset} (current allowance: ${currentAllowance})`);
|
|
830
|
-
const approveTxHash = await wallet.sendTransaction({
|
|
831
|
-
to: asset,
|
|
832
|
-
data: this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256),
|
|
833
|
-
value: 0n
|
|
834
|
-
});
|
|
835
|
-
this.log(`Permit2 approval tx sent: ${approveTxHash}`);
|
|
836
|
-
await this.waitForReceipt(url, approveTxHash);
|
|
837
|
-
this.log("Permit2 approval confirmed");
|
|
838
868
|
} else {
|
|
839
869
|
this.log("Sufficient Permit2 allowance, skipping approval");
|
|
840
870
|
}
|
|
@@ -889,7 +919,8 @@ var EvmAdapter = class {
|
|
|
889
919
|
};
|
|
890
920
|
return {
|
|
891
921
|
serialized: JSON.stringify(payload),
|
|
892
|
-
signature
|
|
922
|
+
signature,
|
|
923
|
+
extensions: approvalExtension
|
|
893
924
|
};
|
|
894
925
|
}
|
|
895
926
|
/**
|
|
@@ -958,6 +989,43 @@ var EvmAdapter = class {
|
|
|
958
989
|
}
|
|
959
990
|
throw new Error(`Approval transaction receipt timeout after ${timeoutMs}ms: ${txHash}`);
|
|
960
991
|
}
|
|
992
|
+
/**
|
|
993
|
+
* Read gas price via eth_gasPrice RPC call.
|
|
994
|
+
*/
|
|
995
|
+
async readGasPrice(rpcUrl) {
|
|
996
|
+
try {
|
|
997
|
+
const response = await fetch(rpcUrl, {
|
|
998
|
+
method: "POST",
|
|
999
|
+
headers: { "Content-Type": "application/json" },
|
|
1000
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_gasPrice", params: [] })
|
|
1001
|
+
});
|
|
1002
|
+
const result = await response.json();
|
|
1003
|
+
return result.result ? BigInt(result.result) : 50000000n;
|
|
1004
|
+
} catch {
|
|
1005
|
+
return 50000000n;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Read transaction count (nonce) via eth_getTransactionCount RPC call.
|
|
1010
|
+
*/
|
|
1011
|
+
async readNonce(rpcUrl, address) {
|
|
1012
|
+
try {
|
|
1013
|
+
const response = await fetch(rpcUrl, {
|
|
1014
|
+
method: "POST",
|
|
1015
|
+
headers: { "Content-Type": "application/json" },
|
|
1016
|
+
body: JSON.stringify({
|
|
1017
|
+
jsonrpc: "2.0",
|
|
1018
|
+
id: 1,
|
|
1019
|
+
method: "eth_getTransactionCount",
|
|
1020
|
+
params: [address, "latest"]
|
|
1021
|
+
})
|
|
1022
|
+
});
|
|
1023
|
+
const result = await response.json();
|
|
1024
|
+
return result.result ? parseInt(result.result, 16) : 0;
|
|
1025
|
+
} catch {
|
|
1026
|
+
return 0;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
961
1029
|
/**
|
|
962
1030
|
* Calculate how much to approve based on the facilitator's approval strategy.
|
|
963
1031
|
* Buffered approvals reduce the number of on-chain approval txs for micropayments.
|
|
@@ -1219,6 +1287,9 @@ function createX402Client(config) {
|
|
|
1219
1287
|
accepted: accept,
|
|
1220
1288
|
payload
|
|
1221
1289
|
};
|
|
1290
|
+
if (signedTx.extensions) {
|
|
1291
|
+
paymentSignature.extensions = signedTx.extensions;
|
|
1292
|
+
}
|
|
1222
1293
|
const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
|
|
1223
1294
|
const passResponse = await customFetch(passUrl, {
|
|
1224
1295
|
...init,
|
|
@@ -1397,6 +1468,9 @@ function createX402Client(config) {
|
|
|
1397
1468
|
accepted: accept,
|
|
1398
1469
|
payload
|
|
1399
1470
|
};
|
|
1471
|
+
if (signedTx.extensions) {
|
|
1472
|
+
paymentSignature.extensions = signedTx.extensions;
|
|
1473
|
+
}
|
|
1400
1474
|
const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
|
|
1401
1475
|
log("Retrying request with payment...");
|
|
1402
1476
|
const retryResponse = await fetchWithRetry(input, {
|
|
@@ -1525,7 +1599,16 @@ async function createEvmKeypairWallet(privateKey) {
|
|
|
1525
1599
|
const account = privateKeyToAccount(normalizedKey);
|
|
1526
1600
|
return {
|
|
1527
1601
|
address: account.address,
|
|
1528
|
-
signTypedData: (params) => account.signTypedData(params)
|
|
1602
|
+
signTypedData: (params) => account.signTypedData(params),
|
|
1603
|
+
signTransaction: (params) => account.signTransaction({
|
|
1604
|
+
to: params.to,
|
|
1605
|
+
data: params.data,
|
|
1606
|
+
chainId: params.chainId,
|
|
1607
|
+
gas: params.gas,
|
|
1608
|
+
gasPrice: params.gasPrice,
|
|
1609
|
+
nonce: params.nonce,
|
|
1610
|
+
type: "legacy"
|
|
1611
|
+
})
|
|
1529
1612
|
};
|
|
1530
1613
|
}
|
|
1531
1614
|
function isEvmKeypairWallet(wallet) {
|
|
@@ -1592,55 +1675,84 @@ function wrapFetch(fetchImpl, options) {
|
|
|
1592
1675
|
}
|
|
1593
1676
|
|
|
1594
1677
|
// src/client/discovery.ts
|
|
1595
|
-
var
|
|
1596
|
-
|
|
1678
|
+
var DEFAULT_CAPABILITY_ENDPOINT = "https://x402.dexter.cash/api/x402gle/capability";
|
|
1679
|
+
function formatPriceLabel(priceUsdc) {
|
|
1680
|
+
if (priceUsdc == null) return "price on request";
|
|
1681
|
+
if (priceUsdc === 0) return "free";
|
|
1682
|
+
if (priceUsdc < 0.01) return `$${priceUsdc.toFixed(4)}`;
|
|
1683
|
+
return `$${priceUsdc.toFixed(2)}`;
|
|
1684
|
+
}
|
|
1685
|
+
function mapResult(r) {
|
|
1686
|
+
return {
|
|
1687
|
+
resourceId: r.resourceId,
|
|
1688
|
+
name: r.displayName ?? r.resourceUrl,
|
|
1689
|
+
url: r.resourceUrl,
|
|
1690
|
+
method: r.method || "GET",
|
|
1691
|
+
price: formatPriceLabel(r.pricing.usdc),
|
|
1692
|
+
priceUsdc: r.pricing.usdc,
|
|
1693
|
+
network: r.pricing.network,
|
|
1694
|
+
description: r.description ?? "",
|
|
1695
|
+
category: r.category ?? "uncategorized",
|
|
1696
|
+
qualityScore: r.verification.qualityScore,
|
|
1697
|
+
verified: r.verification.status === "pass",
|
|
1698
|
+
verificationStatus: r.verification.status,
|
|
1699
|
+
totalCalls: r.usage.totalSettlements,
|
|
1700
|
+
totalVolumeUsdc: r.usage.totalVolumeUsdc,
|
|
1701
|
+
iconUrl: r.icon,
|
|
1702
|
+
host: r.host,
|
|
1703
|
+
gamingFlags: r.gaming.flags,
|
|
1704
|
+
gamingSuspicious: r.gaming.suspicious,
|
|
1705
|
+
tier: r.tier,
|
|
1706
|
+
similarity: Math.round(r.similarity * 1e3) / 1e3,
|
|
1707
|
+
why: r.why,
|
|
1708
|
+
score: r.score
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
async function capabilitySearch(options) {
|
|
1712
|
+
if (!options?.query || !options.query.trim()) {
|
|
1713
|
+
throw new Error("capabilitySearch: query is required");
|
|
1714
|
+
}
|
|
1597
1715
|
const {
|
|
1598
1716
|
query,
|
|
1599
|
-
category,
|
|
1600
|
-
network,
|
|
1601
|
-
maxPrice,
|
|
1602
|
-
verifiedOnly,
|
|
1603
|
-
sort = "marketplace",
|
|
1604
1717
|
limit = 20,
|
|
1605
|
-
|
|
1718
|
+
unverified,
|
|
1719
|
+
testnets,
|
|
1720
|
+
rerank,
|
|
1721
|
+
endpoint = DEFAULT_CAPABILITY_ENDPOINT
|
|
1606
1722
|
} = options;
|
|
1607
1723
|
const params = new URLSearchParams();
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
if (
|
|
1611
|
-
if (
|
|
1612
|
-
if (
|
|
1613
|
-
params.
|
|
1614
|
-
params.set("order", "desc");
|
|
1615
|
-
params.set("limit", String(Math.min(limit, 50)));
|
|
1616
|
-
const url = `${marketplaceUrl}?${params.toString()}`;
|
|
1724
|
+
params.set("q", query);
|
|
1725
|
+
params.set("limit", String(Math.min(Math.max(limit, 1), 50)));
|
|
1726
|
+
if (unverified) params.set("unverified", "true");
|
|
1727
|
+
if (testnets) params.set("testnets", "true");
|
|
1728
|
+
if (rerank === false) params.set("rerank", "false");
|
|
1729
|
+
const url = `${endpoint}?${params.toString()}`;
|
|
1617
1730
|
const response = await fetch(url, {
|
|
1618
|
-
headers: {
|
|
1619
|
-
signal: AbortSignal.timeout(
|
|
1731
|
+
headers: { Accept: "application/json" },
|
|
1732
|
+
signal: AbortSignal.timeout(2e4)
|
|
1620
1733
|
});
|
|
1621
1734
|
if (!response.ok) {
|
|
1622
|
-
|
|
1735
|
+
const body = await response.text().catch(() => "");
|
|
1736
|
+
throw new Error(`Capability search failed: ${response.status} ${body.slice(0, 400)}`);
|
|
1623
1737
|
}
|
|
1624
1738
|
const data = await response.json();
|
|
1625
|
-
if (!data.
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
lastActive: r.lastSettlementAt ?? null
|
|
1643
|
-
}));
|
|
1739
|
+
if (!data.ok) {
|
|
1740
|
+
throw new Error(
|
|
1741
|
+
`Capability search error${data.stage ? ` at stage ${data.stage}` : ""}: ${data.error ?? "unknown"}`
|
|
1742
|
+
);
|
|
1743
|
+
}
|
|
1744
|
+
return {
|
|
1745
|
+
query: data.query,
|
|
1746
|
+
strongResults: data.strongResults.map(mapResult),
|
|
1747
|
+
relatedResults: data.relatedResults.map(mapResult),
|
|
1748
|
+
strongCount: data.strongCount,
|
|
1749
|
+
relatedCount: data.relatedCount,
|
|
1750
|
+
topSimilarity: data.topSimilarity,
|
|
1751
|
+
noMatchReason: data.noMatchReason,
|
|
1752
|
+
rerank: data.rerank,
|
|
1753
|
+
intent: data.intent,
|
|
1754
|
+
durationMs: data.durationMs
|
|
1755
|
+
};
|
|
1644
1756
|
}
|
|
1645
1757
|
|
|
1646
1758
|
// src/client/budget-account.ts
|
|
@@ -1778,6 +1890,7 @@ async function fireImpressionBeacon(response) {
|
|
|
1778
1890
|
SOLANA_MAINNET,
|
|
1779
1891
|
USDC_MINT,
|
|
1780
1892
|
X402Error,
|
|
1893
|
+
capabilitySearch,
|
|
1781
1894
|
createBudgetAccount,
|
|
1782
1895
|
createEvmAdapter,
|
|
1783
1896
|
createEvmKeypairWallet,
|
|
@@ -1790,6 +1903,5 @@ async function fireImpressionBeacon(response) {
|
|
|
1790
1903
|
getSponsoredRecommendations,
|
|
1791
1904
|
isEvmKeypairWallet,
|
|
1792
1905
|
isKeypairWallet,
|
|
1793
|
-
searchAPIs,
|
|
1794
1906
|
wrapFetch
|
|
1795
1907
|
});
|