@dexterai/x402 1.7.2 → 1.8.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/dist/adapters/index.cjs +408 -412
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +6 -5
- package/dist/adapters/index.d.ts +6 -5
- package/dist/adapters/index.js +385 -415
- package/dist/adapters/index.js.map +1 -1
- package/dist/client/index.cjs +573 -549
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +6 -6
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +584 -556
- package/dist/client/index.js.map +1 -1
- package/dist/react/index.cjs +403 -399
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +399 -397
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +191 -81
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +53 -36
- package/dist/server/index.d.ts +53 -36
- package/dist/server/index.js +191 -81
- package/dist/server/index.js.map +1 -1
- package/dist/{solana-BWNn6iue.d.cts → solana-BeGAqPta.d.cts} +16 -4
- package/dist/{solana-q6Na2BF-.d.ts → solana-CQD9yMju.d.ts} +16 -4
- package/dist/{types-BzL-q-AE.d.cts → types-B477nBpg.d.cts} +7 -2
- package/dist/{types-By5Hhdmr.d.ts → types-BWnUAPvD.d.ts} +7 -2
- package/dist/{x402-client-rG7xFxSR.d.ts → x402-client-D9b3PHai.d.ts} +23 -2
- package/dist/{x402-client-BvQfgGwD.d.cts → x402-client-Dk9q2QQF.d.cts} +23 -2
- package/package.json +9 -3
package/dist/adapters/index.cjs
CHANGED
|
@@ -3,9 +3,6 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __esm = (fn, res) => function __init() {
|
|
7
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
-
};
|
|
9
6
|
var __export = (target, all) => {
|
|
10
7
|
for (var name in all)
|
|
11
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -20,446 +17,439 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
17
|
};
|
|
21
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
19
|
|
|
23
|
-
// src/adapters/
|
|
24
|
-
var
|
|
25
|
-
__export(
|
|
20
|
+
// src/adapters/index.ts
|
|
21
|
+
var adapters_exports = {};
|
|
22
|
+
__export(adapters_exports, {
|
|
23
|
+
ARBITRUM_ONE: () => ARBITRUM_ONE,
|
|
24
|
+
AVALANCHE: () => AVALANCHE,
|
|
25
|
+
BASE_MAINNET: () => BASE_MAINNET,
|
|
26
|
+
BASE_SEPOLIA: () => BASE_SEPOLIA,
|
|
27
|
+
ETHEREUM_MAINNET: () => ETHEREUM_MAINNET,
|
|
28
|
+
EvmAdapter: () => EvmAdapter,
|
|
29
|
+
OPTIMISM: () => OPTIMISM,
|
|
30
|
+
POLYGON: () => POLYGON,
|
|
31
|
+
SKALE_BASE: () => SKALE_BASE,
|
|
32
|
+
SKALE_BASE_SEPOLIA: () => SKALE_BASE_SEPOLIA,
|
|
26
33
|
SOLANA_DEVNET: () => SOLANA_DEVNET,
|
|
27
34
|
SOLANA_MAINNET: () => SOLANA_MAINNET,
|
|
28
35
|
SOLANA_TESTNET: () => SOLANA_TESTNET,
|
|
29
36
|
SolanaAdapter: () => SolanaAdapter,
|
|
37
|
+
USDC_ADDRESSES: () => USDC_ADDRESSES,
|
|
38
|
+
createDefaultAdapters: () => createDefaultAdapters,
|
|
39
|
+
createEvmAdapter: () => createEvmAdapter,
|
|
30
40
|
createSolanaAdapter: () => createSolanaAdapter,
|
|
41
|
+
findAdapter: () => findAdapter,
|
|
42
|
+
isEvmWallet: () => isEvmWallet,
|
|
31
43
|
isSolanaWallet: () => isSolanaWallet
|
|
32
44
|
});
|
|
45
|
+
module.exports = __toCommonJS(adapters_exports);
|
|
46
|
+
|
|
47
|
+
// src/adapters/solana.ts
|
|
48
|
+
var import_web3 = require("@solana/web3.js");
|
|
49
|
+
var import_spl_token = require("@solana/spl-token");
|
|
50
|
+
var SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
51
|
+
var SOLANA_DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
|
|
52
|
+
var SOLANA_TESTNET = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";
|
|
53
|
+
var DEFAULT_RPC_URLS = {
|
|
54
|
+
[SOLANA_MAINNET]: "https://api.dexter.cash/api/solana/rpc",
|
|
55
|
+
[SOLANA_DEVNET]: "https://api.devnet.solana.com",
|
|
56
|
+
[SOLANA_TESTNET]: "https://api.testnet.solana.com"
|
|
57
|
+
};
|
|
58
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT = 12e3;
|
|
59
|
+
var DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
|
|
33
60
|
function isSolanaWallet(wallet) {
|
|
34
61
|
if (!wallet || typeof wallet !== "object") return false;
|
|
35
62
|
const w = wallet;
|
|
36
63
|
return "publicKey" in w && "signTransaction" in w && typeof w.signTransaction === "function";
|
|
37
64
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
import_spl_token = require("@solana/spl-token");
|
|
47
|
-
SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
48
|
-
SOLANA_DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
|
|
49
|
-
SOLANA_TESTNET = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";
|
|
50
|
-
DEFAULT_RPC_URLS = {
|
|
51
|
-
[SOLANA_MAINNET]: "https://api.dexter.cash/api/solana/rpc",
|
|
52
|
-
[SOLANA_DEVNET]: "https://api.devnet.solana.com",
|
|
53
|
-
[SOLANA_TESTNET]: "https://api.testnet.solana.com"
|
|
65
|
+
var SolanaAdapter = class {
|
|
66
|
+
name = "Solana";
|
|
67
|
+
networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];
|
|
68
|
+
config;
|
|
69
|
+
log;
|
|
70
|
+
constructor(config = {}) {
|
|
71
|
+
this.config = config;
|
|
72
|
+
this.log = config.verbose ? console.log.bind(console, "[x402:solana]") : () => {
|
|
54
73
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
207
|
-
const message = new import_web3.TransactionMessage({
|
|
208
|
-
payerKey: feePayerPubkey,
|
|
209
|
-
recentBlockhash: blockhash,
|
|
210
|
-
instructions
|
|
211
|
-
}).compileToV0Message();
|
|
212
|
-
const transaction = new import_web3.VersionedTransaction(message);
|
|
213
|
-
const signedTx = await wallet.signTransaction(transaction);
|
|
214
|
-
this.log("Transaction signed successfully");
|
|
215
|
-
return {
|
|
216
|
-
serialized: Buffer.from(signedTx.serialize()).toString("base64")
|
|
217
|
-
};
|
|
218
|
-
}
|
|
74
|
+
}
|
|
75
|
+
canHandle(network) {
|
|
76
|
+
if (this.networks.includes(network)) return true;
|
|
77
|
+
if (network === "solana") return true;
|
|
78
|
+
if (network === "solana-devnet") return true;
|
|
79
|
+
if (network === "solana-testnet") return true;
|
|
80
|
+
if (network.startsWith("solana:")) return true;
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
getDefaultRpcUrl(network) {
|
|
84
|
+
if (this.config.rpcUrls?.[network]) {
|
|
85
|
+
return this.config.rpcUrls[network];
|
|
86
|
+
}
|
|
87
|
+
if (DEFAULT_RPC_URLS[network]) {
|
|
88
|
+
return DEFAULT_RPC_URLS[network];
|
|
89
|
+
}
|
|
90
|
+
if (network === "solana") return DEFAULT_RPC_URLS[SOLANA_MAINNET];
|
|
91
|
+
if (network === "solana-devnet") return DEFAULT_RPC_URLS[SOLANA_DEVNET];
|
|
92
|
+
if (network === "solana-testnet") return DEFAULT_RPC_URLS[SOLANA_TESTNET];
|
|
93
|
+
return DEFAULT_RPC_URLS[SOLANA_MAINNET];
|
|
94
|
+
}
|
|
95
|
+
getAddress(wallet) {
|
|
96
|
+
if (!isSolanaWallet(wallet)) return null;
|
|
97
|
+
return wallet.publicKey?.toBase58() ?? null;
|
|
98
|
+
}
|
|
99
|
+
isConnected(wallet) {
|
|
100
|
+
if (!isSolanaWallet(wallet)) return false;
|
|
101
|
+
return wallet.publicKey !== null;
|
|
102
|
+
}
|
|
103
|
+
async getBalance(accept, wallet, rpcUrl) {
|
|
104
|
+
if (!isSolanaWallet(wallet) || !wallet.publicKey) {
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
|
|
108
|
+
const connection = new import_web3.Connection(url, "confirmed");
|
|
109
|
+
const userPubkey = new import_web3.PublicKey(wallet.publicKey.toBase58());
|
|
110
|
+
const mintPubkey = new import_web3.PublicKey(accept.asset);
|
|
111
|
+
try {
|
|
112
|
+
const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
|
|
113
|
+
const programId = mintInfo?.owner.toBase58() === import_spl_token.TOKEN_2022_PROGRAM_ID.toBase58() ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
|
|
114
|
+
const ata = await (0, import_spl_token.getAssociatedTokenAddress)(
|
|
115
|
+
mintPubkey,
|
|
116
|
+
userPubkey,
|
|
117
|
+
false,
|
|
118
|
+
programId
|
|
119
|
+
);
|
|
120
|
+
const account = await (0, import_spl_token.getAccount)(connection, ata, void 0, programId);
|
|
121
|
+
const decimals = accept.extra?.decimals ?? 6;
|
|
122
|
+
return Number(account.amount) / Math.pow(10, decimals);
|
|
123
|
+
} catch {
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async buildTransaction(accept, wallet, rpcUrl) {
|
|
128
|
+
if (!isSolanaWallet(wallet)) {
|
|
129
|
+
throw new Error("Invalid Solana wallet");
|
|
130
|
+
}
|
|
131
|
+
if (!wallet.publicKey) {
|
|
132
|
+
throw new Error("Wallet not connected");
|
|
133
|
+
}
|
|
134
|
+
const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
|
|
135
|
+
const connection = new import_web3.Connection(url, "confirmed");
|
|
136
|
+
const userPubkey = new import_web3.PublicKey(wallet.publicKey.toBase58());
|
|
137
|
+
const { payTo, asset, extra } = accept;
|
|
138
|
+
const amount = accept.amount || accept.maxAmountRequired;
|
|
139
|
+
if (!amount) {
|
|
140
|
+
throw new Error("Missing amount in payment requirements");
|
|
141
|
+
}
|
|
142
|
+
if (!extra?.feePayer) {
|
|
143
|
+
throw new Error("Missing feePayer in payment requirements");
|
|
144
|
+
}
|
|
145
|
+
const feePayerPubkey = new import_web3.PublicKey(extra.feePayer);
|
|
146
|
+
const mintPubkey = new import_web3.PublicKey(asset);
|
|
147
|
+
const destinationPubkey = new import_web3.PublicKey(payTo);
|
|
148
|
+
this.log("Building transaction:", {
|
|
149
|
+
from: userPubkey.toBase58(),
|
|
150
|
+
to: payTo,
|
|
151
|
+
amount,
|
|
152
|
+
asset,
|
|
153
|
+
feePayer: extra.feePayer
|
|
154
|
+
});
|
|
155
|
+
const instructions = [];
|
|
156
|
+
instructions.push(
|
|
157
|
+
import_web3.ComputeBudgetProgram.setComputeUnitLimit({
|
|
158
|
+
units: DEFAULT_COMPUTE_UNIT_LIMIT
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
instructions.push(
|
|
162
|
+
import_web3.ComputeBudgetProgram.setComputeUnitPrice({
|
|
163
|
+
microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS
|
|
164
|
+
})
|
|
165
|
+
);
|
|
166
|
+
const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
|
|
167
|
+
if (!mintInfo) {
|
|
168
|
+
throw new Error(`Token mint ${asset} not found`);
|
|
169
|
+
}
|
|
170
|
+
const programId = mintInfo.owner.toBase58() === import_spl_token.TOKEN_2022_PROGRAM_ID.toBase58() ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
|
|
171
|
+
const mint = await (0, import_spl_token.getMint)(connection, mintPubkey, void 0, programId);
|
|
172
|
+
if (typeof extra?.decimals === "number" && mint.decimals !== extra.decimals) {
|
|
173
|
+
this.log(
|
|
174
|
+
`Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
const sourceAta = await (0, import_spl_token.getAssociatedTokenAddress)(
|
|
178
|
+
mintPubkey,
|
|
179
|
+
userPubkey,
|
|
180
|
+
false,
|
|
181
|
+
programId
|
|
182
|
+
);
|
|
183
|
+
const destinationAta = await (0, import_spl_token.getAssociatedTokenAddress)(
|
|
184
|
+
mintPubkey,
|
|
185
|
+
destinationPubkey,
|
|
186
|
+
false,
|
|
187
|
+
programId
|
|
188
|
+
);
|
|
189
|
+
const sourceAtaInfo = await connection.getAccountInfo(sourceAta, "confirmed");
|
|
190
|
+
if (!sourceAtaInfo) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`No token account found for ${asset}. Please ensure you have USDC in your wallet.`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
const destAtaInfo = await connection.getAccountInfo(destinationAta, "confirmed");
|
|
196
|
+
if (!destAtaInfo) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Seller token account not found. The seller (${payTo}) must have a USDC account.`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
const amountBigInt = BigInt(amount);
|
|
202
|
+
instructions.push(
|
|
203
|
+
(0, import_spl_token.createTransferCheckedInstruction)(
|
|
204
|
+
sourceAta,
|
|
205
|
+
mintPubkey,
|
|
206
|
+
destinationAta,
|
|
207
|
+
userPubkey,
|
|
208
|
+
amountBigInt,
|
|
209
|
+
mint.decimals,
|
|
210
|
+
[],
|
|
211
|
+
programId
|
|
212
|
+
)
|
|
213
|
+
);
|
|
214
|
+
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
215
|
+
const message = new import_web3.TransactionMessage({
|
|
216
|
+
payerKey: feePayerPubkey,
|
|
217
|
+
recentBlockhash: blockhash,
|
|
218
|
+
instructions
|
|
219
|
+
}).compileToV0Message();
|
|
220
|
+
const transaction = new import_web3.VersionedTransaction(message);
|
|
221
|
+
const signedTx = await wallet.signTransaction(transaction);
|
|
222
|
+
this.log("Transaction signed successfully");
|
|
223
|
+
return {
|
|
224
|
+
serialized: Buffer.from(signedTx.serialize()).toString("base64")
|
|
219
225
|
};
|
|
220
226
|
}
|
|
221
|
-
}
|
|
227
|
+
};
|
|
228
|
+
function createSolanaAdapter(config) {
|
|
229
|
+
return new SolanaAdapter(config);
|
|
230
|
+
}
|
|
222
231
|
|
|
223
232
|
// src/adapters/evm.ts
|
|
224
|
-
var
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
var BASE_MAINNET = "eip155:8453";
|
|
234
|
+
var BASE_SEPOLIA = "eip155:84532";
|
|
235
|
+
var ARBITRUM_ONE = "eip155:42161";
|
|
236
|
+
var POLYGON = "eip155:137";
|
|
237
|
+
var OPTIMISM = "eip155:10";
|
|
238
|
+
var AVALANCHE = "eip155:43114";
|
|
239
|
+
var SKALE_BASE = "eip155:1187947933";
|
|
240
|
+
var SKALE_BASE_SEPOLIA = "eip155:324705682";
|
|
241
|
+
var ETHEREUM_MAINNET = "eip155:1";
|
|
242
|
+
var CHAIN_IDS = {
|
|
243
|
+
[BASE_MAINNET]: 8453,
|
|
244
|
+
[BASE_SEPOLIA]: 84532,
|
|
245
|
+
[ARBITRUM_ONE]: 42161,
|
|
246
|
+
[POLYGON]: 137,
|
|
247
|
+
[OPTIMISM]: 10,
|
|
248
|
+
[AVALANCHE]: 43114,
|
|
249
|
+
[SKALE_BASE]: 1187947933,
|
|
250
|
+
[SKALE_BASE_SEPOLIA]: 324705682,
|
|
251
|
+
[ETHEREUM_MAINNET]: 1
|
|
252
|
+
};
|
|
253
|
+
var DEFAULT_RPC_URLS2 = {
|
|
254
|
+
[BASE_MAINNET]: "https://api.dexter.cash/api/base/rpc",
|
|
255
|
+
[BASE_SEPOLIA]: "https://sepolia.base.org",
|
|
256
|
+
[ARBITRUM_ONE]: "https://arb1.arbitrum.io/rpc",
|
|
257
|
+
[POLYGON]: "https://polygon-rpc.com",
|
|
258
|
+
[OPTIMISM]: "https://mainnet.optimism.io",
|
|
259
|
+
[AVALANCHE]: "https://api.avax.network/ext/bc/C/rpc",
|
|
260
|
+
[SKALE_BASE]: "https://skale-base.skalenodes.com/v1/base",
|
|
261
|
+
[SKALE_BASE_SEPOLIA]: "https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",
|
|
262
|
+
[ETHEREUM_MAINNET]: "https://eth.llamarpc.com"
|
|
263
|
+
};
|
|
264
|
+
var USDC_ADDRESSES = {
|
|
265
|
+
[BASE_MAINNET]: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
266
|
+
[BASE_SEPOLIA]: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
267
|
+
[ARBITRUM_ONE]: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
268
|
+
[POLYGON]: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
269
|
+
[OPTIMISM]: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
270
|
+
[AVALANCHE]: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
271
|
+
[SKALE_BASE]: "0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",
|
|
272
|
+
[SKALE_BASE_SEPOLIA]: "0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",
|
|
273
|
+
[ETHEREUM_MAINNET]: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
274
|
+
};
|
|
235
275
|
function isEvmWallet(wallet) {
|
|
236
276
|
if (!wallet || typeof wallet !== "object") return false;
|
|
237
277
|
const w = wallet;
|
|
238
278
|
return "address" in w && typeof w.address === "string" && w.address.startsWith("0x");
|
|
239
279
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
BASE_SEPOLIA = "eip155:84532";
|
|
249
|
-
ETHEREUM_MAINNET = "eip155:1";
|
|
250
|
-
ARBITRUM_ONE = "eip155:42161";
|
|
251
|
-
CHAIN_IDS = {
|
|
252
|
-
[BASE_MAINNET]: 8453,
|
|
253
|
-
[BASE_SEPOLIA]: 84532,
|
|
254
|
-
[ETHEREUM_MAINNET]: 1,
|
|
255
|
-
[ARBITRUM_ONE]: 42161
|
|
256
|
-
};
|
|
257
|
-
DEFAULT_RPC_URLS2 = {
|
|
258
|
-
[BASE_MAINNET]: "https://api.dexter.cash/api/base/rpc",
|
|
259
|
-
[BASE_SEPOLIA]: "https://sepolia.base.org",
|
|
260
|
-
[ETHEREUM_MAINNET]: "https://eth.llamarpc.com",
|
|
261
|
-
[ARBITRUM_ONE]: "https://arb1.arbitrum.io/rpc"
|
|
280
|
+
var EvmAdapter = class {
|
|
281
|
+
name = "EVM";
|
|
282
|
+
networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];
|
|
283
|
+
config;
|
|
284
|
+
log;
|
|
285
|
+
constructor(config = {}) {
|
|
286
|
+
this.config = config;
|
|
287
|
+
this.log = config.verbose ? console.log.bind(console, "[x402:evm]") : () => {
|
|
262
288
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const data = this.encodeBalanceOf(wallet.address);
|
|
324
|
-
const response = await fetch(url, {
|
|
325
|
-
method: "POST",
|
|
326
|
-
headers: { "Content-Type": "application/json" },
|
|
327
|
-
body: JSON.stringify({
|
|
328
|
-
jsonrpc: "2.0",
|
|
329
|
-
id: 1,
|
|
330
|
-
method: "eth_call",
|
|
331
|
-
params: [
|
|
332
|
-
{
|
|
333
|
-
to: accept.asset,
|
|
334
|
-
data
|
|
335
|
-
},
|
|
336
|
-
"latest"
|
|
337
|
-
]
|
|
338
|
-
})
|
|
339
|
-
});
|
|
340
|
-
const result = await response.json();
|
|
341
|
-
if (result.error || !result.result) {
|
|
342
|
-
return 0;
|
|
343
|
-
}
|
|
344
|
-
const balance = BigInt(result.result);
|
|
345
|
-
const decimals = accept.extra?.decimals ?? 6;
|
|
346
|
-
return Number(balance) / Math.pow(10, decimals);
|
|
347
|
-
} catch {
|
|
348
|
-
return 0;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
encodeBalanceOf(address) {
|
|
352
|
-
const selector = "0x70a08231";
|
|
353
|
-
const paddedAddress = address.slice(2).toLowerCase().padStart(64, "0");
|
|
354
|
-
return selector + paddedAddress;
|
|
355
|
-
}
|
|
356
|
-
async buildTransaction(accept, wallet, _rpcUrl) {
|
|
357
|
-
if (!isEvmWallet(wallet)) {
|
|
358
|
-
throw new Error("Invalid EVM wallet");
|
|
359
|
-
}
|
|
360
|
-
if (!wallet.address) {
|
|
361
|
-
throw new Error("Wallet not connected");
|
|
362
|
-
}
|
|
363
|
-
const { payTo, asset, extra } = accept;
|
|
364
|
-
const amount = accept.amount || accept.maxAmountRequired;
|
|
365
|
-
if (!amount) {
|
|
366
|
-
throw new Error("Missing amount in payment requirements");
|
|
367
|
-
}
|
|
368
|
-
this.log("Building EVM transaction:", {
|
|
369
|
-
from: wallet.address,
|
|
370
|
-
to: payTo,
|
|
371
|
-
amount,
|
|
372
|
-
asset,
|
|
373
|
-
network: accept.network
|
|
374
|
-
});
|
|
375
|
-
const chainId = this.getChainId(accept.network);
|
|
376
|
-
const domain = {
|
|
377
|
-
name: extra?.name ?? "USD Coin",
|
|
378
|
-
version: extra?.version ?? "2",
|
|
379
|
-
chainId: BigInt(chainId),
|
|
380
|
-
verifyingContract: asset
|
|
381
|
-
};
|
|
382
|
-
const types = {
|
|
383
|
-
TransferWithAuthorization: [
|
|
384
|
-
{ name: "from", type: "address" },
|
|
385
|
-
{ name: "to", type: "address" },
|
|
386
|
-
{ name: "value", type: "uint256" },
|
|
387
|
-
{ name: "validAfter", type: "uint256" },
|
|
388
|
-
{ name: "validBefore", type: "uint256" },
|
|
389
|
-
{ name: "nonce", type: "bytes32" }
|
|
289
|
+
}
|
|
290
|
+
canHandle(network) {
|
|
291
|
+
if (this.networks.includes(network)) return true;
|
|
292
|
+
if (network === "base") return true;
|
|
293
|
+
if (network === "ethereum") return true;
|
|
294
|
+
if (network === "arbitrum") return true;
|
|
295
|
+
if (network.startsWith("eip155:")) return true;
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
getDefaultRpcUrl(network) {
|
|
299
|
+
if (this.config.rpcUrls?.[network]) {
|
|
300
|
+
return this.config.rpcUrls[network];
|
|
301
|
+
}
|
|
302
|
+
if (DEFAULT_RPC_URLS2[network]) {
|
|
303
|
+
return DEFAULT_RPC_URLS2[network];
|
|
304
|
+
}
|
|
305
|
+
if (network === "base") return DEFAULT_RPC_URLS2[BASE_MAINNET];
|
|
306
|
+
if (network === "ethereum") return DEFAULT_RPC_URLS2[ETHEREUM_MAINNET];
|
|
307
|
+
if (network === "arbitrum") return DEFAULT_RPC_URLS2[ARBITRUM_ONE];
|
|
308
|
+
return DEFAULT_RPC_URLS2[BASE_MAINNET];
|
|
309
|
+
}
|
|
310
|
+
getAddress(wallet) {
|
|
311
|
+
if (!isEvmWallet(wallet)) return null;
|
|
312
|
+
return wallet.address;
|
|
313
|
+
}
|
|
314
|
+
isConnected(wallet) {
|
|
315
|
+
if (!isEvmWallet(wallet)) return false;
|
|
316
|
+
return !!wallet.address;
|
|
317
|
+
}
|
|
318
|
+
getChainId(network) {
|
|
319
|
+
if (CHAIN_IDS[network]) return CHAIN_IDS[network];
|
|
320
|
+
if (network.startsWith("eip155:")) {
|
|
321
|
+
const chainIdStr = network.split(":")[1];
|
|
322
|
+
return parseInt(chainIdStr, 10);
|
|
323
|
+
}
|
|
324
|
+
if (network === "base") return 8453;
|
|
325
|
+
if (network === "ethereum") return 1;
|
|
326
|
+
if (network === "arbitrum") return 42161;
|
|
327
|
+
return 8453;
|
|
328
|
+
}
|
|
329
|
+
async getBalance(accept, wallet, rpcUrl) {
|
|
330
|
+
if (!isEvmWallet(wallet) || !wallet.address) {
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
|
|
334
|
+
try {
|
|
335
|
+
const data = this.encodeBalanceOf(wallet.address);
|
|
336
|
+
const response = await fetch(url, {
|
|
337
|
+
method: "POST",
|
|
338
|
+
headers: { "Content-Type": "application/json" },
|
|
339
|
+
body: JSON.stringify({
|
|
340
|
+
jsonrpc: "2.0",
|
|
341
|
+
id: 1,
|
|
342
|
+
method: "eth_call",
|
|
343
|
+
params: [
|
|
344
|
+
{
|
|
345
|
+
to: accept.asset,
|
|
346
|
+
data
|
|
347
|
+
},
|
|
348
|
+
"latest"
|
|
390
349
|
]
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
to: payTo,
|
|
397
|
-
value: amount,
|
|
398
|
-
// string
|
|
399
|
-
validAfter: String(now - 600),
|
|
400
|
-
// 10 minutes before (matching upstream)
|
|
401
|
-
validBefore: String(now + (accept.maxTimeoutSeconds || 60)),
|
|
402
|
-
nonce
|
|
403
|
-
};
|
|
404
|
-
const message = {
|
|
405
|
-
from: wallet.address,
|
|
406
|
-
to: payTo,
|
|
407
|
-
value: BigInt(amount),
|
|
408
|
-
validAfter: BigInt(now - 600),
|
|
409
|
-
validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),
|
|
410
|
-
nonce
|
|
411
|
-
};
|
|
412
|
-
if (!wallet.signTypedData) {
|
|
413
|
-
throw new Error("Wallet does not support signTypedData (EIP-712)");
|
|
414
|
-
}
|
|
415
|
-
const signature = await wallet.signTypedData({
|
|
416
|
-
domain,
|
|
417
|
-
types,
|
|
418
|
-
primaryType: "TransferWithAuthorization",
|
|
419
|
-
message
|
|
420
|
-
});
|
|
421
|
-
this.log("EIP-712 signature obtained");
|
|
422
|
-
const payload = {
|
|
423
|
-
authorization,
|
|
424
|
-
signature
|
|
425
|
-
};
|
|
426
|
-
return {
|
|
427
|
-
serialized: JSON.stringify(payload),
|
|
428
|
-
signature
|
|
429
|
-
};
|
|
350
|
+
})
|
|
351
|
+
});
|
|
352
|
+
const result = await response.json();
|
|
353
|
+
if (result.error || !result.result) {
|
|
354
|
+
return 0;
|
|
430
355
|
}
|
|
356
|
+
const balance = BigInt(result.result);
|
|
357
|
+
const decimals = accept.extra?.decimals ?? 6;
|
|
358
|
+
return Number(balance) / Math.pow(10, decimals);
|
|
359
|
+
} catch {
|
|
360
|
+
return 0;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
encodeBalanceOf(address) {
|
|
364
|
+
const selector = "0x70a08231";
|
|
365
|
+
const paddedAddress = address.slice(2).toLowerCase().padStart(64, "0");
|
|
366
|
+
return selector + paddedAddress;
|
|
367
|
+
}
|
|
368
|
+
async buildTransaction(accept, wallet, _rpcUrl) {
|
|
369
|
+
if (!isEvmWallet(wallet)) {
|
|
370
|
+
throw new Error("Invalid EVM wallet");
|
|
371
|
+
}
|
|
372
|
+
if (!wallet.address) {
|
|
373
|
+
throw new Error("Wallet not connected");
|
|
374
|
+
}
|
|
375
|
+
const { payTo, asset, extra } = accept;
|
|
376
|
+
const amount = accept.amount || accept.maxAmountRequired;
|
|
377
|
+
if (!amount) {
|
|
378
|
+
throw new Error("Missing amount in payment requirements");
|
|
379
|
+
}
|
|
380
|
+
this.log("Building EVM transaction:", {
|
|
381
|
+
from: wallet.address,
|
|
382
|
+
to: payTo,
|
|
383
|
+
amount,
|
|
384
|
+
asset,
|
|
385
|
+
network: accept.network
|
|
386
|
+
});
|
|
387
|
+
const chainId = this.getChainId(accept.network);
|
|
388
|
+
const domain = {
|
|
389
|
+
name: extra?.name ?? "USD Coin",
|
|
390
|
+
version: extra?.version ?? "2",
|
|
391
|
+
chainId: BigInt(chainId),
|
|
392
|
+
verifyingContract: asset
|
|
393
|
+
};
|
|
394
|
+
const types = {
|
|
395
|
+
TransferWithAuthorization: [
|
|
396
|
+
{ name: "from", type: "address" },
|
|
397
|
+
{ name: "to", type: "address" },
|
|
398
|
+
{ name: "value", type: "uint256" },
|
|
399
|
+
{ name: "validAfter", type: "uint256" },
|
|
400
|
+
{ name: "validBefore", type: "uint256" },
|
|
401
|
+
{ name: "nonce", type: "bytes32" }
|
|
402
|
+
]
|
|
403
|
+
};
|
|
404
|
+
const nonce = "0x" + [...Array(32)].map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, "0")).join("");
|
|
405
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
406
|
+
const authorization = {
|
|
407
|
+
from: wallet.address,
|
|
408
|
+
to: payTo,
|
|
409
|
+
value: amount,
|
|
410
|
+
// string
|
|
411
|
+
validAfter: String(now - 600),
|
|
412
|
+
// 10 minutes before (matching upstream)
|
|
413
|
+
validBefore: String(now + (accept.maxTimeoutSeconds || 60)),
|
|
414
|
+
nonce
|
|
415
|
+
};
|
|
416
|
+
const message = {
|
|
417
|
+
from: wallet.address,
|
|
418
|
+
to: payTo,
|
|
419
|
+
value: BigInt(amount),
|
|
420
|
+
validAfter: BigInt(now - 600),
|
|
421
|
+
validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),
|
|
422
|
+
nonce
|
|
423
|
+
};
|
|
424
|
+
if (!wallet.signTypedData) {
|
|
425
|
+
throw new Error("Wallet does not support signTypedData (EIP-712)");
|
|
426
|
+
}
|
|
427
|
+
const signature = await wallet.signTypedData({
|
|
428
|
+
domain,
|
|
429
|
+
types,
|
|
430
|
+
primaryType: "TransferWithAuthorization",
|
|
431
|
+
message
|
|
432
|
+
});
|
|
433
|
+
this.log("EIP-712 signature obtained");
|
|
434
|
+
const payload = {
|
|
435
|
+
authorization,
|
|
436
|
+
signature
|
|
437
|
+
};
|
|
438
|
+
return {
|
|
439
|
+
serialized: JSON.stringify(payload),
|
|
440
|
+
signature
|
|
431
441
|
};
|
|
432
442
|
}
|
|
433
|
-
}
|
|
443
|
+
};
|
|
444
|
+
function createEvmAdapter(config) {
|
|
445
|
+
return new EvmAdapter(config);
|
|
446
|
+
}
|
|
434
447
|
|
|
435
448
|
// src/adapters/index.ts
|
|
436
|
-
var adapters_exports = {};
|
|
437
|
-
__export(adapters_exports, {
|
|
438
|
-
ARBITRUM_ONE: () => ARBITRUM_ONE,
|
|
439
|
-
BASE_MAINNET: () => BASE_MAINNET,
|
|
440
|
-
BASE_SEPOLIA: () => BASE_SEPOLIA,
|
|
441
|
-
ETHEREUM_MAINNET: () => ETHEREUM_MAINNET,
|
|
442
|
-
EvmAdapter: () => EvmAdapter,
|
|
443
|
-
SOLANA_DEVNET: () => SOLANA_DEVNET,
|
|
444
|
-
SOLANA_MAINNET: () => SOLANA_MAINNET,
|
|
445
|
-
SOLANA_TESTNET: () => SOLANA_TESTNET,
|
|
446
|
-
SolanaAdapter: () => SolanaAdapter,
|
|
447
|
-
createDefaultAdapters: () => createDefaultAdapters,
|
|
448
|
-
createEvmAdapter: () => createEvmAdapter,
|
|
449
|
-
createSolanaAdapter: () => createSolanaAdapter,
|
|
450
|
-
findAdapter: () => findAdapter,
|
|
451
|
-
isEvmWallet: () => isEvmWallet,
|
|
452
|
-
isSolanaWallet: () => isSolanaWallet
|
|
453
|
-
});
|
|
454
|
-
module.exports = __toCommonJS(adapters_exports);
|
|
455
|
-
init_solana();
|
|
456
|
-
init_evm();
|
|
457
449
|
function createDefaultAdapters(verbose = false) {
|
|
458
|
-
const { createSolanaAdapter: createSolanaAdapter2 } = (init_solana(), __toCommonJS(solana_exports));
|
|
459
|
-
const { createEvmAdapter: createEvmAdapter2 } = (init_evm(), __toCommonJS(evm_exports));
|
|
460
450
|
return [
|
|
461
|
-
|
|
462
|
-
|
|
451
|
+
createSolanaAdapter({ verbose }),
|
|
452
|
+
createEvmAdapter({ verbose })
|
|
463
453
|
];
|
|
464
454
|
}
|
|
465
455
|
function findAdapter(adapters, network) {
|
|
@@ -468,14 +458,20 @@ function findAdapter(adapters, network) {
|
|
|
468
458
|
// Annotate the CommonJS export names for ESM import in node:
|
|
469
459
|
0 && (module.exports = {
|
|
470
460
|
ARBITRUM_ONE,
|
|
461
|
+
AVALANCHE,
|
|
471
462
|
BASE_MAINNET,
|
|
472
463
|
BASE_SEPOLIA,
|
|
473
464
|
ETHEREUM_MAINNET,
|
|
474
465
|
EvmAdapter,
|
|
466
|
+
OPTIMISM,
|
|
467
|
+
POLYGON,
|
|
468
|
+
SKALE_BASE,
|
|
469
|
+
SKALE_BASE_SEPOLIA,
|
|
475
470
|
SOLANA_DEVNET,
|
|
476
471
|
SOLANA_MAINNET,
|
|
477
472
|
SOLANA_TESTNET,
|
|
478
473
|
SolanaAdapter,
|
|
474
|
+
USDC_ADDRESSES,
|
|
479
475
|
createDefaultAdapters,
|
|
480
476
|
createEvmAdapter,
|
|
481
477
|
createSolanaAdapter,
|