@stableops/wallet-sdk 0.1.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/index.js ADDED
@@ -0,0 +1,655 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ EvmWalletChainConfigs: () => EvmWalletChainConfigs,
34
+ StableOpsWalletError: () => StableOpsWalletError,
35
+ encodeErc20Transfer: () => encodeErc20Transfer,
36
+ getInjectedEthereumProvider: () => getInjectedEthereumProvider,
37
+ getInjectedSolanaProvider: () => getInjectedSolanaProvider,
38
+ getInjectedTronProvider: () => getInjectedTronProvider,
39
+ getInjectedWalletProviders: () => getInjectedWalletProviders,
40
+ parseTokenAmount: () => parseTokenAmount,
41
+ selectWalletPaymentInstruction: () => selectWalletPaymentInstruction,
42
+ sendOrderWalletPayment: () => sendOrderWalletPayment,
43
+ sendWalletPayment: () => sendWalletPayment
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+ var solanaWeb3Promise;
47
+ async function loadSolanaWeb3() {
48
+ if (!solanaWeb3Promise) {
49
+ solanaWeb3Promise = import("@solana/web3.js").catch((err) => {
50
+ solanaWeb3Promise = void 0;
51
+ throw new StableOpsWalletError(
52
+ "Solana \u652F\u4ED8\u9700\u8981\u53EF\u9009\u4F9D\u8D56 @solana/web3.js\uFF0C\u8BF7\u5148\u5B89\u88C5\uFF1Anpm install @solana/web3.js",
53
+ "solana_dependency_missing",
54
+ { cause: err }
55
+ );
56
+ });
57
+ }
58
+ return solanaWeb3Promise;
59
+ }
60
+ var WALLET_TOKEN_CONTRACTS = [
61
+ {
62
+ chain: "ethereum",
63
+ asset: "USDC",
64
+ address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
65
+ decimals: 6
66
+ },
67
+ {
68
+ chain: "ethereum",
69
+ asset: "USDT",
70
+ address: "0xdac17f958d2ee523a2206206994597c13d831ec7",
71
+ decimals: 6
72
+ },
73
+ {
74
+ chain: "base",
75
+ asset: "USDC",
76
+ address: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
77
+ decimals: 6
78
+ },
79
+ {
80
+ chain: "base-sepolia",
81
+ asset: "USDC",
82
+ address: "0x036cbd53842c5426634e7929541ec2318f3dcf7e",
83
+ decimals: 6
84
+ },
85
+ {
86
+ chain: "arbitrum",
87
+ asset: "USDC",
88
+ address: "0xaf88d065e77cc2239327c5edb3a432268e5831",
89
+ decimals: 6
90
+ },
91
+ {
92
+ chain: "polygon",
93
+ asset: "USDC",
94
+ address: "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
95
+ decimals: 6
96
+ },
97
+ {
98
+ chain: "tron",
99
+ asset: "USDT",
100
+ address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
101
+ decimals: 6
102
+ },
103
+ {
104
+ chain: "solana",
105
+ asset: "USDC",
106
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
107
+ decimals: 6
108
+ },
109
+ {
110
+ chain: "solana",
111
+ asset: "USDT",
112
+ address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
113
+ decimals: 6
114
+ },
115
+ {
116
+ chain: "ethereum-sepolia",
117
+ asset: "USDC",
118
+ address: "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238",
119
+ decimals: 6
120
+ },
121
+ {
122
+ chain: "arbitrum-sepolia",
123
+ asset: "USDC",
124
+ address: "0x75faf114eafb1bdbe2f0316df893fd58ce46aa4d",
125
+ decimals: 6
126
+ },
127
+ {
128
+ chain: "polygon-amoy",
129
+ asset: "USDC",
130
+ address: "0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582",
131
+ decimals: 6
132
+ },
133
+ {
134
+ chain: "solana-devnet",
135
+ asset: "USDC",
136
+ address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
137
+ decimals: 6
138
+ },
139
+ {
140
+ chain: "tron-nile",
141
+ asset: "USDT",
142
+ address: "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf",
143
+ decimals: 6
144
+ }
145
+ ];
146
+ var EVM_WALLET_CHAINS = [
147
+ "ethereum",
148
+ "base",
149
+ "base-sepolia",
150
+ "arbitrum",
151
+ "polygon",
152
+ "ethereum-sepolia",
153
+ "arbitrum-sepolia",
154
+ "polygon-amoy"
155
+ ];
156
+ var TRON_WALLET_CHAINS = ["tron", "tron-nile"];
157
+ var SOLANA_WALLET_CHAINS = ["solana", "solana-devnet"];
158
+ var ERC20_TRANSFER_SELECTOR = "a9059cbb";
159
+ var SOLANA_MAINNET_RPC_URL = "https://api.mainnet-beta.solana.com";
160
+ var SOLANA_TOKEN_PROGRAM_ID_BASE58 = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
161
+ var SOLANA_ASSOCIATED_TOKEN_PROGRAM_ID_BASE58 = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
162
+ var SOLANA_TRANSFER_CHECKED_INSTRUCTION = 12;
163
+ var SOLANA_CREATE_ASSOCIATED_TOKEN_ACCOUNT_IDEMPOTENT_INSTRUCTION = 1;
164
+ var StableOpsWalletError = class extends Error {
165
+ constructor(message, code, details) {
166
+ super(message);
167
+ this.code = code;
168
+ this.details = details;
169
+ this.name = "StableOpsWalletError";
170
+ }
171
+ code;
172
+ details;
173
+ };
174
+ var EvmWalletChainConfigs = {
175
+ ethereum: {
176
+ chainId: "ethereum",
177
+ eip155ChainId: 1,
178
+ chainName: "Ethereum Mainnet",
179
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
180
+ rpcUrls: ["https://cloudflare-eth.com"],
181
+ blockExplorerUrls: ["https://etherscan.io"]
182
+ },
183
+ base: {
184
+ chainId: "base",
185
+ eip155ChainId: 8453,
186
+ chainName: "Base",
187
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
188
+ rpcUrls: ["https://mainnet.base.org"],
189
+ blockExplorerUrls: ["https://basescan.org"]
190
+ },
191
+ "base-sepolia": {
192
+ chainId: "base-sepolia",
193
+ eip155ChainId: 84532,
194
+ chainName: "Base Sepolia",
195
+ nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 },
196
+ rpcUrls: ["https://sepolia.base.org"],
197
+ blockExplorerUrls: ["https://sepolia.basescan.org"]
198
+ },
199
+ arbitrum: {
200
+ chainId: "arbitrum",
201
+ eip155ChainId: 42161,
202
+ chainName: "Arbitrum One",
203
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
204
+ rpcUrls: ["https://arb1.arbitrum.io/rpc"],
205
+ blockExplorerUrls: ["https://arbiscan.io"]
206
+ },
207
+ polygon: {
208
+ chainId: "polygon",
209
+ eip155ChainId: 137,
210
+ chainName: "Polygon",
211
+ nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
212
+ rpcUrls: ["https://polygon-rpc.com"],
213
+ blockExplorerUrls: ["https://polygonscan.com"]
214
+ },
215
+ "ethereum-sepolia": {
216
+ chainId: "ethereum-sepolia",
217
+ eip155ChainId: 11155111,
218
+ chainName: "Sepolia",
219
+ nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 },
220
+ rpcUrls: ["https://ethereum-sepolia-rpc.publicnode.com"],
221
+ blockExplorerUrls: ["https://sepolia.etherscan.io"]
222
+ },
223
+ "arbitrum-sepolia": {
224
+ chainId: "arbitrum-sepolia",
225
+ eip155ChainId: 421614,
226
+ chainName: "Arbitrum Sepolia",
227
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
228
+ rpcUrls: ["https://sepolia-rollup.arbitrum.io/rpc"],
229
+ blockExplorerUrls: ["https://sepolia.arbiscan.io"]
230
+ },
231
+ "polygon-amoy": {
232
+ chainId: "polygon-amoy",
233
+ eip155ChainId: 80002,
234
+ chainName: "Polygon Amoy",
235
+ nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
236
+ rpcUrls: ["https://rpc-amoy.polygon.technology"],
237
+ blockExplorerUrls: ["https://amoy.polygonscan.com"]
238
+ }
239
+ };
240
+ function getInjectedEthereumProvider() {
241
+ const maybeGlobal = globalThis;
242
+ return maybeGlobal.ethereum;
243
+ }
244
+ function getInjectedTronProvider() {
245
+ const maybeGlobal = globalThis;
246
+ if (!maybeGlobal.tronWeb) return void 0;
247
+ return { tronLink: maybeGlobal.tronLink, tronWeb: maybeGlobal.tronWeb };
248
+ }
249
+ function getInjectedSolanaProvider() {
250
+ const maybeGlobal = globalThis;
251
+ return maybeGlobal.phantom?.solana ?? maybeGlobal.solana;
252
+ }
253
+ function getInjectedWalletProviders() {
254
+ const providers = {};
255
+ const evmProvider = getInjectedEthereumProvider();
256
+ if (evmProvider) {
257
+ for (const chain of EVM_WALLET_CHAINS) providers[chain] = evmProvider;
258
+ }
259
+ const tronProvider = getInjectedTronProvider();
260
+ if (tronProvider) {
261
+ for (const chain of TRON_WALLET_CHAINS) providers[chain] = tronProvider;
262
+ }
263
+ const solanaProvider = getInjectedSolanaProvider();
264
+ if (solanaProvider) {
265
+ for (const chain of SOLANA_WALLET_CHAINS) providers[chain] = solanaProvider;
266
+ }
267
+ return providers;
268
+ }
269
+ function selectWalletPaymentInstruction(instructions, providers, preferredChains = []) {
270
+ if (instructions.length === 0) {
271
+ throw new StableOpsWalletError("\u8BA2\u5355\u8FD8\u6CA1\u6709\u53EF\u652F\u4ED8\u7684\u94FE\u4E0A\u6536\u6B3E\u6307\u4EE4", "payment_instruction_not_found");
272
+ }
273
+ const preferred = preferredChains.map((chain) => instructions.find((instruction) => instruction.chain === chain)).filter((instruction) => Boolean(instruction));
274
+ const candidates = [...preferred, ...instructions.filter((instruction) => !preferred.includes(instruction))];
275
+ for (const instruction of candidates) {
276
+ const provider = providers[instruction.chain];
277
+ if (provider) return { instruction, provider };
278
+ }
279
+ throw new StableOpsWalletError("\u672A\u627E\u5230\u8BA2\u5355\u5019\u9009\u94FE\u5BF9\u5E94\u7684\u94B1\u5305 provider", "wallet_provider_not_found", {
280
+ chains: instructions.map((instruction) => instruction.chain)
281
+ });
282
+ }
283
+ async function sendOrderWalletPayment(input) {
284
+ const selected = selectWalletPaymentInstruction(
285
+ input.order.paymentInstructions,
286
+ input.providers,
287
+ input.preferredChains
288
+ );
289
+ return sendWalletPayment({
290
+ ...input,
291
+ provider: selected.provider,
292
+ instruction: selected.instruction,
293
+ amount: input.order.amount
294
+ });
295
+ }
296
+ async function sendWalletPayment(input) {
297
+ const instruction = requireInstruction(input.instruction);
298
+ const token = findWalletTokenContract(instruction.chain, instruction.asset);
299
+ if (!token) {
300
+ throw new StableOpsWalletError("\u672A\u627E\u5230\u8BE5\u94FE\u4E0E\u8D44\u4EA7\u7684\u9ED8\u8BA4\u4EE3\u5E01\u5408\u7EA6", "token_contract_not_found", {
301
+ chain: instruction.chain,
302
+ asset: instruction.asset
303
+ });
304
+ }
305
+ if (isEvmWalletChain(instruction.chain)) {
306
+ return sendEvmWalletPayment(input, { ...instruction, chain: instruction.chain }, token);
307
+ }
308
+ if (isTronWalletChain(instruction.chain)) {
309
+ return sendTronWalletPayment(input, instruction, token);
310
+ }
311
+ if (isSolanaWalletChain(instruction.chain)) {
312
+ return sendSolanaWalletPayment(input, instruction, token);
313
+ }
314
+ throw new StableOpsWalletError("\u5F53\u524D\u94B1\u5305 SDK \u4E0D\u652F\u6301\u8BE5\u94FE", "unsupported_chain", { chain: instruction.chain });
315
+ }
316
+ function encodeErc20Transfer(toAddress, amountUnits) {
317
+ const normalizedTo = normalizeEvmAddress(toAddress);
318
+ if (amountUnits < 0n) {
319
+ throw new StableOpsWalletError("\u8F6C\u8D26\u91D1\u989D\u4E0D\u80FD\u4E3A\u8D1F\u6570", "invalid_amount", { amountUnits: amountUnits.toString() });
320
+ }
321
+ return `0x${ERC20_TRANSFER_SELECTOR}${padHex(normalizedTo.slice(2))}${padHex(amountUnits.toString(16))}`;
322
+ }
323
+ function parseTokenAmount(amount, decimals) {
324
+ if (!Number.isInteger(decimals) || decimals < 0) {
325
+ throw new StableOpsWalletError("\u4EE3\u5E01\u7CBE\u5EA6\u914D\u7F6E\u65E0\u6548", "invalid_decimals", { decimals });
326
+ }
327
+ const trimmed = amount.trim();
328
+ const match = /^(\d+)(?:\.(\d+))?$/u.exec(trimmed);
329
+ if (!match) {
330
+ throw new StableOpsWalletError("\u8F6C\u8D26\u91D1\u989D\u683C\u5F0F\u65E0\u6548", "invalid_amount", { amount });
331
+ }
332
+ const whole = match[1];
333
+ const fraction = match[2] ?? "";
334
+ if (fraction.length > decimals) {
335
+ throw new StableOpsWalletError("\u8F6C\u8D26\u91D1\u989D\u5C0F\u6570\u4F4D\u8D85\u8FC7\u4EE3\u5E01\u7CBE\u5EA6", "amount_precision_exceeded", {
336
+ amount,
337
+ decimals
338
+ });
339
+ }
340
+ const units = BigInt(whole) * 10n ** BigInt(decimals) + BigInt(fraction.padEnd(decimals, "0") || "0");
341
+ if (units <= 0n) {
342
+ throw new StableOpsWalletError("\u8F6C\u8D26\u91D1\u989D\u5FC5\u987B\u5927\u4E8E 0", "invalid_amount", { amount });
343
+ }
344
+ return units;
345
+ }
346
+ async function sendEvmWalletPayment(input, instruction, token) {
347
+ const provider = input.provider;
348
+ if (!isEip1193Provider(provider)) {
349
+ throw new StableOpsWalletError("EVM \u652F\u4ED8\u9700\u8981 EIP-1193 \u94B1\u5305 provider", "wallet_provider_mismatch");
350
+ }
351
+ const config = resolveChainConfig(instruction.chain, input.chainConfigs);
352
+ const fromAddress = normalizeEvmAddress(input.fromAddress ?? await requestFirstEvmAccount(provider));
353
+ await ensureEvmChain(provider, config);
354
+ const amountUnits = parseTokenAmount(input.amount, token.decimals);
355
+ const txHash = await provider.request({
356
+ method: "eth_sendTransaction",
357
+ params: [
358
+ {
359
+ from: fromAddress,
360
+ to: token.address,
361
+ value: "0x0",
362
+ data: encodeErc20Transfer(instruction.address, amountUnits)
363
+ }
364
+ ]
365
+ });
366
+ return buildSentPayment(txHash, instruction, token, fromAddress, input.amount, amountUnits);
367
+ }
368
+ async function sendTronWalletPayment(input, instruction, token) {
369
+ const tronWeb = getTronWeb(input.provider);
370
+ const accountRequester = getTronAccountRequester(input.provider);
371
+ if (accountRequester) {
372
+ await accountRequester({ method: "tron_requestAccounts" });
373
+ }
374
+ const fromAddress = normalizeTronAddress(input.fromAddress ?? tronWeb.defaultAddress?.base58);
375
+ const toAddress = normalizeTronAddress(instruction.address);
376
+ const amountUnits = parseTokenAmount(input.amount, token.decimals);
377
+ const built = await tronWeb.transactionBuilder.triggerSmartContract(
378
+ token.address,
379
+ "transfer(address,uint256)",
380
+ { feeLimit: 1e8 },
381
+ [
382
+ { type: "address", value: toAddress },
383
+ { type: "uint256", value: amountUnits.toString() }
384
+ ],
385
+ fromAddress
386
+ );
387
+ if (!built.transaction) {
388
+ throw new StableOpsWalletError("TRON \u94B1\u5305\u672A\u80FD\u521B\u5EFA TRC-20 \u8F6C\u8D26\u4EA4\u6613", "tron_transaction_build_failed", built);
389
+ }
390
+ const signed = await tronWeb.trx.sign(built.transaction);
391
+ const sent = await tronWeb.trx.sendRawTransaction(signed);
392
+ const txHash = sent.txid ?? sent.transaction?.txID ?? getTronSignedTransactionId(signed);
393
+ if (!txHash) {
394
+ throw new StableOpsWalletError("TRON \u94B1\u5305\u672A\u8FD4\u56DE\u4EA4\u6613\u54C8\u5E0C", "wallet_transaction_hash_not_found", sent);
395
+ }
396
+ return buildSentPayment(txHash, instruction, token, fromAddress, input.amount, amountUnits);
397
+ }
398
+ async function sendSolanaWalletPayment(input, instruction, token) {
399
+ const web3 = await loadSolanaWeb3();
400
+ const provider = input.provider;
401
+ const payer = publicKeyFromString(web3, input.fromAddress ?? await requestSolanaPublicKey(provider));
402
+ const recipient = publicKeyFromString(web3, instruction.address);
403
+ const mint = publicKeyFromString(web3, token.address);
404
+ const amountUnits = parseTokenAmount(input.amount, token.decimals);
405
+ const connection = input.solanaConnection ?? new web3.Connection(input.solanaRpcUrl ?? SOLANA_MAINNET_RPC_URL, "confirmed");
406
+ const tokenProgramId = new web3.PublicKey(SOLANA_TOKEN_PROGRAM_ID_BASE58);
407
+ const associatedTokenProgramId = new web3.PublicKey(SOLANA_ASSOCIATED_TOKEN_PROGRAM_ID_BASE58);
408
+ const sourceTokenAccount = findAssociatedTokenAddress(web3, payer, mint, tokenProgramId, associatedTokenProgramId);
409
+ const destinationTokenAccount = findAssociatedTokenAddress(web3, recipient, mint, tokenProgramId, associatedTokenProgramId);
410
+ const latest = await connection.getLatestBlockhash();
411
+ const transaction = new web3.Transaction({
412
+ feePayer: payer,
413
+ recentBlockhash: latest.blockhash
414
+ });
415
+ transaction.add(
416
+ createAssociatedTokenAccountIdempotentInstruction(
417
+ web3,
418
+ payer,
419
+ destinationTokenAccount,
420
+ recipient,
421
+ mint,
422
+ tokenProgramId,
423
+ associatedTokenProgramId
424
+ )
425
+ );
426
+ transaction.add(
427
+ createSplTokenTransferCheckedInstruction(
428
+ web3,
429
+ sourceTokenAccount,
430
+ mint,
431
+ destinationTokenAccount,
432
+ payer,
433
+ amountUnits,
434
+ token.decimals,
435
+ tokenProgramId
436
+ )
437
+ );
438
+ const txHash = await sendSolanaTransaction(provider, connection, transaction);
439
+ return buildSentPayment(txHash, instruction, token, payer.toBase58(), input.amount, amountUnits);
440
+ }
441
+ function buildSentPayment(txHash, instruction, token, fromAddress, amount, amountUnits) {
442
+ return {
443
+ txHash,
444
+ chain: instruction.chain,
445
+ asset: instruction.asset,
446
+ fromAddress,
447
+ toAddress: instruction.address,
448
+ tokenContract: token.address,
449
+ amount,
450
+ amountUnits: amountUnits.toString()
451
+ };
452
+ }
453
+ function isEvmWalletChain(chain) {
454
+ return EVM_WALLET_CHAINS.includes(chain);
455
+ }
456
+ function isTronWalletChain(chain) {
457
+ return TRON_WALLET_CHAINS.includes(chain);
458
+ }
459
+ function isSolanaWalletChain(chain) {
460
+ return SOLANA_WALLET_CHAINS.includes(chain);
461
+ }
462
+ function findWalletTokenContract(chain, asset) {
463
+ return WALLET_TOKEN_CONTRACTS.find((entry) => entry.chain === chain && entry.asset === asset);
464
+ }
465
+ function isEip1193Provider(provider) {
466
+ return typeof provider.request === "function";
467
+ }
468
+ async function requestFirstEvmAccount(provider) {
469
+ const accounts = await provider.request({ method: "eth_requestAccounts" });
470
+ const first = accounts[0];
471
+ if (!first) {
472
+ throw new StableOpsWalletError("\u94B1\u5305\u672A\u8FD4\u56DE\u53EF\u7528\u8D26\u6237", "wallet_account_not_found");
473
+ }
474
+ return first;
475
+ }
476
+ async function ensureEvmChain(provider, config) {
477
+ try {
478
+ await provider.request({
479
+ method: "wallet_switchEthereumChain",
480
+ params: [{ chainId: toHexChainId(config.eip155ChainId) }]
481
+ });
482
+ } catch (err) {
483
+ if (!isUnknownChainError(err)) throw err;
484
+ await provider.request({ method: "wallet_addEthereumChain", params: [toWalletAddChainParams(config)] });
485
+ await provider.request({
486
+ method: "wallet_switchEthereumChain",
487
+ params: [{ chainId: toHexChainId(config.eip155ChainId) }]
488
+ });
489
+ }
490
+ }
491
+ function requireInstruction(instruction) {
492
+ if (!instruction) {
493
+ throw new StableOpsWalletError("\u8BA2\u5355\u8FD8\u6CA1\u6709\u53EF\u652F\u4ED8\u7684\u94FE\u4E0A\u6536\u6B3E\u6307\u4EE4", "payment_instruction_not_found");
494
+ }
495
+ return instruction;
496
+ }
497
+ function resolveChainConfig(chain, overrides) {
498
+ const config = overrides?.[chain] ?? EvmWalletChainConfigs[chain];
499
+ if (!config) {
500
+ throw new StableOpsWalletError("\u672A\u627E\u5230\u94B1\u5305\u5207\u94FE\u914D\u7F6E", "chain_config_not_found", { chain });
501
+ }
502
+ return config;
503
+ }
504
+ function toWalletAddChainParams(config) {
505
+ return {
506
+ chainId: toHexChainId(config.eip155ChainId),
507
+ chainName: config.chainName,
508
+ nativeCurrency: config.nativeCurrency,
509
+ rpcUrls: config.rpcUrls,
510
+ blockExplorerUrls: config.blockExplorerUrls
511
+ };
512
+ }
513
+ function toHexChainId(chainId) {
514
+ return `0x${chainId.toString(16)}`;
515
+ }
516
+ function isUnknownChainError(err) {
517
+ if (typeof err !== "object" || err === null) return false;
518
+ const code = Number(err.code);
519
+ if (code === 4902) return true;
520
+ const data = err.data;
521
+ if (typeof data !== "object" || data === null) return false;
522
+ const originalError = data.originalError;
523
+ if (typeof originalError !== "object" || originalError === null) return false;
524
+ return Number(originalError.code) === 4902;
525
+ }
526
+ function getTronWeb(provider) {
527
+ const tronWeb = provider.tronWeb ?? provider;
528
+ if (!tronWeb || typeof tronWeb.transactionBuilder?.triggerSmartContract !== "function" || typeof tronWeb.trx?.sign !== "function" || typeof tronWeb.trx?.sendRawTransaction !== "function") {
529
+ throw new StableOpsWalletError("TRON \u652F\u4ED8\u9700\u8981 TronLink / TronWeb \u94B1\u5305 provider", "wallet_provider_mismatch");
530
+ }
531
+ return tronWeb;
532
+ }
533
+ function getTronAccountRequester(provider) {
534
+ const wrapper = provider;
535
+ return wrapper.tronLink?.request?.bind(wrapper.tronLink) ?? wrapper.request?.bind(wrapper);
536
+ }
537
+ function getTronSignedTransactionId(signed) {
538
+ if (typeof signed !== "object" || signed === null) return void 0;
539
+ return signed.txID;
540
+ }
541
+ async function requestSolanaPublicKey(provider) {
542
+ const existing = solanaPublicKeyToString(provider.publicKey);
543
+ if (existing) return existing;
544
+ const connected = await provider.connect?.();
545
+ const connectedKey = connected ? solanaPublicKeyToString(connected.publicKey) : void 0;
546
+ const providerKey = solanaPublicKeyToString(provider.publicKey);
547
+ const publicKey = connectedKey ?? providerKey;
548
+ if (!publicKey) {
549
+ throw new StableOpsWalletError("Solana \u94B1\u5305\u672A\u8FD4\u56DE\u53EF\u7528\u8D26\u6237", "wallet_account_not_found");
550
+ }
551
+ return publicKey;
552
+ }
553
+ async function sendSolanaTransaction(provider, connection, transaction) {
554
+ if (typeof provider.signAndSendTransaction === "function") {
555
+ const result = await provider.signAndSendTransaction(transaction);
556
+ const signature = typeof result === "string" ? result : result.signature;
557
+ if (!signature) {
558
+ throw new StableOpsWalletError("Solana \u94B1\u5305\u672A\u8FD4\u56DE\u4EA4\u6613\u7B7E\u540D", "wallet_transaction_hash_not_found", result);
559
+ }
560
+ return signature;
561
+ }
562
+ if (typeof provider.signTransaction !== "function") {
563
+ throw new StableOpsWalletError("Solana \u652F\u4ED8\u9700\u8981\u94B1\u5305\u652F\u6301 signAndSendTransaction \u6216 signTransaction", "wallet_provider_mismatch");
564
+ }
565
+ const signed = await provider.signTransaction(transaction);
566
+ return connection.sendRawTransaction(signed.serialize());
567
+ }
568
+ function solanaPublicKeyToString(publicKey) {
569
+ if (!publicKey) return void 0;
570
+ if (typeof publicKey === "string") return publicKey;
571
+ return publicKey.toBase58();
572
+ }
573
+ function publicKeyFromString(web3, address) {
574
+ try {
575
+ return new web3.PublicKey(address);
576
+ } catch (err) {
577
+ throw new StableOpsWalletError("Solana \u5730\u5740\u683C\u5F0F\u65E0\u6548", "invalid_solana_address", { address, cause: err });
578
+ }
579
+ }
580
+ function findAssociatedTokenAddress(web3, owner, mint, tokenProgramId, associatedTokenProgramId) {
581
+ return web3.PublicKey.findProgramAddressSync(
582
+ [owner.toBuffer(), tokenProgramId.toBuffer(), mint.toBuffer()],
583
+ associatedTokenProgramId
584
+ )[0];
585
+ }
586
+ function createAssociatedTokenAccountIdempotentInstruction(web3, payer, associatedToken, owner, mint, tokenProgramId, associatedTokenProgramId) {
587
+ return new web3.TransactionInstruction({
588
+ programId: associatedTokenProgramId,
589
+ keys: [
590
+ { pubkey: payer, isSigner: true, isWritable: true },
591
+ { pubkey: associatedToken, isSigner: false, isWritable: true },
592
+ { pubkey: owner, isSigner: false, isWritable: false },
593
+ { pubkey: mint, isSigner: false, isWritable: false },
594
+ { pubkey: web3.SystemProgram.programId, isSigner: false, isWritable: false },
595
+ { pubkey: tokenProgramId, isSigner: false, isWritable: false }
596
+ ],
597
+ data: new Uint8Array([SOLANA_CREATE_ASSOCIATED_TOKEN_ACCOUNT_IDEMPOTENT_INSTRUCTION])
598
+ });
599
+ }
600
+ function createSplTokenTransferCheckedInstruction(web3, source, mint, destination, owner, amountUnits, decimals, tokenProgramId) {
601
+ const data = new Uint8Array(10);
602
+ data[0] = SOLANA_TRANSFER_CHECKED_INSTRUCTION;
603
+ writeBigUInt64LE(data, amountUnits, 1);
604
+ data[9] = decimals;
605
+ return new web3.TransactionInstruction({
606
+ programId: tokenProgramId,
607
+ keys: [
608
+ { pubkey: source, isSigner: false, isWritable: true },
609
+ { pubkey: mint, isSigner: false, isWritable: false },
610
+ { pubkey: destination, isSigner: false, isWritable: true },
611
+ { pubkey: owner, isSigner: true, isWritable: false }
612
+ ],
613
+ data
614
+ });
615
+ }
616
+ function writeBigUInt64LE(bytes, value, offset) {
617
+ if (value > 0xffffffffffffffffn) {
618
+ throw new StableOpsWalletError("\u8F6C\u8D26\u91D1\u989D\u8D85\u51FA u64 \u8303\u56F4", "invalid_amount", { amountUnits: value.toString() });
619
+ }
620
+ let remaining = value;
621
+ for (let index = 0; index < 8; index++) {
622
+ bytes[offset + index] = Number(remaining & 0xffn);
623
+ remaining >>= 8n;
624
+ }
625
+ }
626
+ function normalizeEvmAddress(address) {
627
+ if (!/^0x[0-9a-fA-F]{40}$/u.test(address)) {
628
+ throw new StableOpsWalletError("EVM \u5730\u5740\u683C\u5F0F\u65E0\u6548", "invalid_evm_address", { address });
629
+ }
630
+ return address.toLowerCase();
631
+ }
632
+ function normalizeTronAddress(address) {
633
+ if (!address || !/^T[1-9A-HJ-NP-Za-km-z]{33}$/u.test(address)) {
634
+ throw new StableOpsWalletError("TRON \u5730\u5740\u683C\u5F0F\u65E0\u6548", "invalid_tron_address", { address });
635
+ }
636
+ return address;
637
+ }
638
+ function padHex(hex) {
639
+ return hex.padStart(64, "0");
640
+ }
641
+ // Annotate the CommonJS export names for ESM import in node:
642
+ 0 && (module.exports = {
643
+ EvmWalletChainConfigs,
644
+ StableOpsWalletError,
645
+ encodeErc20Transfer,
646
+ getInjectedEthereumProvider,
647
+ getInjectedSolanaProvider,
648
+ getInjectedTronProvider,
649
+ getInjectedWalletProviders,
650
+ parseTokenAmount,
651
+ selectWalletPaymentInstruction,
652
+ sendOrderWalletPayment,
653
+ sendWalletPayment
654
+ });
655
+ //# sourceMappingURL=index.js.map