@movebridge/core 0.0.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 +0 -0
- package/dist/index.d.mts +602 -0
- package/dist/index.d.ts +602 -0
- package/dist/index.js +1025 -0
- package/dist/index.mjs +973 -0
- package/package.json +55 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1025 @@
|
|
|
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
|
+
ContractInterface: () => ContractInterface,
|
|
34
|
+
DEFAULT_COIN_TYPE: () => DEFAULT_COIN_TYPE,
|
|
35
|
+
Errors: () => Errors,
|
|
36
|
+
EventListener: () => EventListener,
|
|
37
|
+
Movement: () => Movement,
|
|
38
|
+
MovementError: () => MovementError,
|
|
39
|
+
NETWORK_CONFIG: () => NETWORK_CONFIG,
|
|
40
|
+
TransactionBuilder: () => TransactionBuilder,
|
|
41
|
+
WalletManager: () => WalletManager,
|
|
42
|
+
getExplorerAccountUrl: () => getExplorerAccountUrl,
|
|
43
|
+
getExplorerTxUrl: () => getExplorerTxUrl,
|
|
44
|
+
isMovementError: () => isMovementError,
|
|
45
|
+
isValidAddress: () => isValidAddress,
|
|
46
|
+
isValidEventHandle: () => isValidEventHandle,
|
|
47
|
+
resolveConfig: () => resolveConfig,
|
|
48
|
+
wrapError: () => wrapError
|
|
49
|
+
});
|
|
50
|
+
module.exports = __toCommonJS(index_exports);
|
|
51
|
+
|
|
52
|
+
// src/client.ts
|
|
53
|
+
var import_ts_sdk = require("@aptos-labs/ts-sdk");
|
|
54
|
+
|
|
55
|
+
// src/config.ts
|
|
56
|
+
var NETWORK_CONFIG = {
|
|
57
|
+
mainnet: {
|
|
58
|
+
chainId: 126,
|
|
59
|
+
rpcUrl: "https://full.mainnet.movementinfra.xyz/v1",
|
|
60
|
+
indexerUrl: "https://indexer.mainnet.movementnetwork.xyz/v1/graphql",
|
|
61
|
+
explorerUrl: "https://explorer.movementnetwork.xyz/?network=mainnet"
|
|
62
|
+
},
|
|
63
|
+
testnet: {
|
|
64
|
+
chainId: 250,
|
|
65
|
+
rpcUrl: "https://testnet.movementnetwork.xyz/v1",
|
|
66
|
+
indexerUrl: null,
|
|
67
|
+
explorerUrl: "https://explorer.movementnetwork.xyz/?network=bardock+testnet",
|
|
68
|
+
faucetUrl: "https://faucet.testnet.movementnetwork.xyz/"
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var DEFAULT_COIN_TYPE = "0x1::aptos_coin::AptosCoin";
|
|
72
|
+
function resolveConfig(config) {
|
|
73
|
+
const networkConfig = NETWORK_CONFIG[config.network];
|
|
74
|
+
return {
|
|
75
|
+
network: config.network,
|
|
76
|
+
chainId: networkConfig.chainId,
|
|
77
|
+
rpcUrl: config.rpcUrl ?? networkConfig.rpcUrl,
|
|
78
|
+
indexerUrl: config.indexerUrl ?? networkConfig.indexerUrl,
|
|
79
|
+
explorerUrl: networkConfig.explorerUrl,
|
|
80
|
+
autoConnect: config.autoConnect ?? false
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function isValidAddress(address) {
|
|
84
|
+
const addressRegex = /^0x[a-fA-F0-9]{1,64}$/;
|
|
85
|
+
return addressRegex.test(address);
|
|
86
|
+
}
|
|
87
|
+
function isValidEventHandle(eventHandle) {
|
|
88
|
+
const eventHandleRegex = /^0x[a-fA-F0-9]{1,64}::[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
89
|
+
return eventHandleRegex.test(eventHandle);
|
|
90
|
+
}
|
|
91
|
+
function getExplorerTxUrl(network, txHash) {
|
|
92
|
+
const config = NETWORK_CONFIG[network];
|
|
93
|
+
return `${config.explorerUrl}&txn=${txHash}`;
|
|
94
|
+
}
|
|
95
|
+
function getExplorerAccountUrl(network, address) {
|
|
96
|
+
const config = NETWORK_CONFIG[network];
|
|
97
|
+
return `${config.explorerUrl}&account=${address}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/errors.ts
|
|
101
|
+
var MovementError = class _MovementError extends Error {
|
|
102
|
+
constructor(message, code, details) {
|
|
103
|
+
super(message);
|
|
104
|
+
this.code = code;
|
|
105
|
+
this.details = details;
|
|
106
|
+
if (Error.captureStackTrace) {
|
|
107
|
+
Error.captureStackTrace(this, _MovementError);
|
|
108
|
+
}
|
|
109
|
+
Object.setPrototypeOf(this, _MovementError.prototype);
|
|
110
|
+
}
|
|
111
|
+
name = "MovementError";
|
|
112
|
+
/**
|
|
113
|
+
* Serializes the error to a JSON-compatible object
|
|
114
|
+
*/
|
|
115
|
+
toJSON() {
|
|
116
|
+
return {
|
|
117
|
+
name: this.name,
|
|
118
|
+
message: this.message,
|
|
119
|
+
code: this.code,
|
|
120
|
+
details: this.details
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Creates a string representation of the error
|
|
125
|
+
*/
|
|
126
|
+
toString() {
|
|
127
|
+
return `${this.name} [${this.code}]: ${this.message}`;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var Errors = {
|
|
131
|
+
/**
|
|
132
|
+
* Creates an invalid address error
|
|
133
|
+
*/
|
|
134
|
+
invalidAddress(address, reason) {
|
|
135
|
+
return new MovementError(
|
|
136
|
+
`Invalid address: ${address}${reason ? ` - ${reason}` : ""}`,
|
|
137
|
+
"INVALID_ADDRESS",
|
|
138
|
+
{ address, reason }
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
/**
|
|
142
|
+
* Creates a wallet not found error
|
|
143
|
+
*/
|
|
144
|
+
walletNotFound(wallet, available) {
|
|
145
|
+
return new MovementError(
|
|
146
|
+
`Wallet "${wallet}" not found. Available wallets: ${available.join(", ") || "none"}`,
|
|
147
|
+
"WALLET_NOT_FOUND",
|
|
148
|
+
{ wallet, available }
|
|
149
|
+
);
|
|
150
|
+
},
|
|
151
|
+
/**
|
|
152
|
+
* Creates a wallet connection failed error
|
|
153
|
+
*/
|
|
154
|
+
walletConnectionFailed(wallet, originalError) {
|
|
155
|
+
const errorMessage = originalError instanceof Error ? originalError.message : String(originalError);
|
|
156
|
+
return new MovementError(
|
|
157
|
+
`Failed to connect to wallet "${wallet}": ${errorMessage}`,
|
|
158
|
+
"WALLET_CONNECTION_FAILED",
|
|
159
|
+
{ wallet, originalError }
|
|
160
|
+
);
|
|
161
|
+
},
|
|
162
|
+
/**
|
|
163
|
+
* Creates a wallet not connected error
|
|
164
|
+
*/
|
|
165
|
+
walletNotConnected() {
|
|
166
|
+
return new MovementError(
|
|
167
|
+
"No wallet connected. Please connect a wallet first.",
|
|
168
|
+
"WALLET_NOT_CONNECTED"
|
|
169
|
+
);
|
|
170
|
+
},
|
|
171
|
+
/**
|
|
172
|
+
* Creates a transaction failed error
|
|
173
|
+
*/
|
|
174
|
+
transactionFailed(hash, vmStatus, gasUsed) {
|
|
175
|
+
return new MovementError(
|
|
176
|
+
`Transaction ${hash} failed with status: ${vmStatus}`,
|
|
177
|
+
"TRANSACTION_FAILED",
|
|
178
|
+
{ hash, vmStatus, gasUsed }
|
|
179
|
+
);
|
|
180
|
+
},
|
|
181
|
+
/**
|
|
182
|
+
* Creates a transaction timeout error
|
|
183
|
+
*/
|
|
184
|
+
transactionTimeout(hash) {
|
|
185
|
+
return new MovementError(
|
|
186
|
+
`Transaction ${hash} timed out waiting for confirmation`,
|
|
187
|
+
"TRANSACTION_TIMEOUT",
|
|
188
|
+
{ hash }
|
|
189
|
+
);
|
|
190
|
+
},
|
|
191
|
+
/**
|
|
192
|
+
* Creates a view function failed error
|
|
193
|
+
*/
|
|
194
|
+
viewFunctionFailed(functionName, args, originalError) {
|
|
195
|
+
const errorMessage = originalError instanceof Error ? originalError.message : String(originalError);
|
|
196
|
+
return new MovementError(
|
|
197
|
+
`View function "${functionName}" failed: ${errorMessage}`,
|
|
198
|
+
"VIEW_FUNCTION_FAILED",
|
|
199
|
+
{ function: functionName, args, originalError }
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
/**
|
|
203
|
+
* Creates an invalid event handle error
|
|
204
|
+
*/
|
|
205
|
+
invalidEventHandle(eventHandle) {
|
|
206
|
+
return new MovementError(
|
|
207
|
+
`Invalid event handle format: ${eventHandle}`,
|
|
208
|
+
"INVALID_EVENT_HANDLE",
|
|
209
|
+
{ eventHandle, expectedFormat: "0xADDRESS::module::EventType" }
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
/**
|
|
213
|
+
* Creates a network error
|
|
214
|
+
*/
|
|
215
|
+
networkError(url, httpStatus, responseBody) {
|
|
216
|
+
return new MovementError(
|
|
217
|
+
`Network request to ${url} failed${httpStatus ? ` with status ${httpStatus}` : ""}`,
|
|
218
|
+
"NETWORK_ERROR",
|
|
219
|
+
{ url, httpStatus, responseBody }
|
|
220
|
+
);
|
|
221
|
+
},
|
|
222
|
+
/**
|
|
223
|
+
* Creates an ABI fetch failed error
|
|
224
|
+
*/
|
|
225
|
+
abiFetchFailed(address, network, originalError) {
|
|
226
|
+
const errorMessage = originalError instanceof Error ? originalError.message : String(originalError);
|
|
227
|
+
return new MovementError(
|
|
228
|
+
`Failed to fetch ABI for ${address} on ${network}: ${errorMessage}`,
|
|
229
|
+
"ABI_FETCH_FAILED",
|
|
230
|
+
{ address, network, originalError }
|
|
231
|
+
);
|
|
232
|
+
},
|
|
233
|
+
/**
|
|
234
|
+
* Creates a codegen failed error
|
|
235
|
+
*/
|
|
236
|
+
codegenFailed(reason, abi) {
|
|
237
|
+
return new MovementError(
|
|
238
|
+
`Code generation failed: ${reason}`,
|
|
239
|
+
"CODEGEN_FAILED",
|
|
240
|
+
{ reason, abi }
|
|
241
|
+
);
|
|
242
|
+
},
|
|
243
|
+
/**
|
|
244
|
+
* Creates an invalid argument error
|
|
245
|
+
*/
|
|
246
|
+
invalidArgument(argument, reason) {
|
|
247
|
+
return new MovementError(
|
|
248
|
+
`Invalid argument "${argument}": ${reason}`,
|
|
249
|
+
"INVALID_ARGUMENT",
|
|
250
|
+
{ argument, reason }
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
function isMovementError(error) {
|
|
255
|
+
return error instanceof MovementError;
|
|
256
|
+
}
|
|
257
|
+
function wrapError(error, code, context) {
|
|
258
|
+
if (isMovementError(error)) {
|
|
259
|
+
return error;
|
|
260
|
+
}
|
|
261
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
262
|
+
return new MovementError(
|
|
263
|
+
context ? `${context}: ${message}` : message,
|
|
264
|
+
code,
|
|
265
|
+
{ originalError: error }
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/wallet.ts
|
|
270
|
+
var import_eventemitter3 = __toESM(require("eventemitter3"));
|
|
271
|
+
var import_wallet_standard = require("@aptos-labs/wallet-standard");
|
|
272
|
+
var SUPPORTED_WALLETS = {
|
|
273
|
+
"petra": "petra",
|
|
274
|
+
"petra wallet": "petra",
|
|
275
|
+
"pontem": "pontem",
|
|
276
|
+
"pontem wallet": "pontem",
|
|
277
|
+
"nightly": "nightly",
|
|
278
|
+
"nightly wallet": "nightly"
|
|
279
|
+
};
|
|
280
|
+
var STORAGE_KEY = "movebridge:lastWallet";
|
|
281
|
+
function toHexString(data) {
|
|
282
|
+
if (typeof data === "string") return data;
|
|
283
|
+
if (data instanceof Uint8Array) {
|
|
284
|
+
return "0x" + Array.from(data).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
285
|
+
}
|
|
286
|
+
if (data && typeof data.toString === "function") {
|
|
287
|
+
return data.toString();
|
|
288
|
+
}
|
|
289
|
+
return String(data);
|
|
290
|
+
}
|
|
291
|
+
function createStandardAdapter(wallet) {
|
|
292
|
+
const connectFeature = wallet.features?.["aptos:connect"];
|
|
293
|
+
const disconnectFeature = wallet.features?.["aptos:disconnect"];
|
|
294
|
+
const signTxFeature = wallet.features?.["aptos:signAndSubmitTransaction"];
|
|
295
|
+
const signOnlyFeature = wallet.features?.["aptos:signTransaction"];
|
|
296
|
+
const accountChangeFeature = wallet.features?.["aptos:onAccountChange"];
|
|
297
|
+
const networkChangeFeature = wallet.features?.["aptos:onNetworkChange"];
|
|
298
|
+
return {
|
|
299
|
+
name: wallet.name,
|
|
300
|
+
icon: wallet.icon || "",
|
|
301
|
+
async connect() {
|
|
302
|
+
if (!connectFeature) throw new Error("Wallet does not support connect");
|
|
303
|
+
const response = await connectFeature.connect();
|
|
304
|
+
const result = response?.args ?? response;
|
|
305
|
+
if (response?.status === "rejected") {
|
|
306
|
+
throw new Error("User rejected the connection");
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
address: toHexString(result.address),
|
|
310
|
+
publicKey: toHexString(result.publicKey)
|
|
311
|
+
};
|
|
312
|
+
},
|
|
313
|
+
async disconnect() {
|
|
314
|
+
if (disconnectFeature) await disconnectFeature.disconnect();
|
|
315
|
+
},
|
|
316
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
317
|
+
async signAndSubmitTransaction(payload) {
|
|
318
|
+
if (!signTxFeature) throw new Error("Wallet does not support signAndSubmitTransaction");
|
|
319
|
+
const response = await signTxFeature.signAndSubmitTransaction(payload);
|
|
320
|
+
if (response?.status === "rejected") {
|
|
321
|
+
throw new Error("User rejected the transaction");
|
|
322
|
+
}
|
|
323
|
+
const result = response?.args ?? response;
|
|
324
|
+
return { hash: result.hash || toHexString(result) };
|
|
325
|
+
},
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
327
|
+
async signTransaction(payload) {
|
|
328
|
+
if (!signOnlyFeature) throw new Error("Wallet does not support signTransaction");
|
|
329
|
+
const response = await signOnlyFeature.signTransaction(payload);
|
|
330
|
+
if (response?.status === "rejected") {
|
|
331
|
+
throw new Error("User rejected the transaction");
|
|
332
|
+
}
|
|
333
|
+
const result = response?.args ?? response;
|
|
334
|
+
return result.authenticator || result.signature || new Uint8Array();
|
|
335
|
+
},
|
|
336
|
+
onAccountChange(cb) {
|
|
337
|
+
if (accountChangeFeature) {
|
|
338
|
+
accountChangeFeature.onAccountChange((account) => {
|
|
339
|
+
if (account) {
|
|
340
|
+
cb({ address: toHexString(account.address), publicKey: toHexString(account.publicKey) });
|
|
341
|
+
} else {
|
|
342
|
+
cb(null);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
onNetworkChange(cb) {
|
|
348
|
+
if (networkChangeFeature) {
|
|
349
|
+
networkChangeFeature.onNetworkChange((network) => {
|
|
350
|
+
cb(network?.name || String(network));
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
var WalletManager = class extends import_eventemitter3.default {
|
|
357
|
+
state = { connected: false, address: null, publicKey: null };
|
|
358
|
+
currentWallet = null;
|
|
359
|
+
adapter = null;
|
|
360
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
361
|
+
standardWallets = /* @__PURE__ */ new Map();
|
|
362
|
+
detectedWallets = [];
|
|
363
|
+
unsubscribe = null;
|
|
364
|
+
detectWallets() {
|
|
365
|
+
if (typeof window === "undefined") return [];
|
|
366
|
+
const available = /* @__PURE__ */ new Set();
|
|
367
|
+
this.standardWallets.clear();
|
|
368
|
+
try {
|
|
369
|
+
const { aptosWallets, on } = (0, import_wallet_standard.getAptosWallets)();
|
|
370
|
+
if (this.unsubscribe) this.unsubscribe();
|
|
371
|
+
this.unsubscribe = on("register", () => this.detectWallets());
|
|
372
|
+
for (const wallet of aptosWallets) {
|
|
373
|
+
const normalizedName = wallet.name.toLowerCase();
|
|
374
|
+
const walletType = SUPPORTED_WALLETS[normalizedName];
|
|
375
|
+
if (walletType) {
|
|
376
|
+
available.add(walletType);
|
|
377
|
+
this.standardWallets.set(walletType, wallet);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
} catch (error) {
|
|
381
|
+
console.warn("Failed to detect wallets via AIP-62 standard:", error);
|
|
382
|
+
}
|
|
383
|
+
this.detectedWallets = Array.from(available);
|
|
384
|
+
return this.detectedWallets;
|
|
385
|
+
}
|
|
386
|
+
getWalletInfo() {
|
|
387
|
+
return this.detectedWallets.map((type) => {
|
|
388
|
+
const wallet = this.standardWallets.get(type);
|
|
389
|
+
return { type, name: wallet?.name || type, icon: wallet?.icon || "" };
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
async connect(wallet) {
|
|
393
|
+
const available = this.detectWallets();
|
|
394
|
+
if (!available.includes(wallet)) throw Errors.walletNotFound(wallet, available);
|
|
395
|
+
try {
|
|
396
|
+
const standardWallet = this.standardWallets.get(wallet);
|
|
397
|
+
if (!standardWallet) throw new Error(`Wallet ${wallet} not found`);
|
|
398
|
+
this.adapter = createStandardAdapter(standardWallet);
|
|
399
|
+
const result = await this.adapter.connect();
|
|
400
|
+
this.state = { connected: true, address: result.address, publicKey: result.publicKey };
|
|
401
|
+
this.currentWallet = wallet;
|
|
402
|
+
this.saveLastWallet(wallet);
|
|
403
|
+
this.setupEventListeners();
|
|
404
|
+
this.emit("connect", result.address);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
this.adapter = null;
|
|
407
|
+
throw Errors.walletConnectionFailed(wallet, error);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
async disconnect() {
|
|
411
|
+
if (this.adapter) {
|
|
412
|
+
try {
|
|
413
|
+
await this.adapter.disconnect();
|
|
414
|
+
} catch {
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
this.state = { connected: false, address: null, publicKey: null };
|
|
418
|
+
this.currentWallet = null;
|
|
419
|
+
this.adapter = null;
|
|
420
|
+
this.clearLastWallet();
|
|
421
|
+
this.emit("disconnect");
|
|
422
|
+
}
|
|
423
|
+
getState() {
|
|
424
|
+
return { ...this.state };
|
|
425
|
+
}
|
|
426
|
+
getWallet() {
|
|
427
|
+
return this.currentWallet;
|
|
428
|
+
}
|
|
429
|
+
getAdapter() {
|
|
430
|
+
return this.adapter;
|
|
431
|
+
}
|
|
432
|
+
async autoConnect() {
|
|
433
|
+
const lastWallet = this.getLastWallet();
|
|
434
|
+
if (!lastWallet) return;
|
|
435
|
+
const available = this.detectWallets();
|
|
436
|
+
if (available.includes(lastWallet)) {
|
|
437
|
+
try {
|
|
438
|
+
await this.connect(lastWallet);
|
|
439
|
+
} catch {
|
|
440
|
+
this.clearLastWallet();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
destroy() {
|
|
445
|
+
if (this.unsubscribe) {
|
|
446
|
+
this.unsubscribe();
|
|
447
|
+
this.unsubscribe = null;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
setupEventListeners() {
|
|
451
|
+
if (!this.adapter) return;
|
|
452
|
+
this.adapter.onAccountChange((account) => {
|
|
453
|
+
if (account) {
|
|
454
|
+
this.state = { connected: true, address: account.address, publicKey: account.publicKey };
|
|
455
|
+
this.emit("accountChanged", account.address);
|
|
456
|
+
} else {
|
|
457
|
+
this.state = { connected: false, address: null, publicKey: null };
|
|
458
|
+
this.emit("disconnect");
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
this.adapter.onNetworkChange((network) => this.emit("networkChanged", network));
|
|
462
|
+
}
|
|
463
|
+
saveLastWallet(wallet) {
|
|
464
|
+
try {
|
|
465
|
+
if (typeof localStorage !== "undefined") localStorage.setItem(STORAGE_KEY, wallet);
|
|
466
|
+
} catch {
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
getLastWallet() {
|
|
470
|
+
try {
|
|
471
|
+
if (typeof localStorage !== "undefined") {
|
|
472
|
+
const wallet = localStorage.getItem(STORAGE_KEY);
|
|
473
|
+
if (wallet && Object.values(SUPPORTED_WALLETS).includes(wallet)) {
|
|
474
|
+
return wallet;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
} catch {
|
|
478
|
+
}
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
clearLastWallet() {
|
|
482
|
+
try {
|
|
483
|
+
if (typeof localStorage !== "undefined") localStorage.removeItem(STORAGE_KEY);
|
|
484
|
+
} catch {
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// src/transaction.ts
|
|
490
|
+
var TransactionBuilder = class {
|
|
491
|
+
constructor(aptosClient, walletManager) {
|
|
492
|
+
this.aptosClient = aptosClient;
|
|
493
|
+
this.walletManager = walletManager;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Builds a transfer transaction payload
|
|
497
|
+
* @param options - Transfer options
|
|
498
|
+
* @returns Transaction payload
|
|
499
|
+
*/
|
|
500
|
+
async transfer(options) {
|
|
501
|
+
const coinType = options.coinType ?? DEFAULT_COIN_TYPE;
|
|
502
|
+
return {
|
|
503
|
+
type: "entry_function_payload",
|
|
504
|
+
function: "0x1::coin::transfer",
|
|
505
|
+
typeArguments: [coinType],
|
|
506
|
+
arguments: [options.to, options.amount]
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Builds a generic transaction payload
|
|
511
|
+
* @param options - Build options
|
|
512
|
+
* @returns Transaction payload
|
|
513
|
+
*/
|
|
514
|
+
async build(options) {
|
|
515
|
+
return {
|
|
516
|
+
type: "entry_function_payload",
|
|
517
|
+
function: options.function,
|
|
518
|
+
typeArguments: options.typeArguments,
|
|
519
|
+
arguments: options.arguments
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Signs a transaction payload
|
|
524
|
+
* @param payload - Transaction payload to sign
|
|
525
|
+
* @returns Signed transaction
|
|
526
|
+
* @throws MovementError with code WALLET_NOT_CONNECTED if no wallet is connected
|
|
527
|
+
*/
|
|
528
|
+
async sign(payload) {
|
|
529
|
+
const adapter = this.walletManager.getAdapter();
|
|
530
|
+
const state = this.walletManager.getState();
|
|
531
|
+
if (!adapter || !state.connected || !state.address) {
|
|
532
|
+
throw Errors.walletNotConnected();
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
const signatureBytes = await adapter.signTransaction({
|
|
536
|
+
type: payload.type,
|
|
537
|
+
function: payload.function,
|
|
538
|
+
type_arguments: payload.typeArguments,
|
|
539
|
+
arguments: payload.arguments
|
|
540
|
+
});
|
|
541
|
+
const signature = Array.from(signatureBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
542
|
+
return {
|
|
543
|
+
payload,
|
|
544
|
+
signature: `0x${signature}`,
|
|
545
|
+
sender: state.address
|
|
546
|
+
};
|
|
547
|
+
} catch (error) {
|
|
548
|
+
throw wrapError(error, "TRANSACTION_FAILED", "Failed to sign transaction");
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Submits a signed transaction to the network
|
|
553
|
+
* @param signed - Signed transaction
|
|
554
|
+
* @returns Transaction hash
|
|
555
|
+
*/
|
|
556
|
+
async submit(signed) {
|
|
557
|
+
const adapter = this.walletManager.getAdapter();
|
|
558
|
+
if (!adapter) {
|
|
559
|
+
throw Errors.walletNotConnected();
|
|
560
|
+
}
|
|
561
|
+
try {
|
|
562
|
+
const result = await adapter.signAndSubmitTransaction({
|
|
563
|
+
type: signed.payload.type,
|
|
564
|
+
function: signed.payload.function,
|
|
565
|
+
type_arguments: signed.payload.typeArguments,
|
|
566
|
+
arguments: signed.payload.arguments
|
|
567
|
+
});
|
|
568
|
+
return result.hash;
|
|
569
|
+
} catch (error) {
|
|
570
|
+
throw wrapError(error, "TRANSACTION_FAILED", "Failed to submit transaction");
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Signs and submits a transaction in one step
|
|
575
|
+
* @param payload - Transaction payload
|
|
576
|
+
* @returns Transaction hash
|
|
577
|
+
*/
|
|
578
|
+
async signAndSubmit(payload) {
|
|
579
|
+
const adapter = this.walletManager.getAdapter();
|
|
580
|
+
if (!adapter) {
|
|
581
|
+
throw Errors.walletNotConnected();
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const result = await adapter.signAndSubmitTransaction({
|
|
585
|
+
type: payload.type,
|
|
586
|
+
function: payload.function,
|
|
587
|
+
type_arguments: payload.typeArguments,
|
|
588
|
+
arguments: payload.arguments
|
|
589
|
+
});
|
|
590
|
+
return result.hash;
|
|
591
|
+
} catch (error) {
|
|
592
|
+
throw wrapError(error, "TRANSACTION_FAILED", "Failed to sign and submit transaction");
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Simulates a transaction without submitting
|
|
597
|
+
* @param payload - Transaction payload
|
|
598
|
+
* @returns Simulation result with gas estimate
|
|
599
|
+
*/
|
|
600
|
+
async simulate(payload) {
|
|
601
|
+
const state = this.walletManager.getState();
|
|
602
|
+
if (!state.connected || !state.address) {
|
|
603
|
+
throw Errors.walletNotConnected();
|
|
604
|
+
}
|
|
605
|
+
try {
|
|
606
|
+
const client = this.aptosClient;
|
|
607
|
+
const result = await client.transaction.simulate.simple({
|
|
608
|
+
sender: state.address,
|
|
609
|
+
data: {
|
|
610
|
+
function: payload.function,
|
|
611
|
+
typeArguments: payload.typeArguments,
|
|
612
|
+
functionArguments: payload.arguments
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
const simResult = result[0];
|
|
616
|
+
return {
|
|
617
|
+
success: simResult?.success ?? false,
|
|
618
|
+
gasUsed: String(simResult?.gas_used ?? "0"),
|
|
619
|
+
vmStatus: String(simResult?.vm_status ?? "unknown")
|
|
620
|
+
};
|
|
621
|
+
} catch (error) {
|
|
622
|
+
throw wrapError(error, "TRANSACTION_FAILED", "Failed to simulate transaction");
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
// src/contract.ts
|
|
628
|
+
var ContractInterface = class {
|
|
629
|
+
constructor(aptosClient, walletManager, options) {
|
|
630
|
+
this.aptosClient = aptosClient;
|
|
631
|
+
this.walletManager = walletManager;
|
|
632
|
+
this.address = options.address;
|
|
633
|
+
this.module = options.module;
|
|
634
|
+
}
|
|
635
|
+
/** Contract address */
|
|
636
|
+
address;
|
|
637
|
+
/** Module name */
|
|
638
|
+
module;
|
|
639
|
+
/**
|
|
640
|
+
* Calls a view function (read-only)
|
|
641
|
+
* @param functionName - Name of the view function
|
|
642
|
+
* @param args - Function arguments
|
|
643
|
+
* @param typeArgs - Type arguments (optional)
|
|
644
|
+
* @returns Function result
|
|
645
|
+
* @throws MovementError with code VIEW_FUNCTION_FAILED if call fails
|
|
646
|
+
*/
|
|
647
|
+
async view(functionName, args, typeArgs = []) {
|
|
648
|
+
const fullFunctionName = `${this.address}::${this.module}::${functionName}`;
|
|
649
|
+
try {
|
|
650
|
+
const client = this.aptosClient;
|
|
651
|
+
const result = await client.view({
|
|
652
|
+
payload: {
|
|
653
|
+
function: fullFunctionName,
|
|
654
|
+
typeArguments: typeArgs,
|
|
655
|
+
functionArguments: args
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
return result.length === 1 ? result[0] : result;
|
|
659
|
+
} catch (error) {
|
|
660
|
+
throw Errors.viewFunctionFailed(fullFunctionName, args, error);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Calls an entry function (write operation)
|
|
665
|
+
* @param functionName - Name of the entry function
|
|
666
|
+
* @param args - Function arguments
|
|
667
|
+
* @param typeArgs - Type arguments (optional)
|
|
668
|
+
* @returns Transaction hash
|
|
669
|
+
* @throws MovementError with code WALLET_NOT_CONNECTED if no wallet is connected
|
|
670
|
+
* @throws MovementError with code TRANSACTION_FAILED if transaction fails
|
|
671
|
+
*/
|
|
672
|
+
async call(functionName, args, typeArgs = []) {
|
|
673
|
+
const adapter = this.walletManager.getAdapter();
|
|
674
|
+
const state = this.walletManager.getState();
|
|
675
|
+
if (!adapter || !state.connected) {
|
|
676
|
+
throw Errors.walletNotConnected();
|
|
677
|
+
}
|
|
678
|
+
const fullFunctionName = `${this.address}::${this.module}::${functionName}`;
|
|
679
|
+
try {
|
|
680
|
+
const result = await adapter.signAndSubmitTransaction({
|
|
681
|
+
type: "entry_function_payload",
|
|
682
|
+
function: fullFunctionName,
|
|
683
|
+
type_arguments: typeArgs,
|
|
684
|
+
arguments: args
|
|
685
|
+
});
|
|
686
|
+
return result.hash;
|
|
687
|
+
} catch (error) {
|
|
688
|
+
throw wrapError(error, "TRANSACTION_FAILED", `Failed to call ${fullFunctionName}`);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Checks if a resource exists at the contract address
|
|
693
|
+
* @param resourceType - Full resource type (e.g., '0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>')
|
|
694
|
+
* @returns true if resource exists
|
|
695
|
+
*/
|
|
696
|
+
async hasResource(resourceType) {
|
|
697
|
+
try {
|
|
698
|
+
const client = this.aptosClient;
|
|
699
|
+
await client.getAccountResource({
|
|
700
|
+
accountAddress: this.address,
|
|
701
|
+
resourceType
|
|
702
|
+
});
|
|
703
|
+
return true;
|
|
704
|
+
} catch {
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Gets a resource from the contract address
|
|
710
|
+
* @param resourceType - Full resource type
|
|
711
|
+
* @returns Resource data or null if not found
|
|
712
|
+
*/
|
|
713
|
+
async getResource(resourceType) {
|
|
714
|
+
try {
|
|
715
|
+
const client = this.aptosClient;
|
|
716
|
+
const resource = await client.getAccountResource({
|
|
717
|
+
accountAddress: this.address,
|
|
718
|
+
resourceType
|
|
719
|
+
});
|
|
720
|
+
return resource;
|
|
721
|
+
} catch {
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Gets the full function name for a function in this module
|
|
727
|
+
* @param functionName - Function name
|
|
728
|
+
* @returns Full function name (address::module::function)
|
|
729
|
+
*/
|
|
730
|
+
getFullFunctionName(functionName) {
|
|
731
|
+
return `${this.address}::${this.module}::${functionName}`;
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
// src/events.ts
|
|
736
|
+
var EventListener = class {
|
|
737
|
+
constructor(aptosClient, options) {
|
|
738
|
+
this.aptosClient = aptosClient;
|
|
739
|
+
this.pollIntervalMs = options?.pollIntervalMs ?? 3e3;
|
|
740
|
+
}
|
|
741
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
742
|
+
subscriptionCounter = 0;
|
|
743
|
+
pollIntervalMs;
|
|
744
|
+
/**
|
|
745
|
+
* Subscribes to contract events
|
|
746
|
+
* @param subscription - Subscription configuration
|
|
747
|
+
* @returns Subscription ID
|
|
748
|
+
* @throws MovementError with code INVALID_EVENT_HANDLE if event handle is invalid
|
|
749
|
+
*/
|
|
750
|
+
subscribe(subscription) {
|
|
751
|
+
if (!isValidEventHandle(subscription.eventHandle)) {
|
|
752
|
+
throw Errors.invalidEventHandle(subscription.eventHandle);
|
|
753
|
+
}
|
|
754
|
+
const subscriptionId = `sub_${++this.subscriptionCounter}`;
|
|
755
|
+
const internalSub = {
|
|
756
|
+
eventHandle: subscription.eventHandle,
|
|
757
|
+
callback: subscription.callback,
|
|
758
|
+
lastSequenceNumber: "0",
|
|
759
|
+
intervalId: null
|
|
760
|
+
};
|
|
761
|
+
internalSub.intervalId = setInterval(() => {
|
|
762
|
+
this.pollEvents(subscriptionId).catch(() => {
|
|
763
|
+
});
|
|
764
|
+
}, this.pollIntervalMs);
|
|
765
|
+
this.pollEvents(subscriptionId).catch(() => {
|
|
766
|
+
});
|
|
767
|
+
this.subscriptions.set(subscriptionId, internalSub);
|
|
768
|
+
return subscriptionId;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Unsubscribes from events
|
|
772
|
+
* @param subscriptionId - Subscription ID to remove
|
|
773
|
+
*/
|
|
774
|
+
unsubscribe(subscriptionId) {
|
|
775
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
776
|
+
if (subscription) {
|
|
777
|
+
if (subscription.intervalId) {
|
|
778
|
+
clearInterval(subscription.intervalId);
|
|
779
|
+
}
|
|
780
|
+
this.subscriptions.delete(subscriptionId);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Unsubscribes from all events
|
|
785
|
+
*/
|
|
786
|
+
unsubscribeAll() {
|
|
787
|
+
for (const [id] of this.subscriptions) {
|
|
788
|
+
this.unsubscribe(id);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Gets active subscription count
|
|
793
|
+
* @returns Number of active subscriptions
|
|
794
|
+
*/
|
|
795
|
+
getSubscriptionCount() {
|
|
796
|
+
return this.subscriptions.size;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Checks if a subscription exists
|
|
800
|
+
* @param subscriptionId - Subscription ID
|
|
801
|
+
* @returns true if subscription exists
|
|
802
|
+
*/
|
|
803
|
+
hasSubscription(subscriptionId) {
|
|
804
|
+
return this.subscriptions.has(subscriptionId);
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Polls for new events
|
|
808
|
+
* @param subscriptionId - Subscription ID
|
|
809
|
+
*/
|
|
810
|
+
async pollEvents(subscriptionId) {
|
|
811
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
812
|
+
if (!subscription) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
try {
|
|
816
|
+
const parts = subscription.eventHandle.split("::");
|
|
817
|
+
if (parts.length !== 3) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
const [address, module2, eventType] = parts;
|
|
821
|
+
const eventHandleStruct = `${address}::${module2}::${eventType}`;
|
|
822
|
+
const client = this.aptosClient;
|
|
823
|
+
const events = await client.getAccountEventsByEventType({
|
|
824
|
+
accountAddress: address,
|
|
825
|
+
eventType: eventHandleStruct,
|
|
826
|
+
options: {
|
|
827
|
+
limit: 25
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
for (const event of events) {
|
|
831
|
+
const sequenceNumber = event.sequence_number?.toString() ?? "0";
|
|
832
|
+
if (BigInt(sequenceNumber) > BigInt(subscription.lastSequenceNumber)) {
|
|
833
|
+
const contractEvent = {
|
|
834
|
+
type: event.type,
|
|
835
|
+
sequenceNumber,
|
|
836
|
+
data: event.data
|
|
837
|
+
};
|
|
838
|
+
subscription.callback(contractEvent);
|
|
839
|
+
subscription.lastSequenceNumber = sequenceNumber;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
} catch {
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
// src/client.ts
|
|
848
|
+
var Movement = class {
|
|
849
|
+
/** Resolved configuration */
|
|
850
|
+
config;
|
|
851
|
+
/** Aptos SDK client instance */
|
|
852
|
+
aptosClient;
|
|
853
|
+
/** Wallet manager instance */
|
|
854
|
+
wallet;
|
|
855
|
+
/** Transaction builder instance */
|
|
856
|
+
transaction;
|
|
857
|
+
/** Event listener instance */
|
|
858
|
+
events;
|
|
859
|
+
/**
|
|
860
|
+
* Creates a new Movement client
|
|
861
|
+
* @param config - Configuration options
|
|
862
|
+
*/
|
|
863
|
+
constructor(config) {
|
|
864
|
+
this.config = resolveConfig(config);
|
|
865
|
+
const aptosConfigOptions = {
|
|
866
|
+
network: import_ts_sdk.Network.CUSTOM,
|
|
867
|
+
fullnode: this.config.rpcUrl
|
|
868
|
+
};
|
|
869
|
+
if (this.config.indexerUrl) {
|
|
870
|
+
aptosConfigOptions.indexer = this.config.indexerUrl;
|
|
871
|
+
}
|
|
872
|
+
const aptosConfig = new import_ts_sdk.AptosConfig(aptosConfigOptions);
|
|
873
|
+
this.aptosClient = new import_ts_sdk.Aptos(aptosConfig);
|
|
874
|
+
this.wallet = new WalletManager();
|
|
875
|
+
this.transaction = new TransactionBuilder(this.aptosClient, this.wallet);
|
|
876
|
+
this.events = new EventListener(this.aptosClient);
|
|
877
|
+
if (this.config.autoConnect) {
|
|
878
|
+
this.wallet.autoConnect().catch(() => {
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Gets the underlying Aptos client
|
|
884
|
+
* @returns Aptos SDK client instance
|
|
885
|
+
*/
|
|
886
|
+
getAptosClient() {
|
|
887
|
+
return this.aptosClient;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Gets the account balance for an address
|
|
891
|
+
* @param address - Account address
|
|
892
|
+
* @returns Balance as string in smallest unit (octas)
|
|
893
|
+
* @throws MovementError with code INVALID_ADDRESS if address is invalid
|
|
894
|
+
*/
|
|
895
|
+
async getAccountBalance(address) {
|
|
896
|
+
if (!isValidAddress(address)) {
|
|
897
|
+
throw Errors.invalidAddress(address, "Invalid address format");
|
|
898
|
+
}
|
|
899
|
+
try {
|
|
900
|
+
const resources = await this.aptosClient.getAccountResources({
|
|
901
|
+
accountAddress: address
|
|
902
|
+
});
|
|
903
|
+
const coinResource = resources.find(
|
|
904
|
+
(r) => r.type === "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>"
|
|
905
|
+
);
|
|
906
|
+
if (!coinResource) {
|
|
907
|
+
return "0";
|
|
908
|
+
}
|
|
909
|
+
const data = coinResource.data;
|
|
910
|
+
return data.coin.value;
|
|
911
|
+
} catch (error) {
|
|
912
|
+
throw wrapError(error, "NETWORK_ERROR", `Failed to get balance for ${address}`);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Gets all resources for an account
|
|
917
|
+
* @param address - Account address
|
|
918
|
+
* @returns Array of resources
|
|
919
|
+
* @throws MovementError with code INVALID_ADDRESS if address is invalid
|
|
920
|
+
*/
|
|
921
|
+
async getAccountResources(address) {
|
|
922
|
+
if (!isValidAddress(address)) {
|
|
923
|
+
throw Errors.invalidAddress(address, "Invalid address format");
|
|
924
|
+
}
|
|
925
|
+
try {
|
|
926
|
+
const resources = await this.aptosClient.getAccountResources({
|
|
927
|
+
accountAddress: address
|
|
928
|
+
});
|
|
929
|
+
return resources.map((r) => ({
|
|
930
|
+
type: r.type,
|
|
931
|
+
data: r.data
|
|
932
|
+
}));
|
|
933
|
+
} catch (error) {
|
|
934
|
+
if (error instanceof Error && error.message.includes("Account not found")) {
|
|
935
|
+
return [];
|
|
936
|
+
}
|
|
937
|
+
throw wrapError(error, "NETWORK_ERROR", `Failed to get resources for ${address}`);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Gets a transaction by hash
|
|
942
|
+
* @param hash - Transaction hash
|
|
943
|
+
* @returns Transaction data
|
|
944
|
+
*/
|
|
945
|
+
async getTransaction(hash) {
|
|
946
|
+
try {
|
|
947
|
+
const tx = await this.aptosClient.getTransactionByHash({ transactionHash: hash });
|
|
948
|
+
const userTx = tx;
|
|
949
|
+
return {
|
|
950
|
+
hash: userTx.hash,
|
|
951
|
+
sender: userTx.sender,
|
|
952
|
+
sequenceNumber: userTx.sequence_number,
|
|
953
|
+
payload: {
|
|
954
|
+
type: "entry_function_payload",
|
|
955
|
+
function: userTx.payload?.function ?? "",
|
|
956
|
+
typeArguments: userTx.payload?.type_arguments ?? [],
|
|
957
|
+
arguments: userTx.payload?.arguments ?? []
|
|
958
|
+
},
|
|
959
|
+
timestamp: userTx.timestamp
|
|
960
|
+
};
|
|
961
|
+
} catch (error) {
|
|
962
|
+
throw wrapError(error, "NETWORK_ERROR", `Failed to get transaction ${hash}`);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Waits for a transaction to be confirmed
|
|
967
|
+
* @param hash - Transaction hash
|
|
968
|
+
* @param options - Wait options
|
|
969
|
+
* @returns Transaction response
|
|
970
|
+
*/
|
|
971
|
+
async waitForTransaction(hash, options) {
|
|
972
|
+
const timeoutMs = options?.timeoutMs ?? 3e4;
|
|
973
|
+
const checkIntervalMs = options?.checkIntervalMs ?? 1e3;
|
|
974
|
+
const startTime = Date.now();
|
|
975
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
976
|
+
try {
|
|
977
|
+
const tx = await this.aptosClient.getTransactionByHash({ transactionHash: hash });
|
|
978
|
+
if ("success" in tx) {
|
|
979
|
+
const committedTx = tx;
|
|
980
|
+
return {
|
|
981
|
+
hash: committedTx.hash,
|
|
982
|
+
success: committedTx.success,
|
|
983
|
+
vmStatus: committedTx.vm_status,
|
|
984
|
+
gasUsed: committedTx.gas_used,
|
|
985
|
+
events: committedTx.events.map((e) => ({
|
|
986
|
+
type: e.type,
|
|
987
|
+
sequenceNumber: e.sequence_number,
|
|
988
|
+
data: e.data
|
|
989
|
+
}))
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
} catch {
|
|
993
|
+
}
|
|
994
|
+
await new Promise((resolve) => setTimeout(resolve, checkIntervalMs));
|
|
995
|
+
}
|
|
996
|
+
throw Errors.transactionTimeout(hash);
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Creates a contract interface for interacting with a Move module
|
|
1000
|
+
* @param options - Contract options
|
|
1001
|
+
* @returns Contract interface
|
|
1002
|
+
*/
|
|
1003
|
+
contract(options) {
|
|
1004
|
+
return new ContractInterface(this.aptosClient, this.wallet, options);
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1008
|
+
0 && (module.exports = {
|
|
1009
|
+
ContractInterface,
|
|
1010
|
+
DEFAULT_COIN_TYPE,
|
|
1011
|
+
Errors,
|
|
1012
|
+
EventListener,
|
|
1013
|
+
Movement,
|
|
1014
|
+
MovementError,
|
|
1015
|
+
NETWORK_CONFIG,
|
|
1016
|
+
TransactionBuilder,
|
|
1017
|
+
WalletManager,
|
|
1018
|
+
getExplorerAccountUrl,
|
|
1019
|
+
getExplorerTxUrl,
|
|
1020
|
+
isMovementError,
|
|
1021
|
+
isValidAddress,
|
|
1022
|
+
isValidEventHandle,
|
|
1023
|
+
resolveConfig,
|
|
1024
|
+
wrapError
|
|
1025
|
+
});
|