@sodax/wallet-sdk-core 0.0.1-rc.1
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/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/index.cjs +734 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +291 -0
- package/dist/index.d.ts +291 -0
- package/dist/index.mjs +680 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
2
|
+
import { createWalletClient, http, createPublicClient } from 'viem';
|
|
3
|
+
import { nibiru, polygon, bsc, optimism, base, arbitrum, avalanche, sonic } from 'viem/chains';
|
|
4
|
+
import { NIBIRU_MAINNET_CHAIN_ID, POLYGON_MAINNET_CHAIN_ID, BSC_MAINNET_CHAIN_ID, OPTIMISM_MAINNET_CHAIN_ID, BASE_MAINNET_CHAIN_ID, ARBITRUM_MAINNET_CHAIN_ID, AVALANCHE_MAINNET_CHAIN_ID, SONIC_MAINNET_CHAIN_ID, InjectiveExecuteResponse } from '@sodax/types';
|
|
5
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
6
|
+
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
7
|
+
import { signTransaction } from '@mysten/wallet-standard';
|
|
8
|
+
import * as IconSdkRaw from 'icon-sdk-js';
|
|
9
|
+
import { MsgExecuteContract, createTransaction, MsgExecuteContractCompat } from '@injectivelabs/sdk-ts';
|
|
10
|
+
import { getAssociatedTokenAddress } from '@solana/spl-token';
|
|
11
|
+
import { Keypair, Connection, TransactionMessage, VersionedTransaction, PublicKey, TransactionInstruction } from '@solana/web3.js';
|
|
12
|
+
import { Networks, Keypair as Keypair$1, Horizon, Transaction } from '@stellar/stellar-sdk';
|
|
13
|
+
|
|
14
|
+
// src/wallet-providers/EvmWalletProvider.ts
|
|
15
|
+
function getEvmViemChain(id) {
|
|
16
|
+
switch (id) {
|
|
17
|
+
case SONIC_MAINNET_CHAIN_ID:
|
|
18
|
+
return sonic;
|
|
19
|
+
case AVALANCHE_MAINNET_CHAIN_ID:
|
|
20
|
+
return avalanche;
|
|
21
|
+
case ARBITRUM_MAINNET_CHAIN_ID:
|
|
22
|
+
return arbitrum;
|
|
23
|
+
case BASE_MAINNET_CHAIN_ID:
|
|
24
|
+
return base;
|
|
25
|
+
case OPTIMISM_MAINNET_CHAIN_ID:
|
|
26
|
+
return optimism;
|
|
27
|
+
case BSC_MAINNET_CHAIN_ID:
|
|
28
|
+
return bsc;
|
|
29
|
+
case POLYGON_MAINNET_CHAIN_ID:
|
|
30
|
+
return polygon;
|
|
31
|
+
case NIBIRU_MAINNET_CHAIN_ID:
|
|
32
|
+
return nibiru;
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`Unsupported EVM chain ID: ${id}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
var EvmWalletProvider = class {
|
|
38
|
+
walletClient;
|
|
39
|
+
publicClient;
|
|
40
|
+
constructor(config) {
|
|
41
|
+
if (isPrivateKeyEvmWalletConfig(config)) {
|
|
42
|
+
const chain = getEvmViemChain(config.chainId);
|
|
43
|
+
this.walletClient = createWalletClient({
|
|
44
|
+
chain,
|
|
45
|
+
transport: http(config.rpcUrl ?? chain.rpcUrls.default.http[0]),
|
|
46
|
+
account: privateKeyToAccount(config.privateKey)
|
|
47
|
+
});
|
|
48
|
+
this.publicClient = createPublicClient({
|
|
49
|
+
chain,
|
|
50
|
+
transport: http(config.rpcUrl ?? chain.rpcUrls.default.http[0])
|
|
51
|
+
});
|
|
52
|
+
} else if (isBrowserExtensionEvmWalletConfig(config)) {
|
|
53
|
+
this.walletClient = config.walletClient;
|
|
54
|
+
this.publicClient = config.publicClient;
|
|
55
|
+
} else {
|
|
56
|
+
throw new Error("Invalid EVM wallet config");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async sendTransaction(evmRawTx) {
|
|
60
|
+
return this.walletClient.sendTransaction(evmRawTx);
|
|
61
|
+
}
|
|
62
|
+
async waitForTransactionReceipt(txHash) {
|
|
63
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
64
|
+
return {
|
|
65
|
+
...receipt,
|
|
66
|
+
transactionIndex: receipt.transactionIndex.toString(),
|
|
67
|
+
blockNumber: receipt.blockNumber.toString(),
|
|
68
|
+
cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
|
|
69
|
+
gasUsed: receipt.gasUsed.toString(),
|
|
70
|
+
contractAddress: receipt.contractAddress?.toString() ?? null,
|
|
71
|
+
logs: receipt.logs.map((log) => ({
|
|
72
|
+
...log,
|
|
73
|
+
blockNumber: log.blockNumber.toString(),
|
|
74
|
+
logIndex: log.logIndex.toString(),
|
|
75
|
+
transactionIndex: log.transactionIndex.toString()
|
|
76
|
+
})),
|
|
77
|
+
effectiveGasPrice: receipt.effectiveGasPrice.toString()
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async getWalletAddress() {
|
|
81
|
+
return this.walletClient.account.address;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function isPrivateKeyEvmWalletConfig(config) {
|
|
85
|
+
return "privateKey" in config && config.privateKey.startsWith("0x");
|
|
86
|
+
}
|
|
87
|
+
function isBrowserExtensionEvmWalletConfig(config) {
|
|
88
|
+
return "walletClient" in config && "publicClient" in config;
|
|
89
|
+
}
|
|
90
|
+
function isPrivateKeySuiWalletConfig(walletConfig) {
|
|
91
|
+
return "mnemonics" in walletConfig;
|
|
92
|
+
}
|
|
93
|
+
function isBrowserExtensionSuiWalletConfig(walletConfig) {
|
|
94
|
+
return "wallet" in walletConfig && "account" in walletConfig;
|
|
95
|
+
}
|
|
96
|
+
function isPkSuiWallet(wallet) {
|
|
97
|
+
return "keyPair" in wallet;
|
|
98
|
+
}
|
|
99
|
+
function isBrowserExtensionSuiWallet(wallet) {
|
|
100
|
+
return "wallet" in wallet && "account" in wallet;
|
|
101
|
+
}
|
|
102
|
+
function isSuiWallet(wallet) {
|
|
103
|
+
return isPkSuiWallet(wallet) || isBrowserExtensionSuiWallet(wallet);
|
|
104
|
+
}
|
|
105
|
+
var SuiWalletProvider = class {
|
|
106
|
+
client;
|
|
107
|
+
wallet;
|
|
108
|
+
constructor(walletConfig) {
|
|
109
|
+
if (isPrivateKeySuiWalletConfig(walletConfig)) {
|
|
110
|
+
this.client = new SuiClient({ url: walletConfig.rpcUrl });
|
|
111
|
+
this.wallet = {
|
|
112
|
+
keyPair: Ed25519Keypair.deriveKeypair(walletConfig.mnemonics)
|
|
113
|
+
};
|
|
114
|
+
} else if (isBrowserExtensionSuiWalletConfig(walletConfig)) {
|
|
115
|
+
this.client = walletConfig.client;
|
|
116
|
+
this.wallet = {
|
|
117
|
+
wallet: walletConfig.wallet,
|
|
118
|
+
account: walletConfig.account
|
|
119
|
+
};
|
|
120
|
+
} else {
|
|
121
|
+
throw new Error("Invalid wallet configuration");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async signAndExecuteTxn(txn) {
|
|
125
|
+
if (isPkSuiWallet(this.wallet)) {
|
|
126
|
+
const res = await this.client.signAndExecuteTransaction({
|
|
127
|
+
transaction: txn,
|
|
128
|
+
signer: this.wallet.keyPair
|
|
129
|
+
});
|
|
130
|
+
return res.digest;
|
|
131
|
+
}
|
|
132
|
+
if (isBrowserExtensionSuiWallet(this.wallet)) {
|
|
133
|
+
const browserWallet = this.wallet.wallet;
|
|
134
|
+
const browserAccount = this.wallet.account;
|
|
135
|
+
if (!browserAccount || browserAccount.chains.length === 0) {
|
|
136
|
+
throw new Error("No chains available for wallet account");
|
|
137
|
+
}
|
|
138
|
+
const chain = browserAccount.chains[0];
|
|
139
|
+
if (!chain) {
|
|
140
|
+
throw new Error("No chain available for wallet account");
|
|
141
|
+
}
|
|
142
|
+
const { bytes, signature } = await signTransaction(browserWallet, {
|
|
143
|
+
transaction: txn,
|
|
144
|
+
account: browserAccount,
|
|
145
|
+
chain
|
|
146
|
+
});
|
|
147
|
+
const res = await this.client.executeTransactionBlock({
|
|
148
|
+
transactionBlock: bytes,
|
|
149
|
+
signature,
|
|
150
|
+
options: {
|
|
151
|
+
showRawEffects: true
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
return res.digest;
|
|
155
|
+
}
|
|
156
|
+
throw new Error("Invalid wallet configuration");
|
|
157
|
+
}
|
|
158
|
+
async viewContract(tx, packageId, module, functionName, args, typeArgs = []) {
|
|
159
|
+
tx.moveCall({
|
|
160
|
+
target: `${packageId}::${module}::${functionName}`,
|
|
161
|
+
arguments: args,
|
|
162
|
+
typeArguments: typeArgs
|
|
163
|
+
});
|
|
164
|
+
const sender = this.getSuiAddress();
|
|
165
|
+
const txResults = await this.client.devInspectTransactionBlock({
|
|
166
|
+
transactionBlock: tx,
|
|
167
|
+
sender
|
|
168
|
+
});
|
|
169
|
+
if (txResults.results && txResults.results[0] !== void 0) {
|
|
170
|
+
return txResults.results[0];
|
|
171
|
+
}
|
|
172
|
+
throw Error(`transaction didn't return any values: ${JSON.stringify(txResults, null, 2)}`);
|
|
173
|
+
}
|
|
174
|
+
async getCoins(address, token) {
|
|
175
|
+
return this.client.getCoins({ owner: address, coinType: token, limit: 10 });
|
|
176
|
+
}
|
|
177
|
+
getSuiAddress() {
|
|
178
|
+
if (isPkSuiWallet(this.wallet)) {
|
|
179
|
+
return this.wallet.keyPair.toSuiAddress();
|
|
180
|
+
}
|
|
181
|
+
if (isBrowserExtensionSuiWallet(this.wallet)) {
|
|
182
|
+
return this.wallet.account.address;
|
|
183
|
+
}
|
|
184
|
+
throw new Error("Invalid wallet configuration");
|
|
185
|
+
}
|
|
186
|
+
async getWalletAddress() {
|
|
187
|
+
return this.getSuiAddress();
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
var IconSdk = "default" in IconSdkRaw.default ? IconSdkRaw.default : IconSdkRaw;
|
|
191
|
+
var { Converter, CallTransactionBuilder, Wallet } = IconSdk;
|
|
192
|
+
var IconWalletProvider = class {
|
|
193
|
+
wallet;
|
|
194
|
+
iconService;
|
|
195
|
+
constructor(wallet) {
|
|
196
|
+
if (isPrivateKeyIconWalletConfig(wallet)) {
|
|
197
|
+
this.wallet = {
|
|
198
|
+
type: "PRIVATE_KEY",
|
|
199
|
+
wallet: Wallet.loadPrivateKey(wallet.privateKey.slice(2))
|
|
200
|
+
};
|
|
201
|
+
this.iconService = new IconSdk.IconService(new IconSdk.IconService.HttpProvider(wallet.rpcUrl));
|
|
202
|
+
} else if (isBrowserExtensionIconWalletConfig(wallet)) {
|
|
203
|
+
this.wallet = {
|
|
204
|
+
type: "BROWSER_EXTENSION",
|
|
205
|
+
wallet: wallet.walletAddress
|
|
206
|
+
};
|
|
207
|
+
this.iconService = new IconSdk.IconService(new IconSdk.IconService.HttpProvider(wallet.rpcUrl));
|
|
208
|
+
} else {
|
|
209
|
+
throw new Error("Invalid Icon wallet config");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async sendTransaction(tx) {
|
|
213
|
+
const builtTx = new CallTransactionBuilder().from(tx.from).to(tx.to).stepLimit(Converter.toHex(2e6)).nid(tx.nid).version(tx.version ?? "0x3").timestamp(Converter.toHex(tx.timestamp ?? (/* @__PURE__ */ new Date()).getTime() * 1e3)).value(tx.value).method(tx.method).params(tx.params).build();
|
|
214
|
+
if (!isIconPkWallet(this.wallet)) {
|
|
215
|
+
const result2 = await requestJsonRpc(builtTx);
|
|
216
|
+
return result2.result;
|
|
217
|
+
}
|
|
218
|
+
const signedTx = new IconSdk.IconService.SignedTransaction(builtTx, this.wallet.wallet);
|
|
219
|
+
const result = await this.iconService.sendTransaction(signedTx).execute();
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
async waitForTransactionReceipt(txHash) {
|
|
223
|
+
const result = await this.iconService.waitTransactionResult(txHash).execute();
|
|
224
|
+
return {
|
|
225
|
+
...result,
|
|
226
|
+
status: +result.status,
|
|
227
|
+
cumulativeStepUsed: BigNumberToBigInt(result.cumulativeStepUsed),
|
|
228
|
+
stepUsed: BigNumberToBigInt(result.stepUsed),
|
|
229
|
+
stepPrice: BigNumberToBigInt(result.stepPrice)
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
async getWalletAddress() {
|
|
233
|
+
if (!this.wallet.wallet) {
|
|
234
|
+
throw new Error("Wallet not initialized");
|
|
235
|
+
}
|
|
236
|
+
return isIconPkWallet(this.wallet) ? this.wallet.wallet.getAddress() : this.wallet.wallet;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
function isIconPkWallet(wallet) {
|
|
240
|
+
return wallet.type === "PRIVATE_KEY";
|
|
241
|
+
}
|
|
242
|
+
function isIconBrowserExtensionWallet(wallet) {
|
|
243
|
+
return wallet.type === "BROWSER_EXTENSION";
|
|
244
|
+
}
|
|
245
|
+
function isPrivateKeyIconWalletConfig(config) {
|
|
246
|
+
return "privateKey" in config && config.privateKey.startsWith("0x");
|
|
247
|
+
}
|
|
248
|
+
function isBrowserExtensionIconWalletConfig(config) {
|
|
249
|
+
return "walletAddress" in config && (isIconEoaAddress(config.walletAddress) || !config.walletAddress);
|
|
250
|
+
}
|
|
251
|
+
function isIconAddress(value) {
|
|
252
|
+
return typeof value === "string" && /^hx[a-f0-9]{40}$|^cx[a-f0-9]{40}$/.test(value);
|
|
253
|
+
}
|
|
254
|
+
function isIconEoaAddress(value) {
|
|
255
|
+
return typeof value === "string" && /^hx[a-f0-9]{40}$/.test(value);
|
|
256
|
+
}
|
|
257
|
+
function isResponseAddressType(value) {
|
|
258
|
+
return typeof value === "object" && value !== null && "type" in value && "payload" in value && value.type === "RESPONSE_ADDRESS" && isIconAddress(value.payload);
|
|
259
|
+
}
|
|
260
|
+
function isResponseSigningType(value) {
|
|
261
|
+
return typeof value === "object" && value !== null && "type" in value && "payload" in value && value.type === "RESPONSE_SIGNING" && typeof value.payload === "string";
|
|
262
|
+
}
|
|
263
|
+
function isJsonRpcPayloadResponse(value) {
|
|
264
|
+
return typeof value === "object" && value !== null && "id" in value && "result" in value && typeof value.result === "string";
|
|
265
|
+
}
|
|
266
|
+
function requestAddress() {
|
|
267
|
+
return new Promise((resolve) => {
|
|
268
|
+
const eventHandler = (event) => {
|
|
269
|
+
const customEvent = event;
|
|
270
|
+
const response = customEvent.detail;
|
|
271
|
+
if (isResponseAddressType(response)) {
|
|
272
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
273
|
+
resolve(response.payload);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
277
|
+
window.addEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
278
|
+
window.dispatchEvent(
|
|
279
|
+
new CustomEvent("ICONEX_RELAY_REQUEST", {
|
|
280
|
+
detail: {
|
|
281
|
+
type: "REQUEST_ADDRESS"
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
function requestSigning(from, hash) {
|
|
288
|
+
return new Promise((resolve, reject) => {
|
|
289
|
+
const signRequest = new CustomEvent("ICONEX_RELAY_REQUEST", {
|
|
290
|
+
detail: {
|
|
291
|
+
type: "REQUEST_SIGNING",
|
|
292
|
+
payload: {
|
|
293
|
+
from,
|
|
294
|
+
hash
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
const eventHandler = (event) => {
|
|
299
|
+
const customEvent = event;
|
|
300
|
+
const response = customEvent.detail;
|
|
301
|
+
if (isResponseSigningType(response)) {
|
|
302
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
303
|
+
resolve(response.payload);
|
|
304
|
+
} else if (response.type === "CANCEL_SIGNING") {
|
|
305
|
+
reject(new Error("CANCEL_SIGNING"));
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
309
|
+
window.addEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
310
|
+
window.dispatchEvent(signRequest);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function requestJsonRpc(rawTransaction, id = 99999) {
|
|
314
|
+
return new Promise((resolve, reject) => {
|
|
315
|
+
const eventHandler = (event) => {
|
|
316
|
+
const customEvent = event;
|
|
317
|
+
const { type, payload } = customEvent.detail;
|
|
318
|
+
if (type === "RESPONSE_JSON-RPC") {
|
|
319
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
320
|
+
if (isJsonRpcPayloadResponse(payload)) {
|
|
321
|
+
resolve(payload);
|
|
322
|
+
} else {
|
|
323
|
+
reject(new Error("Invalid payload response type (expected JsonRpcPayloadResponse)"));
|
|
324
|
+
}
|
|
325
|
+
} else if (type === "CANCEL_JSON-RPC") {
|
|
326
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
327
|
+
reject(new Error("CANCEL_JSON-RPC"));
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
window.removeEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
331
|
+
window.addEventListener("ICONEX_RELAY_RESPONSE", eventHandler, false);
|
|
332
|
+
window.dispatchEvent(
|
|
333
|
+
new CustomEvent("ICONEX_RELAY_REQUEST", {
|
|
334
|
+
detail: {
|
|
335
|
+
type: "REQUEST_JSON-RPC",
|
|
336
|
+
payload: {
|
|
337
|
+
jsonrpc: "2.0",
|
|
338
|
+
method: "icx_sendTransaction",
|
|
339
|
+
params: rawTransaction,
|
|
340
|
+
id
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
})
|
|
344
|
+
);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
function BigNumberToBigInt(bigNumber) {
|
|
348
|
+
if (!bigNumber.isInteger()) {
|
|
349
|
+
throw new Error("Cannot convert decimal number to BigInt");
|
|
350
|
+
}
|
|
351
|
+
return BigInt(bigNumber.toFixed(0));
|
|
352
|
+
}
|
|
353
|
+
function isBrowserExtensionInjectiveWalletConfig(config) {
|
|
354
|
+
return "msgBroadcaster" in config && "walletAddress" in config;
|
|
355
|
+
}
|
|
356
|
+
var InjectiveWalletProvider = class {
|
|
357
|
+
msgBroadcaster;
|
|
358
|
+
walletAddress;
|
|
359
|
+
constructor(config) {
|
|
360
|
+
if (isBrowserExtensionInjectiveWalletConfig(config)) {
|
|
361
|
+
this.msgBroadcaster = config.msgBroadcaster;
|
|
362
|
+
this.walletAddress = config.walletAddress;
|
|
363
|
+
} else {
|
|
364
|
+
throw new Error("Invalid Injective wallet config");
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
getRawTransaction(chainId, _, senderAddress, contractAddress, msg, memo) {
|
|
368
|
+
if (!this.walletAddress) {
|
|
369
|
+
throw new Error("Wallet address not found");
|
|
370
|
+
}
|
|
371
|
+
const msgExec = MsgExecuteContract.fromJSON({
|
|
372
|
+
contractAddress,
|
|
373
|
+
sender: senderAddress,
|
|
374
|
+
msg,
|
|
375
|
+
funds: []
|
|
376
|
+
});
|
|
377
|
+
const { txRaw } = createTransaction({
|
|
378
|
+
message: msgExec,
|
|
379
|
+
memo: "",
|
|
380
|
+
pubKey: Buffer.from(this.walletAddress).toString(),
|
|
381
|
+
sequence: 0,
|
|
382
|
+
accountNumber: 0,
|
|
383
|
+
chainId
|
|
384
|
+
});
|
|
385
|
+
const rawTx = {
|
|
386
|
+
from: senderAddress,
|
|
387
|
+
to: contractAddress,
|
|
388
|
+
signedDoc: {
|
|
389
|
+
bodyBytes: txRaw.bodyBytes,
|
|
390
|
+
chainId,
|
|
391
|
+
accountNumber: BigInt(0),
|
|
392
|
+
authInfoBytes: txRaw.authInfoBytes
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
return Promise.resolve(rawTx);
|
|
396
|
+
}
|
|
397
|
+
async getWalletAddress() {
|
|
398
|
+
if (!this.walletAddress) {
|
|
399
|
+
throw new Error("Wallet address not found");
|
|
400
|
+
}
|
|
401
|
+
return Promise.resolve(this.walletAddress);
|
|
402
|
+
}
|
|
403
|
+
async execute(senderAddress, contractAddress, msg, funds) {
|
|
404
|
+
if (!this.walletAddress) {
|
|
405
|
+
throw new Error("Wallet address not found");
|
|
406
|
+
}
|
|
407
|
+
const msgExec = MsgExecuteContractCompat.fromJSON({
|
|
408
|
+
contractAddress,
|
|
409
|
+
sender: senderAddress,
|
|
410
|
+
msg,
|
|
411
|
+
funds: funds || []
|
|
412
|
+
});
|
|
413
|
+
const txResult = await this.msgBroadcaster.broadcastWithFeeDelegation({
|
|
414
|
+
msgs: msgExec,
|
|
415
|
+
injectiveAddress: this.walletAddress
|
|
416
|
+
});
|
|
417
|
+
return InjectiveExecuteResponse.fromTxResponse(txResult);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
function isPrivateKeySolanaWalletConfig(walletConfig) {
|
|
421
|
+
return "privateKey" in walletConfig;
|
|
422
|
+
}
|
|
423
|
+
function isBrowserExtensionSolanaWalletConfig(walletConfig) {
|
|
424
|
+
return "wallet" in walletConfig && !(walletConfig.wallet instanceof Keypair);
|
|
425
|
+
}
|
|
426
|
+
var SolanaWalletProvider = class {
|
|
427
|
+
wallet;
|
|
428
|
+
connection;
|
|
429
|
+
isAdapterMode;
|
|
430
|
+
constructor(walletConfig) {
|
|
431
|
+
if (isPrivateKeySolanaWalletConfig(walletConfig)) {
|
|
432
|
+
this.wallet = Keypair.fromSecretKey(walletConfig.privateKey);
|
|
433
|
+
this.connection = new Connection(walletConfig.endpoint, "confirmed");
|
|
434
|
+
this.isAdapterMode = false;
|
|
435
|
+
} else if (isBrowserExtensionSolanaWalletConfig(walletConfig)) {
|
|
436
|
+
this.wallet = walletConfig.wallet;
|
|
437
|
+
this.connection = walletConfig.connection;
|
|
438
|
+
this.isAdapterMode = true;
|
|
439
|
+
} else {
|
|
440
|
+
throw new Error("Invalid wallet configuration");
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async waitForConfirmation(signature, commitment = "finalized") {
|
|
444
|
+
const latestBlockhash = await this.connection.getLatestBlockhash();
|
|
445
|
+
const response = await this.connection.confirmTransaction(
|
|
446
|
+
{
|
|
447
|
+
signature,
|
|
448
|
+
blockhash: latestBlockhash.blockhash,
|
|
449
|
+
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
|
|
450
|
+
},
|
|
451
|
+
commitment
|
|
452
|
+
);
|
|
453
|
+
return response;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Send a raw transaction to the Solana network.
|
|
457
|
+
* @param rawTransaction - The raw transaction to send.
|
|
458
|
+
* @returns The transaction signature.
|
|
459
|
+
*/
|
|
460
|
+
async sendTransaction(rawTransaction) {
|
|
461
|
+
return this.connection.sendRawTransaction(rawTransaction);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Send a raw transaction to the Solana network and wait for confirmation.
|
|
465
|
+
* @param rawTransaction - The raw transaction to send.
|
|
466
|
+
* @param commitment - The commitment level to use. Defaults to 'finalized'.
|
|
467
|
+
* @returns The transaction signature.
|
|
468
|
+
*/
|
|
469
|
+
async sendTransactionWithConfirmation(rawTransaction, commitment = "finalized") {
|
|
470
|
+
const txHash = await this.connection.sendRawTransaction(rawTransaction);
|
|
471
|
+
await this.waitForConfirmation(txHash, commitment);
|
|
472
|
+
return txHash;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Build a v0 versioned transaction.
|
|
476
|
+
* @param instructions - The instructions to include in the transaction.
|
|
477
|
+
* @returns The v0 transaction.
|
|
478
|
+
*/
|
|
479
|
+
async buildV0Txn(rawInstructions) {
|
|
480
|
+
if (this.isAdapterMode) {
|
|
481
|
+
return this.buildV0TxnWithAdapter(rawInstructions);
|
|
482
|
+
}
|
|
483
|
+
return this.buildV0TxnWithKeypair(rawInstructions);
|
|
484
|
+
}
|
|
485
|
+
async buildV0TxnWithAdapter(rawInstructions) {
|
|
486
|
+
const adapterWallet = this.wallet;
|
|
487
|
+
if (!adapterWallet.publicKey) {
|
|
488
|
+
throw new Error("Wallet public key is not initialized");
|
|
489
|
+
}
|
|
490
|
+
if (!adapterWallet.signTransaction) {
|
|
491
|
+
throw new Error("Wallet signTransaction is not initialized");
|
|
492
|
+
}
|
|
493
|
+
const instructions = this.buildTransactionInstruction(rawInstructions);
|
|
494
|
+
const latestBlockhash = await this.connection.getLatestBlockhash();
|
|
495
|
+
const messageV0 = new TransactionMessage({
|
|
496
|
+
payerKey: adapterWallet.publicKey,
|
|
497
|
+
recentBlockhash: latestBlockhash.blockhash,
|
|
498
|
+
instructions
|
|
499
|
+
}).compileToV0Message();
|
|
500
|
+
const tx = await adapterWallet.signTransaction(new VersionedTransaction(messageV0));
|
|
501
|
+
return tx.serialize();
|
|
502
|
+
}
|
|
503
|
+
async buildV0TxnWithKeypair(rawInstructions) {
|
|
504
|
+
const keypairWallet = this.wallet;
|
|
505
|
+
const instructions = this.buildTransactionInstruction(rawInstructions);
|
|
506
|
+
const messageV0 = new TransactionMessage({
|
|
507
|
+
payerKey: keypairWallet.publicKey,
|
|
508
|
+
recentBlockhash: (await this.connection.getLatestBlockhash()).blockhash,
|
|
509
|
+
instructions
|
|
510
|
+
}).compileToV0Message();
|
|
511
|
+
const tx = new VersionedTransaction(messageV0);
|
|
512
|
+
tx.sign([keypairWallet]);
|
|
513
|
+
return tx.serialize();
|
|
514
|
+
}
|
|
515
|
+
getWalletBase58PublicKey() {
|
|
516
|
+
if (!this.wallet.publicKey) {
|
|
517
|
+
throw new Error("Wallet public key is not initialized");
|
|
518
|
+
}
|
|
519
|
+
return this.wallet.publicKey.toBase58();
|
|
520
|
+
}
|
|
521
|
+
async getWalletAddress() {
|
|
522
|
+
return this.getWalletBase58PublicKey();
|
|
523
|
+
}
|
|
524
|
+
async getAssociatedTokenAddress(mint) {
|
|
525
|
+
if (!this.wallet.publicKey) {
|
|
526
|
+
throw new Error("Wallet public key is not initialized");
|
|
527
|
+
}
|
|
528
|
+
return (await getAssociatedTokenAddress(new PublicKey(mint), this.wallet.publicKey, true)).toBase58();
|
|
529
|
+
}
|
|
530
|
+
async getBalance(publicKey) {
|
|
531
|
+
return await this.connection.getBalance(new PublicKey(publicKey));
|
|
532
|
+
}
|
|
533
|
+
async getTokenAccountBalance(publicKey) {
|
|
534
|
+
return this.connection.getTokenAccountBalance(new PublicKey(publicKey));
|
|
535
|
+
}
|
|
536
|
+
buildTransactionInstruction(rawInstructions) {
|
|
537
|
+
return rawInstructions.map(
|
|
538
|
+
(rawInstruction) => new TransactionInstruction({
|
|
539
|
+
keys: rawInstruction.keys.map((key) => ({
|
|
540
|
+
pubkey: new PublicKey(key.pubkey),
|
|
541
|
+
isSigner: key.isSigner,
|
|
542
|
+
isWritable: key.isWritable
|
|
543
|
+
})),
|
|
544
|
+
programId: new PublicKey(rawInstruction.programId),
|
|
545
|
+
data: Buffer.from(rawInstruction.data)
|
|
546
|
+
})
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
var STELLAR_HORIZON_URLS = {
|
|
551
|
+
TESTNET: "https://horizon-testnet.stellar.org",
|
|
552
|
+
PUBLIC: "https://horizon.stellar.org"
|
|
553
|
+
};
|
|
554
|
+
var STELLAR_NETWORK_PASSPHRASES = {
|
|
555
|
+
TESTNET: Networks.TESTNET,
|
|
556
|
+
PUBLIC: Networks.PUBLIC
|
|
557
|
+
};
|
|
558
|
+
var TX_POLL_INTERVAL = 2e3;
|
|
559
|
+
var TX_POLL_TIMEOUT = 6e4;
|
|
560
|
+
var StellarWalletError = class extends Error {
|
|
561
|
+
constructor(message, code) {
|
|
562
|
+
super(message);
|
|
563
|
+
this.code = code;
|
|
564
|
+
this.name = "StellarWalletError";
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
function isPrivateKeyStellarWalletConfig(config) {
|
|
568
|
+
return config.type === "PRIVATE_KEY";
|
|
569
|
+
}
|
|
570
|
+
function isBrowserExtensionStellarWalletConfig(config) {
|
|
571
|
+
return config.type === "BROWSER_EXTENSION";
|
|
572
|
+
}
|
|
573
|
+
function isStellarPkWallet(wallet) {
|
|
574
|
+
return wallet.type === "PRIVATE_KEY";
|
|
575
|
+
}
|
|
576
|
+
function isStellarBrowserExtensionWallet(wallet) {
|
|
577
|
+
return wallet.type === "BROWSER_EXTENSION";
|
|
578
|
+
}
|
|
579
|
+
function isValidStellarNetwork(network) {
|
|
580
|
+
return ["TESTNET", "PUBLIC"].includes(network);
|
|
581
|
+
}
|
|
582
|
+
function isValidStellarPrivateKey(privateKey) {
|
|
583
|
+
try {
|
|
584
|
+
const key = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
|
|
585
|
+
Keypair$1.fromSecret(key);
|
|
586
|
+
return true;
|
|
587
|
+
} catch {
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
var StellarWalletProvider = class {
|
|
592
|
+
wallet;
|
|
593
|
+
server;
|
|
594
|
+
networkPassphrase;
|
|
595
|
+
constructor(config) {
|
|
596
|
+
if (!isValidStellarNetwork(config.network)) {
|
|
597
|
+
throw new StellarWalletError(`Invalid network: ${config.network}`, "INVALID_NETWORK");
|
|
598
|
+
}
|
|
599
|
+
if (isPrivateKeyStellarWalletConfig(config)) {
|
|
600
|
+
if (!isValidStellarPrivateKey(config.privateKey)) {
|
|
601
|
+
throw new StellarWalletError("Invalid private key format", "INVALID_PRIVATE_KEY");
|
|
602
|
+
}
|
|
603
|
+
const privateKey = config.privateKey.startsWith("0x") ? config.privateKey.slice(2) : config.privateKey;
|
|
604
|
+
this.wallet = {
|
|
605
|
+
type: "PRIVATE_KEY",
|
|
606
|
+
keypair: Keypair$1.fromSecret(privateKey)
|
|
607
|
+
};
|
|
608
|
+
this.server = new Horizon.Server(config.rpcUrl ?? STELLAR_HORIZON_URLS[config.network]);
|
|
609
|
+
this.networkPassphrase = STELLAR_NETWORK_PASSPHRASES[config.network];
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
if (isBrowserExtensionStellarWalletConfig(config)) {
|
|
613
|
+
this.wallet = {
|
|
614
|
+
type: "BROWSER_EXTENSION",
|
|
615
|
+
walletsKit: config.walletsKit
|
|
616
|
+
};
|
|
617
|
+
this.server = new Horizon.Server(config.rpcUrl ?? STELLAR_HORIZON_URLS[config.network]);
|
|
618
|
+
this.networkPassphrase = STELLAR_NETWORK_PASSPHRASES[config.network];
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
throw new StellarWalletError("Invalid wallet configuration", "INVALID_CONFIG");
|
|
622
|
+
}
|
|
623
|
+
async getWalletAddress() {
|
|
624
|
+
try {
|
|
625
|
+
if (isStellarPkWallet(this.wallet)) {
|
|
626
|
+
return this.wallet.keypair.publicKey();
|
|
627
|
+
}
|
|
628
|
+
const { address } = await this.wallet.walletsKit.getAddress();
|
|
629
|
+
return address;
|
|
630
|
+
} catch (error) {
|
|
631
|
+
throw new StellarWalletError(
|
|
632
|
+
error instanceof Error ? error.message : "Failed to get wallet address",
|
|
633
|
+
"INVALID_CONFIG"
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
async signTransaction(tx) {
|
|
638
|
+
try {
|
|
639
|
+
if (isStellarPkWallet(this.wallet)) {
|
|
640
|
+
const transaction = new Transaction(tx, this.networkPassphrase);
|
|
641
|
+
transaction.sign(this.wallet.keypair);
|
|
642
|
+
return transaction.toXDR();
|
|
643
|
+
}
|
|
644
|
+
const { signedTxXdr } = await this.wallet.walletsKit.signTransaction(tx, {
|
|
645
|
+
networkPassphrase: this.networkPassphrase
|
|
646
|
+
});
|
|
647
|
+
return signedTxXdr;
|
|
648
|
+
} catch (error) {
|
|
649
|
+
throw new StellarWalletError(
|
|
650
|
+
error instanceof Error ? error.message : "Failed to sign transaction",
|
|
651
|
+
"SIGN_TX_ERROR"
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
async waitForTransactionReceipt(txHash) {
|
|
656
|
+
const startTime = Date.now();
|
|
657
|
+
while (Date.now() - startTime < TX_POLL_TIMEOUT) {
|
|
658
|
+
try {
|
|
659
|
+
const tx = await this.server.transactions().transaction(txHash).call();
|
|
660
|
+
return {
|
|
661
|
+
...tx,
|
|
662
|
+
_links: {
|
|
663
|
+
...tx._links,
|
|
664
|
+
transaction: tx._links.self
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
} catch (error) {
|
|
668
|
+
await new Promise((resolve) => setTimeout(resolve, TX_POLL_INTERVAL));
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
throw new StellarWalletError(
|
|
672
|
+
`Transaction receipt not found for hash ${txHash} after ${TX_POLL_TIMEOUT / 1e3} seconds.`,
|
|
673
|
+
"TX_RECEIPT_TIMEOUT"
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
export { BigNumberToBigInt, EvmWalletProvider, IconWalletProvider, InjectiveWalletProvider, SolanaWalletProvider, StellarWalletError, StellarWalletProvider, SuiWalletProvider, getEvmViemChain, isBrowserExtensionEvmWalletConfig, isBrowserExtensionIconWalletConfig, isBrowserExtensionInjectiveWalletConfig, isBrowserExtensionStellarWalletConfig, isBrowserExtensionSuiWallet, isIconAddress, isIconBrowserExtensionWallet, isIconEoaAddress, isIconPkWallet, isJsonRpcPayloadResponse, isPkSuiWallet, isPrivateKeyEvmWalletConfig, isPrivateKeyIconWalletConfig, isPrivateKeyStellarWalletConfig, isResponseAddressType, isResponseSigningType, isStellarBrowserExtensionWallet, isStellarPkWallet, isSuiWallet, isValidStellarNetwork, isValidStellarPrivateKey, requestAddress, requestJsonRpc, requestSigning };
|
|
679
|
+
//# sourceMappingURL=index.mjs.map
|
|
680
|
+
//# sourceMappingURL=index.mjs.map
|