@fastnear/api 0.1.0 → 0.4.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.
Files changed (44) hide show
  1. package/dist/cjs/cryptoUtils.js +89 -0
  2. package/dist/cjs/cryptoUtils.js.map +7 -0
  3. package/dist/cjs/index.esm.js +1219 -0
  4. package/dist/cjs/index.esm.js.map +7 -0
  5. package/dist/cjs/index.js +1274 -0
  6. package/dist/cjs/index.js.map +7 -0
  7. package/dist/cjs/near.js +1219 -0
  8. package/dist/cjs/near.js.map +7 -0
  9. package/dist/cjs/transaction.js +360 -0
  10. package/dist/cjs/transaction.js.map +7 -0
  11. package/dist/cjs/utils.js +105 -0
  12. package/dist/cjs/utils.js.map +7 -0
  13. package/dist/esm/chunk-2SCAGR3F.js +68 -0
  14. package/dist/esm/chunk-2SCAGR3F.js.map +7 -0
  15. package/dist/esm/chunk-OR3WITSY.js +842 -0
  16. package/dist/esm/chunk-OR3WITSY.js.map +7 -0
  17. package/dist/esm/chunk-S5Q2EM2B.js +48 -0
  18. package/dist/esm/chunk-S5Q2EM2B.js.map +7 -0
  19. package/{src/transaction.js → dist/esm/chunk-YKPILPMX.js} +113 -99
  20. package/dist/esm/chunk-YKPILPMX.js.map +7 -0
  21. package/dist/esm/cryptoUtils.js +21 -0
  22. package/dist/esm/cryptoUtils.js.map +7 -0
  23. package/dist/esm/index.esm.js +13 -0
  24. package/dist/esm/index.esm.js.map +7 -0
  25. package/dist/esm/index.js +63 -0
  26. package/dist/esm/index.js.map +7 -0
  27. package/dist/esm/near.js +15 -0
  28. package/dist/esm/near.js.map +7 -0
  29. package/dist/esm/transaction.js +16 -0
  30. package/dist/esm/transaction.js.map +7 -0
  31. package/dist/esm/utils.js +24 -0
  32. package/dist/esm/utils.js.map +7 -0
  33. package/dist/umd/index.js +4227 -0
  34. package/dist/umd/index.js.map +7 -0
  35. package/package.json +35 -25
  36. package/README.md +0 -76
  37. package/dist/fastnear.cjs +0 -35
  38. package/dist/fastnear.ejs +0 -24
  39. package/dist/fastnear.js +0 -35
  40. package/src/crypto.js +0 -37
  41. package/src/index.esm.js +0 -3
  42. package/src/index.js +0 -8
  43. package/src/near.js +0 -566
  44. package/src/utils.js +0 -48
@@ -0,0 +1,842 @@
1
+ /* ⋈ 🏃🏻💨 FastNEAR API - https://github.com/fastnear */
2
+ import {
3
+ serializeSignedTransaction,
4
+ serializeTransaction
5
+ } from "./chunk-YKPILPMX.js";
6
+ import {
7
+ privateKeyFromRandom,
8
+ publicKeyFromPrivate,
9
+ sha256,
10
+ signHash
11
+ } from "./chunk-S5Q2EM2B.js";
12
+ import {
13
+ canSignWithLAK,
14
+ fromBase58,
15
+ fromBase64,
16
+ lsGet,
17
+ lsSet,
18
+ toBase58,
19
+ toBase64,
20
+ tryParseJson
21
+ } from "./chunk-2SCAGR3F.js";
22
+
23
+ // src/near.ts
24
+ import Big from "big.js";
25
+
26
+ // ../wallet-adapter/src/index.ts
27
+ var WalletAdapter = class _WalletAdapter {
28
+ /** @type {HTMLIFrameElement} */
29
+ #iframe = null;
30
+ /** @type {string} */
31
+ #targetOrigin;
32
+ /** @type {string} */
33
+ #widgetUrl;
34
+ /** @type {Map<string, Function>} */
35
+ #pending = /* @__PURE__ */ new Map();
36
+ /** @type {WalletState} */
37
+ #state;
38
+ /** @type {Function} */
39
+ #onStateUpdate;
40
+ /** @type {string} */
41
+ #callbackUrl;
42
+ /** @type {string} */
43
+ static defaultWidgetUrl = "https://wallet-adapter.fastnear.com";
44
+ /**
45
+ * @param {WalletAdapterConfig} [config]
46
+ */
47
+ constructor({
48
+ widgetUrl = _WalletAdapter.defaultWidgetUrl,
49
+ targetOrigin = "*",
50
+ onStateUpdate,
51
+ lastState,
52
+ callbackUrl = window.location.href
53
+ } = {}) {
54
+ this.#targetOrigin = targetOrigin;
55
+ this.#widgetUrl = widgetUrl;
56
+ this.#onStateUpdate = onStateUpdate;
57
+ this.#callbackUrl = callbackUrl;
58
+ this.#state = lastState || {};
59
+ window.addEventListener("message", this.#handleMessage.bind(this));
60
+ }
61
+ /**
62
+ * Creates an iframe for wallet interaction
63
+ * @param {string} path - Path to load in iframe
64
+ * @returns {HTMLIFrameElement}
65
+ */
66
+ #createIframe(path) {
67
+ if (this.#iframe) {
68
+ this.#iframe.remove();
69
+ }
70
+ const url = new URL(path, this.#widgetUrl);
71
+ const iframe = document.createElement("iframe");
72
+ iframe.src = url.toString();
73
+ iframe.allow = "usb";
74
+ iframe.style.border = "none";
75
+ iframe.style.zIndex = "10000";
76
+ iframe.style.position = "fixed";
77
+ iframe.style.display = "block";
78
+ iframe.style.top = "0";
79
+ iframe.style.left = "0";
80
+ iframe.style.width = "100%";
81
+ iframe.style.height = "100%";
82
+ document.body.appendChild(iframe);
83
+ this.#iframe = iframe;
84
+ return iframe;
85
+ }
86
+ /**
87
+ * Handles messages from the wallet widget
88
+ * @param {MessageEvent} event
89
+ */
90
+ #handleMessage(event) {
91
+ if (this.#targetOrigin !== "*" && event.origin !== this.#targetOrigin) {
92
+ return;
93
+ }
94
+ const { id, type, action, payload } = event.data;
95
+ if (type !== "wallet-adapter") return;
96
+ if (action === "close") {
97
+ this.#iframe?.remove();
98
+ this.#iframe = null;
99
+ return;
100
+ }
101
+ if (payload?.state) {
102
+ this.#state = { ...this.#state, ...payload.state };
103
+ this.#onStateUpdate?.(this.#state);
104
+ }
105
+ const resolve = this.#pending.get(id);
106
+ if (resolve) {
107
+ this.#pending.delete(id);
108
+ this.#iframe?.remove();
109
+ this.#iframe = null;
110
+ resolve(payload);
111
+ }
112
+ }
113
+ /**
114
+ * Sends a message to the wallet widget
115
+ * @param {string} path - Path to load in iframe
116
+ * @param {string} method - Method to call
117
+ * @param {Object} params - Parameters to pass
118
+ * @returns {Promise<any>}
119
+ */
120
+ async #sendMessage(path, method, params) {
121
+ return new Promise((resolve) => {
122
+ const id = Math.random().toString(36).slice(2);
123
+ this.#pending.set(id, resolve);
124
+ const iframe = this.#createIframe(path);
125
+ iframe.onload = () => {
126
+ iframe.contentWindow?.postMessage(
127
+ {
128
+ type: "wallet-adapter",
129
+ method,
130
+ params: {
131
+ id,
132
+ ...params,
133
+ state: this.#state,
134
+ callbackUrl: params.callbackUrl || this.#callbackUrl
135
+ }
136
+ },
137
+ this.#targetOrigin
138
+ );
139
+ };
140
+ });
141
+ }
142
+ /**
143
+ * Get current wallet state
144
+ * @returns {WalletState}
145
+ */
146
+ getState() {
147
+ return { ...this.#state };
148
+ }
149
+ /**
150
+ * Set current wallet state
151
+ * @param state
152
+ */
153
+ setState(state) {
154
+ this.#state = state;
155
+ }
156
+ /**
157
+ * Sign in with a NEAR wallet
158
+ * @param {SignInConfig} config
159
+ * @returns {Promise<SignInResult>}
160
+ */
161
+ async signIn(config) {
162
+ return this.#sendMessage("/login.html", "signIn", config);
163
+ }
164
+ /**
165
+ * Send a transaction using connected wallet
166
+ * @param {TransactionConfig} config
167
+ * @returns {Promise<TransactionResult>}
168
+ */
169
+ async sendTransactions(config) {
170
+ return this.#sendMessage("/send.html", "sendTransactions", config);
171
+ }
172
+ /**
173
+ * Clean up adapter resources
174
+ */
175
+ destroy() {
176
+ window.removeEventListener("message", this.#handleMessage);
177
+ this.#iframe?.remove();
178
+ this.#iframe = null;
179
+ }
180
+ };
181
+
182
+ // src/near.ts
183
+ Big.DP = 27;
184
+ var MaxBlockDelayMs = 1e3 * 60 * 60 * 6;
185
+ var WIDGET_URL = "http://localhost:3000/";
186
+ var DEFAULT_NETWORK_ID = "mainnet";
187
+ var NETWORKS = {
188
+ testnet: {
189
+ networkId: "testnet",
190
+ nodeUrl: "https://rpc.testnet.fastnear.com/"
191
+ },
192
+ mainnet: {
193
+ networkId: "mainnet",
194
+ nodeUrl: "https://rpc.mainnet.fastnear.com/"
195
+ }
196
+ };
197
+ var _config = lsGet("config") || { ...NETWORKS[DEFAULT_NETWORK_ID] };
198
+ var _state = lsGet("state") || {};
199
+ try {
200
+ _state.publicKey = _state.privateKey ? publicKeyFromPrivate(_state.privateKey) : null;
201
+ } catch (e) {
202
+ console.error("Error parsing private key:", e);
203
+ _state.privateKey = null;
204
+ lsSet("nonce", null);
205
+ }
206
+ var _txHistory = lsGet("txHistory") || {};
207
+ var _eventListeners = {
208
+ account: /* @__PURE__ */ new Set(),
209
+ tx: /* @__PURE__ */ new Set()
210
+ };
211
+ var _unbroadcastedEvents = {
212
+ account: [],
213
+ tx: []
214
+ };
215
+ function getWalletAdapterState() {
216
+ return {
217
+ publicKey: _state.publicKey,
218
+ accountId: _state.accountId,
219
+ lastWalletId: _state.lastWalletId,
220
+ networkId: DEFAULT_NETWORK_ID
221
+ };
222
+ }
223
+ var _adapter;
224
+ function updateState(newState) {
225
+ const oldState = _state;
226
+ _state = { ..._state, ...newState };
227
+ lsSet("state", {
228
+ accountId: _state.accountId,
229
+ privateKey: _state.privateKey,
230
+ lastWalletId: _state.lastWalletId,
231
+ accessKeyContractId: _state.accessKeyContractId
232
+ });
233
+ if (newState.hasOwnProperty("privateKey") && newState.privateKey !== oldState.privateKey) {
234
+ _state.publicKey = newState.privateKey ? publicKeyFromPrivate(newState.privateKey) : null;
235
+ lsSet("nonce", null);
236
+ }
237
+ if (newState.accountId !== oldState.accountId) {
238
+ notifyAccountListeners(newState.accountId);
239
+ }
240
+ if (newState.hasOwnProperty("lastWalletId") && newState.lastWalletId !== oldState.lastWalletId || newState.hasOwnProperty("accountId") && newState.accountId !== oldState.accountId || newState.hasOwnProperty("privateKey") && newState.privateKey !== oldState.privateKey) {
241
+ _adapter.setState(getWalletAdapterState());
242
+ }
243
+ }
244
+ function updateTxHistory(txStatus) {
245
+ const txId = txStatus.txId;
246
+ _txHistory[txId] = {
247
+ ..._txHistory[txId] ?? {},
248
+ ...txStatus,
249
+ updateTimestamp: Date.now()
250
+ };
251
+ lsSet("txHistory", _txHistory);
252
+ notifyTxListeners(_txHistory[txId]);
253
+ }
254
+ function onAdapterStateUpdate(state) {
255
+ console.log("Adapter state update:", state);
256
+ const { accountId, lastWalletId, privateKey } = state;
257
+ updateState({
258
+ accountId,
259
+ lastWalletId,
260
+ ...privateKey && { privateKey }
261
+ });
262
+ }
263
+ _adapter = new WalletAdapter({
264
+ onStateUpdate: onAdapterStateUpdate,
265
+ lastState: getWalletAdapterState(),
266
+ widgetUrl: WIDGET_URL
267
+ });
268
+ function parseJsonFromBytes(bytes) {
269
+ try {
270
+ const decoder = new TextDecoder();
271
+ return JSON.parse(decoder.decode(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)));
272
+ } catch (e) {
273
+ try {
274
+ return bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
275
+ } catch (e2) {
276
+ return bytes;
277
+ }
278
+ }
279
+ }
280
+ function withBlockId(params, blockId) {
281
+ return blockId === "final" || blockId === "optimistic" ? { ...params, finality: blockId } : blockId ? { ...params, block_id: blockId } : { ...params, finality: "optimistic" };
282
+ }
283
+ async function queryRpc(method, params) {
284
+ const response = await fetch(_config.nodeUrl, {
285
+ method: "POST",
286
+ headers: { "Content-Type": "application/json" },
287
+ body: JSON.stringify({
288
+ jsonrpc: "2.0",
289
+ id: `fastnear-${Date.now()}`,
290
+ method,
291
+ params
292
+ })
293
+ });
294
+ const result = await response.json();
295
+ if (result.error) {
296
+ throw new Error(JSON.stringify(result.error));
297
+ }
298
+ return result.result;
299
+ }
300
+ function afterTxSent(txId) {
301
+ queryRpc("tx", {
302
+ tx_hash: _txHistory[txId].txHash,
303
+ sender_account_id: _txHistory[txId].tx.signerId,
304
+ wait_until: "EXECUTED_OPTIMISTIC"
305
+ }).then((result) => {
306
+ const successValue = result?.status?.SuccessValue;
307
+ updateTxHistory({
308
+ txId,
309
+ status: "Executed",
310
+ result,
311
+ successValue: successValue ? tryParseJson(fromBase64(successValue)) : void 0,
312
+ finalState: true
313
+ });
314
+ }).catch((error) => {
315
+ updateTxHistory({
316
+ txId,
317
+ status: "ErrorAfterIncluded",
318
+ error: tryParseJson(error.message),
319
+ finalState: true
320
+ });
321
+ });
322
+ }
323
+ function sendTxToRpc(signedTxBase64, waitUntil, txId) {
324
+ queryRpc("send_tx", {
325
+ signed_tx_base64: signedTxBase64,
326
+ wait_until: waitUntil ?? "INCLUDED"
327
+ }).then((result) => {
328
+ console.log("Transaction included:", result);
329
+ updateTxHistory({
330
+ txId,
331
+ status: "Included",
332
+ finalState: false
333
+ });
334
+ afterTxSent(txId);
335
+ }).catch((error) => {
336
+ updateTxHistory({
337
+ txId,
338
+ status: "Error",
339
+ error: tryParseJson(error.message),
340
+ finalState: false
341
+ });
342
+ });
343
+ }
344
+ function notifyAccountListeners(accountId) {
345
+ if (_eventListeners.account.size === 0) {
346
+ _unbroadcastedEvents.account.push(accountId);
347
+ return;
348
+ }
349
+ _eventListeners.account.forEach((callback) => {
350
+ try {
351
+ callback(accountId);
352
+ } catch (e) {
353
+ console.error(e);
354
+ }
355
+ });
356
+ }
357
+ function notifyTxListeners(tx) {
358
+ if (_eventListeners.tx.size === 0) {
359
+ _unbroadcastedEvents.tx.push(tx);
360
+ return;
361
+ }
362
+ _eventListeners.tx.forEach((callback) => {
363
+ try {
364
+ callback(tx);
365
+ } catch (e) {
366
+ console.error(e);
367
+ }
368
+ });
369
+ }
370
+ function convertUnit(s, ...args) {
371
+ if (Array.isArray(s)) {
372
+ s = s.reduce((acc, part, i) => {
373
+ return acc + (args[i - 1] ?? "") + part;
374
+ });
375
+ }
376
+ if (typeof s == "string") {
377
+ const match = s.match(/([0-9.,_]+)\s*([a-zA-Z]+)?/);
378
+ if (match) {
379
+ const amount = match[1].replace(/[_,]/g, "");
380
+ const unitPart = match[2];
381
+ if (unitPart) {
382
+ switch (unitPart.toLowerCase()) {
383
+ case "near":
384
+ return Big(amount).mul(Big(10).pow(24)).toFixed(0);
385
+ case "tgas":
386
+ return Big(amount).mul(Big(10).pow(12)).toFixed(0);
387
+ case "ggas":
388
+ return Big(amount).mul(Big(10).pow(9)).toFixed(0);
389
+ case "gas":
390
+ case "yoctonear":
391
+ return Big(amount).toFixed(0);
392
+ default:
393
+ throw new Error(`Unknown unit: ${unitPart}`);
394
+ }
395
+ } else {
396
+ return Big(amount).toFixed(0);
397
+ }
398
+ }
399
+ }
400
+ return Big(s).toFixed(0);
401
+ }
402
+ var api = {
403
+ // Context
404
+ get accountId() {
405
+ return _state.accountId;
406
+ },
407
+ get publicKey() {
408
+ return _state.publicKey;
409
+ },
410
+ config(newConfig) {
411
+ if (newConfig) {
412
+ if (newConfig.networkId && _config.networkId !== newConfig.networkId) {
413
+ _config = { ...NETWORKS[newConfig.networkId] };
414
+ updateState({
415
+ accountId: null,
416
+ privateKey: null,
417
+ lastWalletId: null
418
+ });
419
+ lsSet("block", null);
420
+ _txHistory = {};
421
+ lsSet("txHistory", _txHistory);
422
+ }
423
+ _config = { ..._config, ...newConfig };
424
+ lsSet("config", _config);
425
+ }
426
+ return _config;
427
+ },
428
+ get authStatus() {
429
+ if (!_state.accountId) {
430
+ return "SignedOut";
431
+ }
432
+ const accessKey = _state.publicKey;
433
+ const contractId = _state.accessKeyContractId;
434
+ if (accessKey && contractId && _state.privateKey) {
435
+ return {
436
+ type: "SignedInWithLimitedAccessKey",
437
+ accessKey,
438
+ contractId
439
+ };
440
+ }
441
+ return "SignedIn";
442
+ },
443
+ // Query Methods
444
+ async view({
445
+ contractId,
446
+ methodName,
447
+ args,
448
+ argsBase64,
449
+ blockId
450
+ }) {
451
+ const encodedArgs = argsBase64 || (args ? toBase64(JSON.stringify(args)) : "");
452
+ const result = await queryRpc(
453
+ "query",
454
+ withBlockId(
455
+ {
456
+ request_type: "call_function",
457
+ account_id: contractId,
458
+ method_name: methodName,
459
+ args_base64: encodedArgs
460
+ },
461
+ blockId
462
+ )
463
+ );
464
+ return parseJsonFromBytes(result.result);
465
+ },
466
+ async account({
467
+ accountId,
468
+ blockId
469
+ }) {
470
+ return queryRpc(
471
+ "query",
472
+ withBlockId(
473
+ {
474
+ request_type: "view_account",
475
+ account_id: accountId
476
+ },
477
+ blockId
478
+ )
479
+ );
480
+ },
481
+ async block({ blockId }) {
482
+ return queryRpc("block", withBlockId({}, blockId));
483
+ },
484
+ async accessKey({
485
+ accountId,
486
+ publicKey,
487
+ blockId
488
+ }) {
489
+ return queryRpc(
490
+ "query",
491
+ withBlockId(
492
+ {
493
+ request_type: "view_access_key",
494
+ account_id: accountId,
495
+ public_key: publicKey
496
+ },
497
+ blockId
498
+ )
499
+ );
500
+ },
501
+ async tx({ txHash, accountId }) {
502
+ return queryRpc("tx", [txHash, accountId]);
503
+ },
504
+ localTxHistory() {
505
+ return [..._txHistory];
506
+ },
507
+ // Transaction Methods
508
+ async sendTx({
509
+ receiverId,
510
+ actions,
511
+ waitUntil
512
+ }) {
513
+ const signerId = _state.accountId;
514
+ if (!signerId) {
515
+ throw new Error("Not signed in");
516
+ }
517
+ const publicKey = _state.publicKey;
518
+ const privateKey = _state.privateKey;
519
+ const txId = `tx-${Date.now()}-${Math.random()}`;
520
+ if (!privateKey || receiverId !== _state.accessKeyContractId || !canSignWithLAK(actions)) {
521
+ const jsonTransaction2 = {
522
+ signerId,
523
+ receiverId,
524
+ actions
525
+ };
526
+ updateTxHistory({
527
+ status: "Pending",
528
+ txId,
529
+ tx: jsonTransaction2,
530
+ finalState: false
531
+ });
532
+ const url = new URL(typeof window !== "undefined" ? window.location.href : "");
533
+ url.searchParams.set("txIds", txId);
534
+ _adapter.sendTransactions({
535
+ transactions: [jsonTransaction2],
536
+ callbackUrl: url.toString()
537
+ }).then((result) => {
538
+ console.log("Transaction result:", result);
539
+ if (result.url) {
540
+ console.log("Redirecting to wallet:", result.url);
541
+ if (typeof window !== "undefined") {
542
+ setTimeout(() => {
543
+ window.location.href = result.url;
544
+ }, 100);
545
+ }
546
+ } else if (result.outcomes) {
547
+ result.outcomes.forEach((r) => {
548
+ updateTxHistory({
549
+ txId,
550
+ status: "Executed",
551
+ result: r,
552
+ txHash: r.transaction.hash,
553
+ finalState: true
554
+ });
555
+ });
556
+ } else if (result.rejected) {
557
+ updateTxHistory({
558
+ txId,
559
+ status: "RejectedByUser",
560
+ finalState: true
561
+ });
562
+ } else if (result.error) {
563
+ updateTxHistory({
564
+ txId,
565
+ status: "Error",
566
+ error: tryParseJson(result.error),
567
+ finalState: true
568
+ });
569
+ }
570
+ }).catch((error) => {
571
+ updateTxHistory({
572
+ txId,
573
+ status: "Error",
574
+ error: tryParseJson(error.message),
575
+ finalState: true
576
+ });
577
+ });
578
+ return txId;
579
+ }
580
+ let nonce = lsGet("nonce");
581
+ let block = lsGet("block");
582
+ const toDoPromises = {};
583
+ if (nonce === null || nonce === void 0) {
584
+ toDoPromises.nonce = api.accessKey({
585
+ accountId: signerId,
586
+ publicKey
587
+ }).then((accessKey) => {
588
+ if (accessKey.error) {
589
+ throw new Error(`Access key error: ${accessKey.error}`);
590
+ }
591
+ lsSet("nonce", accessKey.nonce);
592
+ return accessKey.nonce;
593
+ });
594
+ }
595
+ if (!block || !block.header || parseFloat(block.header.timestamp_nanosec) / 1e6 + MaxBlockDelayMs < Date.now()) {
596
+ toDoPromises.block = api.block({ blockId: "final" }).then((b) => {
597
+ const newBlock = {
598
+ header: {
599
+ prev_hash: b.header.prev_hash,
600
+ timestamp_nanosec: b.header.timestamp_nanosec
601
+ }
602
+ };
603
+ lsSet("block", newBlock);
604
+ return newBlock;
605
+ });
606
+ }
607
+ if (Object.keys(toDoPromises).length > 0) {
608
+ const results = await Promise.all(Object.values(toDoPromises));
609
+ const keys = Object.keys(toDoPromises);
610
+ results.forEach((res, i) => {
611
+ if (keys[i] === "nonce") {
612
+ nonce = res;
613
+ } else if (keys[i] === "block") {
614
+ block = res;
615
+ }
616
+ });
617
+ }
618
+ const newNonce = (nonce ?? 0) + 1;
619
+ lsSet("nonce", newNonce);
620
+ const blockHash = block.header.prev_hash;
621
+ const jsonTransaction = {
622
+ signerId,
623
+ publicKey,
624
+ nonce: newNonce,
625
+ receiverId,
626
+ blockHash,
627
+ actions
628
+ };
629
+ console.log("Transaction:", jsonTransaction);
630
+ const transaction = serializeTransaction(jsonTransaction);
631
+ const txHash = toBase58(sha256(transaction));
632
+ const signature = signHash(txHash, privateKey);
633
+ const signedTransaction = serializeSignedTransaction(jsonTransaction, signature);
634
+ const signedTxBase64 = toBase64(signedTransaction);
635
+ updateTxHistory({
636
+ status: "Pending",
637
+ txId,
638
+ tx: jsonTransaction,
639
+ signature,
640
+ signedTxBase64,
641
+ txHash,
642
+ finalState: false
643
+ });
644
+ sendTxToRpc(signedTxBase64, waitUntil, txId);
645
+ return txId;
646
+ },
647
+ // Authentication Methods
648
+ async requestSignIn({ contractId }) {
649
+ const privateKey = privateKeyFromRandom();
650
+ updateState({
651
+ accessKeyContractId: contractId,
652
+ accountId: null,
653
+ privateKey
654
+ });
655
+ const publicKey = publicKeyFromPrivate(privateKey);
656
+ const result = await _adapter.signIn({
657
+ networkId: _config.networkId,
658
+ contractId,
659
+ publicKey
660
+ });
661
+ console.log("Sign in result:", result);
662
+ if (result.error) {
663
+ throw new Error(`Wallet error: ${result.error}`);
664
+ }
665
+ if (result.url) {
666
+ console.log("Redirecting to wallet:", result.url);
667
+ if (typeof window !== "undefined") {
668
+ setTimeout(() => {
669
+ window.location.href = result.url;
670
+ }, 100);
671
+ }
672
+ } else if (result.accountId) {
673
+ updateState({
674
+ accountId: result.accountId
675
+ });
676
+ }
677
+ },
678
+ signOut() {
679
+ updateState({
680
+ accountId: null,
681
+ privateKey: null,
682
+ contractId: null
683
+ });
684
+ },
685
+ // Event Handlers
686
+ onAccount(callback) {
687
+ _eventListeners.account.add(callback);
688
+ if (_unbroadcastedEvents.account.length > 0) {
689
+ const events = _unbroadcastedEvents.account;
690
+ _unbroadcastedEvents.account = [];
691
+ events.forEach(notifyAccountListeners);
692
+ }
693
+ },
694
+ onTx(callback) {
695
+ _eventListeners.tx.add(callback);
696
+ if (_unbroadcastedEvents.tx.length > 0) {
697
+ const events = _unbroadcastedEvents.tx;
698
+ _unbroadcastedEvents.tx = [];
699
+ events.forEach(notifyTxListeners);
700
+ }
701
+ },
702
+ // Action Helpers
703
+ actions: {
704
+ functionCall: ({
705
+ methodName,
706
+ gas,
707
+ deposit,
708
+ args,
709
+ argsBase64
710
+ }) => ({
711
+ type: "FunctionCall",
712
+ methodName,
713
+ args,
714
+ argsBase64,
715
+ gas,
716
+ deposit
717
+ }),
718
+ transfer: (yoctoAmount) => ({
719
+ type: "Transfer",
720
+ deposit: yoctoAmount
721
+ }),
722
+ stakeNEAR: ({ amount, publicKey }) => ({
723
+ type: "Stake",
724
+ stake: amount,
725
+ publicKey
726
+ }),
727
+ addFullAccessKey: ({ publicKey }) => ({
728
+ type: "AddKey",
729
+ publicKey,
730
+ accessKey: { permission: "FullAccess" }
731
+ }),
732
+ addLimitedAccessKey: ({
733
+ publicKey,
734
+ allowance,
735
+ accountId,
736
+ methodNames
737
+ }) => ({
738
+ type: "AddKey",
739
+ publicKey,
740
+ accessKey: {
741
+ permission: "FunctionCall",
742
+ allowance,
743
+ receiverId: accountId,
744
+ methodNames
745
+ }
746
+ }),
747
+ deleteKey: ({ publicKey }) => ({
748
+ type: "DeleteKey",
749
+ publicKey
750
+ }),
751
+ deleteAccount: ({ beneficiaryId }) => ({
752
+ type: "DeleteAccount",
753
+ beneficiaryId
754
+ }),
755
+ createAccount: () => ({
756
+ type: "CreateAccount"
757
+ }),
758
+ deployContract: ({ codeBase64 }) => ({
759
+ type: "DeployContract",
760
+ codeBase64
761
+ })
762
+ },
763
+ utils: {
764
+ toBase64,
765
+ fromBase64,
766
+ toBase58,
767
+ fromBase58
768
+ }
769
+ };
770
+ try {
771
+ if (typeof window !== "undefined") {
772
+ const url = new URL(window.location.href);
773
+ const accountId = url.searchParams.get("account_id");
774
+ const publicKey = url.searchParams.get("public_key");
775
+ const errorCode = url.searchParams.get("errorCode");
776
+ const errorMessage = url.searchParams.get("errorMessage");
777
+ const transactionHashes = url.searchParams.get("transactionHashes");
778
+ const txIds = url.searchParams.get("txIds");
779
+ if (errorCode || errorMessage) {
780
+ console.warn(new Error(`Wallet error: ${errorCode} ${errorMessage}`));
781
+ }
782
+ if (accountId && publicKey) {
783
+ if (publicKey === _state.publicKey) {
784
+ updateState({
785
+ accountId
786
+ });
787
+ } else {
788
+ console.error(
789
+ new Error("Public key mismatch from wallet redirect"),
790
+ publicKey,
791
+ _state.publicKey
792
+ );
793
+ }
794
+ }
795
+ if (transactionHashes || txIds) {
796
+ const txHashes = transactionHashes ? transactionHashes.split(",") : [];
797
+ const txIdsArray = txIds ? txIds.split(",") : [];
798
+ if (txIdsArray.length > txHashes.length) {
799
+ txIdsArray.forEach((txId, i) => {
800
+ updateTxHistory({
801
+ txId,
802
+ status: "RejectedByUser",
803
+ finalState: true
804
+ });
805
+ });
806
+ } else if (txIdsArray.length === txHashes.length) {
807
+ txIdsArray.forEach((txId, i) => {
808
+ updateTxHistory({
809
+ txId,
810
+ status: "PendingGotTxHash",
811
+ txHash: txHashes[i],
812
+ finalState: false
813
+ });
814
+ afterTxSent(txId);
815
+ });
816
+ } else {
817
+ console.error(
818
+ new Error("Transaction hash mismatch from wallet redirect"),
819
+ txIdsArray,
820
+ txHashes
821
+ );
822
+ }
823
+ }
824
+ url.searchParams.delete("account_id");
825
+ url.searchParams.delete("public_key");
826
+ url.searchParams.delete("errorCode");
827
+ url.searchParams.delete("errorMessage");
828
+ url.searchParams.delete("all_keys");
829
+ url.searchParams.delete("transactionHashes");
830
+ url.searchParams.delete("txIds");
831
+ window.history.replaceState({}, "", url.toString());
832
+ }
833
+ } catch (e) {
834
+ console.error("Error handling wallet redirect:", e);
835
+ }
836
+
837
+ export {
838
+ parseJsonFromBytes,
839
+ convertUnit,
840
+ api
841
+ };
842
+ //# sourceMappingURL=chunk-OR3WITSY.js.map