@anywalletkit/wallet-near 0.3.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.
package/dist/index.d.cts CHANGED
@@ -401,6 +401,13 @@ declare function actionKey(a: NearAction): NearActionKey;
401
401
  declare function isPlainObject(v: unknown): v is Record<string, unknown>;
402
402
  /** Function-call args as bytes: raw bytes pass through; plain objects / strings become UTF-8 JSON / UTF-8. Anything else throws. */
403
403
  declare function argsBytes(args: Uint8Array | Record<string, unknown> | string): Uint8Array;
404
+ /**
405
+ * The borsh tag of an access-key permission (0 FunctionCall, 1 FullAccess), read from a permission of
406
+ * exactly one known variant: `{ fullAccess: {} }` or `{ functionCall: { receiverId, methodNames, allowance? } }`.
407
+ * Anything else throws, so an empty, misspelled, unknown or doubled variant is never encoded as
408
+ * FullAccess. The encoder, `assertWellFormed` and the description all read this one tag (scan 2026-10-30 F9).
409
+ */
410
+ declare function accessKeyPermissionTag(permission: unknown): 0 | 1;
404
411
  declare function writeAction(w: BorshWriter, a: NearAction): void;
405
412
  declare function readAction(r: BorshReader): NearAction;
406
413
  /** Borsh bytes of an unsigned transaction. */
@@ -619,12 +626,19 @@ declare class WalletAccountReadOnlyNear implements IWalletAccountReadOnly {
619
626
  static hashOf(tx: NearBuiltTransaction): Uint8Array;
620
627
  static txHash(tx: NearBuiltTransaction): string;
621
628
  }
622
- declare function receiptOf(hash: string, o: RawFinalOutcome): NearReceipt;
629
+ /**
630
+ * The receipt of a `tx` / `send_tx` outcome: status 0 when the transaction or any receipt failed,
631
+ * 1 when it executed (`SuccessValue` / `SuccessReceiptId`), `undefined` while it is not executed
632
+ * yet (no execution status, `NotStarted` / `Started`, or `final_execution_status` NONE / INCLUDED /
633
+ * INCLUDED_FINAL).
634
+ */
635
+ declare function receiptOf(hash: string, o: RawFinalOutcome): NearReceipt | undefined;
623
636
  declare function parseSignature(signature: string): Uint8Array;
624
637
  /**
625
638
  * An object transaction has exactly the shape the encoder writes, before it is built or signed (also
626
639
  * `signBuilt`): every action one known key; a function call's `methodName` a string of the method
627
- * grammar, `args` bytes, a string or a plain object, `gas` / `deposit` bigints; every account id and
640
+ * grammar, `args` bytes, a string or a plain object, `gas` / `deposit` bigints; an AddKey permission
641
+ * exactly one known variant (scan 2026-10-30 F9); every account id and
628
642
  * method name well formed. What the policies read is then what gets encoded (scan 2026-10-27 F6, F28).
629
643
  */
630
644
  declare function assertWellFormed(tx: Pick<NearBuiltTransaction, 'receiverId' | 'actions'>): void;
@@ -652,6 +666,15 @@ declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWa
652
666
  readonly signerKind: Signer['kind'];
653
667
  private _disposed;
654
668
  private _readOnly;
669
+ /**
670
+ * Highest nonce this account has broadcast (accepted, or maybe sent). The access key is read at
671
+ * `final`, which lags the block that holds our last transaction, so a second send right after
672
+ * the first would sign the same nonce and be refused. A filled-in nonce is never below it + 1;
673
+ * NEAR only needs nonces to increase, so a gap left by a transaction that never landed is harmless.
674
+ */
675
+ private _nonceFloor;
676
+ /** Tail of this account's send queue: prepare → sign → broadcast runs one send at a time. */
677
+ private _sendTail;
655
678
  constructor(signer: Signer, publicKey: Uint8Array, path: string, config?: NearConfig, accountId?: string);
656
679
  /** Wrap a raw derived key (takes ownership; zeroized on dispose). */
657
680
  static fromPrivateKey(privateKey: Uint8Array, publicKey: Uint8Array, path: string, config?: NearConfig, accountId?: string): WalletAccountNear;
@@ -671,7 +694,11 @@ declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWa
671
694
  sign(message: string | Uint8Array): Promise<string>;
672
695
  /** NEP-413 off-chain message (what NEAR Intents and dApps ask wallets to sign). */
673
696
  signNep413(payload: Nep413Payload): Promise<Nep413Signed>;
674
- /** Sign a fully built transaction. No checks — see `signTransaction`. */
697
+ /**
698
+ * Sign a fully built transaction. It gets the same hard checks as `signTransaction` (this
699
+ * account's signer and key, no dangerous action unless `allowDangerousActions`, gas limit) but
700
+ * no node round-trip: no preflight and no fee check.
701
+ */
675
702
  signBuilt(tx: NearBuiltTransaction): Promise<NearSignedTransaction>;
676
703
  /** Build → hard checks → preflight → fee cap. Shared by sign / send / transfer. */
677
704
  private prepare;
@@ -719,4 +746,4 @@ declare class WalletManagerNear extends WalletManager<WalletAccountNear, NearCon
719
746
  getFeeRates(): Promise<FeeRates>;
720
747
  }
721
748
 
722
- export { ACTION_TAG, BorshReader, BorshWriter, BroadcastUnknownError, CAIP2, DANGEROUS_ACTIONS, type DescribeContext, FT_TRANSFER_GAS, IMPLICIT_ACCOUNT_MIN_DEPOSIT, MAX_GAS, MessageIsTransactionError, NEAR_BASE_PATH, NEP413_PREFIX, type NearAccessKey, type NearAccountView, type NearAction, type NearAddKeyAction, type NearBuiltTransaction, type NearConfig, type NearCreateAccountAction, type NearDelegateAction, type NearDeleteAccountAction, type NearDeleteKeyAction, type NearDeployContractAction, type NearDeployGlobalContractAction, type NearFeeEstimate, type NearFetch, type NearFunctionCallAction, type NearProvider, type NearPublicKey, type NearQuote, type NearReceipt, NearRpc, NearRpcError, type NearSignature, type NearSignedDelegateAction, type NearSignedTransaction, type NearSimulation, type NearStakeAction, type NearTransaction, type NearTransferAction, type NearTransferOptions, type NearTransferResult, type NearTxDescription, type NearTxKind, type NearTxWarning, type NearTxWarningCode, type NearUseGlobalContractAction, type Nep413Payload, type Nep413Signed, ONE_YOCTO, type RawAccessKeyView, type RawAccountView, type RawFinalOutcome, STORAGE_DEPOSIT_GAS, STORAGE_PRICE_PER_BYTE, SimulationError, TGAS, type UnsafeTransactionCode, UnsafeTransactionError, WalletAccountNear, WalletAccountReadOnlyNear, WalletManagerNear, YOCTO, actionKey, argsBytes, assertWellFormed, base58ToBytes, bytesToBase58, createClient, decodeAnyTransaction, decodeSignedTransaction, decodeTransaction, WalletManagerNear as default, describeTransaction, ed25519Key, encodeSignedTransaction, encodeTransaction, failureOf, fromBase64, implicitAccountId, isDangerous, isImplicitAccountId, isPlainObject, isValidAccountId, nep413Bytes, nep413Hash, outcomeFailed, parsePublicKey, parseSignature, publicKeyOfImplicit, publicKeyToString, readAction, readPublicKey, readSignature, receiptOf, toBase64, writeAction, writePublicKey, writeSignature };
749
+ export { ACTION_TAG, BorshReader, BorshWriter, BroadcastUnknownError, CAIP2, DANGEROUS_ACTIONS, type DescribeContext, FT_TRANSFER_GAS, IMPLICIT_ACCOUNT_MIN_DEPOSIT, MAX_GAS, MessageIsTransactionError, NEAR_BASE_PATH, NEP413_PREFIX, type NearAccessKey, type NearAccountView, type NearAction, type NearAddKeyAction, type NearBuiltTransaction, type NearConfig, type NearCreateAccountAction, type NearDelegateAction, type NearDeleteAccountAction, type NearDeleteKeyAction, type NearDeployContractAction, type NearDeployGlobalContractAction, type NearFeeEstimate, type NearFetch, type NearFunctionCallAction, type NearProvider, type NearPublicKey, type NearQuote, type NearReceipt, NearRpc, NearRpcError, type NearSignature, type NearSignedDelegateAction, type NearSignedTransaction, type NearSimulation, type NearStakeAction, type NearTransaction, type NearTransferAction, type NearTransferOptions, type NearTransferResult, type NearTxDescription, type NearTxKind, type NearTxWarning, type NearTxWarningCode, type NearUseGlobalContractAction, type Nep413Payload, type Nep413Signed, ONE_YOCTO, type RawAccessKeyView, type RawAccountView, type RawFinalOutcome, STORAGE_DEPOSIT_GAS, STORAGE_PRICE_PER_BYTE, SimulationError, TGAS, type UnsafeTransactionCode, UnsafeTransactionError, WalletAccountNear, WalletAccountReadOnlyNear, WalletManagerNear, YOCTO, accessKeyPermissionTag, actionKey, argsBytes, assertWellFormed, base58ToBytes, bytesToBase58, createClient, decodeAnyTransaction, decodeSignedTransaction, decodeTransaction, WalletManagerNear as default, describeTransaction, ed25519Key, encodeSignedTransaction, encodeTransaction, failureOf, fromBase64, implicitAccountId, isDangerous, isImplicitAccountId, isPlainObject, isValidAccountId, nep413Bytes, nep413Hash, outcomeFailed, parsePublicKey, parseSignature, publicKeyOfImplicit, publicKeyToString, readAction, readPublicKey, readSignature, receiptOf, toBase64, writeAction, writePublicKey, writeSignature };
package/dist/index.d.ts CHANGED
@@ -401,6 +401,13 @@ declare function actionKey(a: NearAction): NearActionKey;
401
401
  declare function isPlainObject(v: unknown): v is Record<string, unknown>;
402
402
  /** Function-call args as bytes: raw bytes pass through; plain objects / strings become UTF-8 JSON / UTF-8. Anything else throws. */
403
403
  declare function argsBytes(args: Uint8Array | Record<string, unknown> | string): Uint8Array;
404
+ /**
405
+ * The borsh tag of an access-key permission (0 FunctionCall, 1 FullAccess), read from a permission of
406
+ * exactly one known variant: `{ fullAccess: {} }` or `{ functionCall: { receiverId, methodNames, allowance? } }`.
407
+ * Anything else throws, so an empty, misspelled, unknown or doubled variant is never encoded as
408
+ * FullAccess. The encoder, `assertWellFormed` and the description all read this one tag (scan 2026-10-30 F9).
409
+ */
410
+ declare function accessKeyPermissionTag(permission: unknown): 0 | 1;
404
411
  declare function writeAction(w: BorshWriter, a: NearAction): void;
405
412
  declare function readAction(r: BorshReader): NearAction;
406
413
  /** Borsh bytes of an unsigned transaction. */
@@ -619,12 +626,19 @@ declare class WalletAccountReadOnlyNear implements IWalletAccountReadOnly {
619
626
  static hashOf(tx: NearBuiltTransaction): Uint8Array;
620
627
  static txHash(tx: NearBuiltTransaction): string;
621
628
  }
622
- declare function receiptOf(hash: string, o: RawFinalOutcome): NearReceipt;
629
+ /**
630
+ * The receipt of a `tx` / `send_tx` outcome: status 0 when the transaction or any receipt failed,
631
+ * 1 when it executed (`SuccessValue` / `SuccessReceiptId`), `undefined` while it is not executed
632
+ * yet (no execution status, `NotStarted` / `Started`, or `final_execution_status` NONE / INCLUDED /
633
+ * INCLUDED_FINAL).
634
+ */
635
+ declare function receiptOf(hash: string, o: RawFinalOutcome): NearReceipt | undefined;
623
636
  declare function parseSignature(signature: string): Uint8Array;
624
637
  /**
625
638
  * An object transaction has exactly the shape the encoder writes, before it is built or signed (also
626
639
  * `signBuilt`): every action one known key; a function call's `methodName` a string of the method
627
- * grammar, `args` bytes, a string or a plain object, `gas` / `deposit` bigints; every account id and
640
+ * grammar, `args` bytes, a string or a plain object, `gas` / `deposit` bigints; an AddKey permission
641
+ * exactly one known variant (scan 2026-10-30 F9); every account id and
628
642
  * method name well formed. What the policies read is then what gets encoded (scan 2026-10-27 F6, F28).
629
643
  */
630
644
  declare function assertWellFormed(tx: Pick<NearBuiltTransaction, 'receiverId' | 'actions'>): void;
@@ -652,6 +666,15 @@ declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWa
652
666
  readonly signerKind: Signer['kind'];
653
667
  private _disposed;
654
668
  private _readOnly;
669
+ /**
670
+ * Highest nonce this account has broadcast (accepted, or maybe sent). The access key is read at
671
+ * `final`, which lags the block that holds our last transaction, so a second send right after
672
+ * the first would sign the same nonce and be refused. A filled-in nonce is never below it + 1;
673
+ * NEAR only needs nonces to increase, so a gap left by a transaction that never landed is harmless.
674
+ */
675
+ private _nonceFloor;
676
+ /** Tail of this account's send queue: prepare → sign → broadcast runs one send at a time. */
677
+ private _sendTail;
655
678
  constructor(signer: Signer, publicKey: Uint8Array, path: string, config?: NearConfig, accountId?: string);
656
679
  /** Wrap a raw derived key (takes ownership; zeroized on dispose). */
657
680
  static fromPrivateKey(privateKey: Uint8Array, publicKey: Uint8Array, path: string, config?: NearConfig, accountId?: string): WalletAccountNear;
@@ -671,7 +694,11 @@ declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWa
671
694
  sign(message: string | Uint8Array): Promise<string>;
672
695
  /** NEP-413 off-chain message (what NEAR Intents and dApps ask wallets to sign). */
673
696
  signNep413(payload: Nep413Payload): Promise<Nep413Signed>;
674
- /** Sign a fully built transaction. No checks — see `signTransaction`. */
697
+ /**
698
+ * Sign a fully built transaction. It gets the same hard checks as `signTransaction` (this
699
+ * account's signer and key, no dangerous action unless `allowDangerousActions`, gas limit) but
700
+ * no node round-trip: no preflight and no fee check.
701
+ */
675
702
  signBuilt(tx: NearBuiltTransaction): Promise<NearSignedTransaction>;
676
703
  /** Build → hard checks → preflight → fee cap. Shared by sign / send / transfer. */
677
704
  private prepare;
@@ -719,4 +746,4 @@ declare class WalletManagerNear extends WalletManager<WalletAccountNear, NearCon
719
746
  getFeeRates(): Promise<FeeRates>;
720
747
  }
721
748
 
722
- export { ACTION_TAG, BorshReader, BorshWriter, BroadcastUnknownError, CAIP2, DANGEROUS_ACTIONS, type DescribeContext, FT_TRANSFER_GAS, IMPLICIT_ACCOUNT_MIN_DEPOSIT, MAX_GAS, MessageIsTransactionError, NEAR_BASE_PATH, NEP413_PREFIX, type NearAccessKey, type NearAccountView, type NearAction, type NearAddKeyAction, type NearBuiltTransaction, type NearConfig, type NearCreateAccountAction, type NearDelegateAction, type NearDeleteAccountAction, type NearDeleteKeyAction, type NearDeployContractAction, type NearDeployGlobalContractAction, type NearFeeEstimate, type NearFetch, type NearFunctionCallAction, type NearProvider, type NearPublicKey, type NearQuote, type NearReceipt, NearRpc, NearRpcError, type NearSignature, type NearSignedDelegateAction, type NearSignedTransaction, type NearSimulation, type NearStakeAction, type NearTransaction, type NearTransferAction, type NearTransferOptions, type NearTransferResult, type NearTxDescription, type NearTxKind, type NearTxWarning, type NearTxWarningCode, type NearUseGlobalContractAction, type Nep413Payload, type Nep413Signed, ONE_YOCTO, type RawAccessKeyView, type RawAccountView, type RawFinalOutcome, STORAGE_DEPOSIT_GAS, STORAGE_PRICE_PER_BYTE, SimulationError, TGAS, type UnsafeTransactionCode, UnsafeTransactionError, WalletAccountNear, WalletAccountReadOnlyNear, WalletManagerNear, YOCTO, actionKey, argsBytes, assertWellFormed, base58ToBytes, bytesToBase58, createClient, decodeAnyTransaction, decodeSignedTransaction, decodeTransaction, WalletManagerNear as default, describeTransaction, ed25519Key, encodeSignedTransaction, encodeTransaction, failureOf, fromBase64, implicitAccountId, isDangerous, isImplicitAccountId, isPlainObject, isValidAccountId, nep413Bytes, nep413Hash, outcomeFailed, parsePublicKey, parseSignature, publicKeyOfImplicit, publicKeyToString, readAction, readPublicKey, readSignature, receiptOf, toBase64, writeAction, writePublicKey, writeSignature };
749
+ export { ACTION_TAG, BorshReader, BorshWriter, BroadcastUnknownError, CAIP2, DANGEROUS_ACTIONS, type DescribeContext, FT_TRANSFER_GAS, IMPLICIT_ACCOUNT_MIN_DEPOSIT, MAX_GAS, MessageIsTransactionError, NEAR_BASE_PATH, NEP413_PREFIX, type NearAccessKey, type NearAccountView, type NearAction, type NearAddKeyAction, type NearBuiltTransaction, type NearConfig, type NearCreateAccountAction, type NearDelegateAction, type NearDeleteAccountAction, type NearDeleteKeyAction, type NearDeployContractAction, type NearDeployGlobalContractAction, type NearFeeEstimate, type NearFetch, type NearFunctionCallAction, type NearProvider, type NearPublicKey, type NearQuote, type NearReceipt, NearRpc, NearRpcError, type NearSignature, type NearSignedDelegateAction, type NearSignedTransaction, type NearSimulation, type NearStakeAction, type NearTransaction, type NearTransferAction, type NearTransferOptions, type NearTransferResult, type NearTxDescription, type NearTxKind, type NearTxWarning, type NearTxWarningCode, type NearUseGlobalContractAction, type Nep413Payload, type Nep413Signed, ONE_YOCTO, type RawAccessKeyView, type RawAccountView, type RawFinalOutcome, STORAGE_DEPOSIT_GAS, STORAGE_PRICE_PER_BYTE, SimulationError, TGAS, type UnsafeTransactionCode, UnsafeTransactionError, WalletAccountNear, WalletAccountReadOnlyNear, WalletManagerNear, YOCTO, accessKeyPermissionTag, actionKey, argsBytes, assertWellFormed, base58ToBytes, bytesToBase58, createClient, decodeAnyTransaction, decodeSignedTransaction, decodeTransaction, WalletManagerNear as default, describeTransaction, ed25519Key, encodeSignedTransaction, encodeTransaction, failureOf, fromBase64, implicitAccountId, isDangerous, isImplicitAccountId, isPlainObject, isValidAccountId, nep413Bytes, nep413Hash, outcomeFailed, parsePublicKey, parseSignature, publicKeyOfImplicit, publicKeyToString, readAction, readPublicKey, readSignature, receiptOf, toBase64, writeAction, writePublicKey, writeSignature };
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  encodeCursor,
23
23
  failureOf,
24
24
  fromBase64,
25
- isDefinitive,
25
+ isDefinitiveBroadcast,
26
26
  mapNearblocksGroup,
27
27
  mapNearblocksTxn,
28
28
  mapRpcTxStatus,
@@ -30,7 +30,7 @@ import {
30
30
  outcomeFailed,
31
31
  parseJsonPreservingBigInts,
32
32
  toBase64
33
- } from "./chunk-ZWMEZA5A.js";
33
+ } from "./chunk-5UHDSFWA.js";
34
34
 
35
35
  // src/address.ts
36
36
  import { base58 } from "@scure/base";
@@ -239,17 +239,34 @@ function argsBytes(args) {
239
239
  if (!isPlainObject(args)) throw new TypeError("function-call args must be bytes, a string or a plain object");
240
240
  return utf8.encode(JSON.stringify(args));
241
241
  }
242
+ var FUNCTION_CALL_PERMISSION_KEYS = /* @__PURE__ */ new Set(["allowance", "receiverId", "methodNames"]);
243
+ function accessKeyPermissionTag(permission) {
244
+ const keys = isPlainObject(permission) ? Object.keys(permission) : [];
245
+ if (keys.length !== 1) throw new TypeError(`an access-key permission must have exactly one variant, fullAccess or functionCall (has: ${keys.join(", ") || "none"})`);
246
+ const variant = permission[keys[0]];
247
+ if (keys[0] === "fullAccess") {
248
+ if (!isPlainObject(variant)) throw new TypeError("fullAccess must be a plain object");
249
+ return 1;
250
+ }
251
+ if (keys[0] === "functionCall") {
252
+ if (!isPlainObject(variant) || Object.keys(variant).some((k) => !FUNCTION_CALL_PERMISSION_KEYS.has(k))) throw new TypeError("functionCall must be a plain { receiverId, methodNames, allowance? } object");
253
+ if (typeof variant.receiverId !== "string") throw new TypeError("functionCall.receiverId must be a string");
254
+ if (!Array.isArray(variant.methodNames) || !variant.methodNames.every((m) => typeof m === "string")) throw new TypeError("functionCall.methodNames must be an array of strings");
255
+ if (variant.allowance !== void 0 && typeof variant.allowance !== "bigint") throw new TypeError("functionCall.allowance must be a bigint or absent");
256
+ return 0;
257
+ }
258
+ throw new TypeError(`unknown access-key permission ${JSON.stringify(keys[0])}`);
259
+ }
242
260
  function writeAccessKey(w, k) {
243
261
  w.u64(k.nonce);
244
- if ("functionCall" in k.permission) {
262
+ const tag = accessKeyPermissionTag(k.permission);
263
+ w.u8(tag);
264
+ if (tag === 0) {
245
265
  const p = k.permission.functionCall;
246
- w.u8(0);
247
266
  w.option(p.allowance, (a) => w.u128(a));
248
267
  w.string(p.receiverId);
249
268
  w.u32(p.methodNames.length);
250
269
  for (const m of p.methodNames) w.string(m);
251
- } else {
252
- w.u8(1);
253
270
  }
254
271
  }
255
272
  function readAccessKey(r) {
@@ -489,8 +506,15 @@ function describeTransaction(tx, ctx = {}) {
489
506
  if (DANGEROUS_ACTIONS.has(key)) {
490
507
  dangerous ??= KIND_OF_DANGEROUS[key];
491
508
  warnings.push({ code: "dangerous-action", message: `${key} changes the account, its keys or its code.` });
492
- if (key === "addKey" && "fullAccess" in a.addKey.accessKey.permission) {
493
- warnings.push({ code: "full-access-key", message: "Adds a FULL ACCESS key: whoever holds it owns the account." });
509
+ if (key === "addKey") {
510
+ let tag;
511
+ try {
512
+ tag = accessKeyPermissionTag(a.addKey?.accessKey?.permission);
513
+ } catch {
514
+ tag = void 0;
515
+ }
516
+ if (tag === 1) warnings.push({ code: "full-access-key", message: "Adds a FULL ACCESS key: whoever holds it owns the account." });
517
+ else if (tag === void 0) warnings.push({ code: "dangerous-action", message: "Malformed access-key permission: neither fullAccess nor functionCall. The wallet refuses to sign it." });
494
518
  }
495
519
  continue;
496
520
  }
@@ -838,8 +862,7 @@ var WalletAccountReadOnlyNear = class _WalletAccountReadOnlyNear {
838
862
  /** Status of one of this account's transactions (the `tx` RPC needs the sender). */
839
863
  async getTransactionReceipt(hash) {
840
864
  const o = await this.requireRpc("fetch transaction receipts").txStatus(hash, this.address);
841
- if (!o) return void 0;
842
- return receiptOf(hash, o);
865
+ return o ? receiptOf(hash, o) : void 0;
843
866
  }
844
867
  /** Verify an `ed25519:<base58>` (or bare base58 / hex) signature produced by `sign`. */
845
868
  async verify(message, signature) {
@@ -860,8 +883,10 @@ var WalletAccountReadOnlyNear = class _WalletAccountReadOnlyNear {
860
883
  };
861
884
  function receiptOf(hash, o) {
862
885
  const failure = outcomeFailed(o);
863
- const pending = o.final_execution_status !== void 0 && /NONE|INCLUDED$/.test(o.final_execution_status) && !failureOf(o.status) && o.status === void 0;
864
- return { hash, status: failure ? 0 : 1, ...failure ? { failure } : {}, raw: { ...o, ...pending ? { pending: true } : {} } };
886
+ if (failure) return { hash, status: 0, failure, raw: { ...o } };
887
+ if (o.final_execution_status !== void 0 && /^(?:NONE|INCLUDED|INCLUDED_FINAL)$/.test(o.final_execution_status)) return void 0;
888
+ const executed = typeof o.status === "object" && o.status !== null && ("SuccessValue" in o.status || "SuccessReceiptId" in o.status);
889
+ return executed ? { hash, status: 1, raw: { ...o } } : void 0;
865
890
  }
866
891
  function parseSignature(signature) {
867
892
  const s = signature.startsWith("ed25519:") ? signature.slice("ed25519:".length) : signature;
@@ -888,6 +913,15 @@ function assertShape(actions, depth = 0) {
888
913
  if (!(f.args instanceof Uint8Array) && typeof f.args !== "string" && !isPlainObject(f.args)) throw new UnsafeTransactionError("malformed-action", "Function-call args must be bytes, a string or a plain object.");
889
914
  if (f.gas !== void 0 && typeof f.gas !== "bigint" || f.deposit !== void 0 && typeof f.deposit !== "bigint") throw new UnsafeTransactionError("malformed-action", "Function-call gas and deposit must be bigints.");
890
915
  }
916
+ if ("addKey" in a) {
917
+ const k = a.addKey;
918
+ if (!isPlainObject(k) || !isPlainObject(k.accessKey)) throw new UnsafeTransactionError("malformed-action", "addKey must carry an accessKey object.");
919
+ try {
920
+ accessKeyPermissionTag(k.accessKey.permission);
921
+ } catch (e) {
922
+ throw new UnsafeTransactionError("malformed-action", `AddKey: ${e.message}.`);
923
+ }
924
+ }
891
925
  if ("signedDelegate" in a && depth === 0) assertShape(a.signedDelegate.delegateAction.actions, depth + 1);
892
926
  }
893
927
  }
@@ -960,6 +994,15 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
960
994
  signerKind;
961
995
  _disposed = false;
962
996
  _readOnly;
997
+ /**
998
+ * Highest nonce this account has broadcast (accepted, or maybe sent). The access key is read at
999
+ * `final`, which lags the block that holds our last transaction, so a second send right after
1000
+ * the first would sign the same nonce and be refused. A filled-in nonce is never below it + 1;
1001
+ * NEAR only needs nonces to increase, so a gap left by a transaction that never landed is harmless.
1002
+ */
1003
+ _nonceFloor;
1004
+ /** Tail of this account's send queue: prepare → sign → broadcast runs one send at a time. */
1005
+ _sendTail = Promise.resolve();
963
1006
  constructor(signer, publicKey, path, config = {}, accountId) {
964
1007
  super(accountId ?? implicitAccountId(publicKey), config, ed25519Key(publicKey));
965
1008
  this.#signer = requireCurve(signer, "ed25519");
@@ -1004,15 +1047,44 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
1004
1047
  const sig = await this.#signBytes(nep413Hash(payload), "near-nep413");
1005
1048
  return { signature: toBase64(sig), publicKey: publicKeyToString(this.publicKey), accountId: this.address };
1006
1049
  }
1007
- /** Sign a fully built transaction. No checks — see `signTransaction`. */
1050
+ /**
1051
+ * Sign a fully built transaction. It gets the same hard checks as `signTransaction` (this
1052
+ * account's signer and key, no dangerous action unless `allowDangerousActions`, gas limit) but
1053
+ * no node round-trip: no preflight and no fee check.
1054
+ */
1008
1055
  async signBuilt(tx) {
1056
+ const own = this.#ownCopy(tx);
1057
+ this.assertSafe(own);
1058
+ return this.#signChecked(own);
1059
+ }
1060
+ /**
1061
+ * A plain copy of `tx`, decoded from its borsh bytes: the object the checks read is the one that
1062
+ * gets hashed and signed, whatever the caller does with its own object (a getter, or an array
1063
+ * changed while a node call is awaited).
1064
+ */
1065
+ #ownCopy(tx) {
1066
+ let copy;
1067
+ try {
1068
+ copy = decodeTransaction(encodeTransaction(tx));
1069
+ } catch (e) {
1070
+ this.assertSafe(tx);
1071
+ throw new UnsafeTransactionError("non-canonical", `Not an encodable NEAR transaction: ${e.message}`);
1072
+ }
1073
+ return copy;
1074
+ }
1075
+ /** Sign a transaction that has already been through `assertSafe`. */
1076
+ async #signChecked(tx) {
1009
1077
  assertWellFormed(tx);
1010
1078
  const sig = await this.#signBytes(WalletAccountReadOnlyNear.hashOf(tx), "near-tx");
1011
1079
  return { transaction: tx, signature: { keyType: "ed25519", data: sig } };
1012
1080
  }
1013
1081
  /** Build → hard checks → preflight → fee cap. Shared by sign / send / transfer. */
1014
1082
  async prepare(tx, maxFee, op) {
1015
- const built = await this.buildTransaction(tx);
1083
+ let built = await this.buildTransaction(tx);
1084
+ if (typeof tx !== "string" && tx.nonce === void 0 && this._nonceFloor !== void 0 && built.nonce <= this._nonceFloor) {
1085
+ built = { ...built, nonce: this._nonceFloor + 1n };
1086
+ }
1087
+ built = this.#ownCopy(built);
1016
1088
  this.assertSafe(built);
1017
1089
  const estimate = await this.estimate(built);
1018
1090
  this.assertSafe(built, estimate.fee);
@@ -1028,18 +1100,24 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
1028
1100
  this.key();
1029
1101
  this.requireRpc("sign transactions");
1030
1102
  const { built } = await this.prepare(tx, feeLimit(this._config.transactionMaxFee, options), "transaction");
1031
- return toBase64(encodeSignedTransaction(await this.signBuilt(built)));
1103
+ return toBase64(encodeSignedTransaction(await this.#signChecked(built)));
1032
1104
  }
1033
1105
  async broadcast(signed) {
1034
1106
  const hash = WalletAccountReadOnlyNear.txHash(signed.transaction);
1035
1107
  const rpc = this.requireRpc("broadcast");
1108
+ const used = () => {
1109
+ const n = signed.transaction.nonce;
1110
+ if (this._nonceFloor === void 0 || n > this._nonceFloor) this._nonceFloor = n;
1111
+ };
1036
1112
  let outcome;
1037
1113
  try {
1038
1114
  outcome = await rpc.sendTx(toBase64(encodeSignedTransaction(signed)));
1039
1115
  } catch (e) {
1040
- if (isDefinitive(e)) throw e;
1116
+ if (isDefinitiveBroadcast(e)) throw e;
1117
+ used();
1041
1118
  throw new BroadcastUnknownError(hash, e);
1042
1119
  }
1120
+ used();
1043
1121
  const failure = outcomeFailed(outcome);
1044
1122
  if (failure) throw new Error(`Transaction ${hash} failed on chain: ${failure}`);
1045
1123
  return outcome.transaction?.hash ?? hash;
@@ -1048,20 +1126,35 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
1048
1126
  * Sign and broadcast. Accepts a transaction, or base64 borsh of an unsigned /
1049
1127
  * already-signed transaction (a signed one is checked, not re-signed).
1050
1128
  */
1051
- async sendTransaction(tx, options = {}) {
1129
+ sendTransaction(tx, options = {}) {
1130
+ return this.#serial(() => this.#sendTransactionNow(tx, options));
1131
+ }
1132
+ async #sendTransactionNow(tx, options) {
1052
1133
  this.key();
1053
1134
  this.requireRpc("send transactions");
1054
1135
  const presigned = typeof tx === "string" ? decodeSigned(tx) : void 0;
1055
1136
  const { built, estimate } = await this.prepare(tx, feeLimit(this._config.transactionMaxFee, options), "transaction");
1056
- const signed = presigned ?? await this.signBuilt(built);
1137
+ const signed = presigned ?? await this.#signChecked(built);
1057
1138
  return { hash: await this.broadcast(signed), fee: estimate.fee, estimate };
1058
1139
  }
1059
1140
  /** Native NEAR (no `token`) or NEP-141 `ft_transfer` (with `storage_deposit` when the recipient needs it). */
1060
- async transfer(o, writeOptions = {}) {
1141
+ transfer(o, writeOptions = {}) {
1142
+ return this.#serial(() => this.#transferNow(o, writeOptions));
1143
+ }
1144
+ async #transferNow(o, writeOptions) {
1061
1145
  this.key();
1062
1146
  this.requireRpc("transfer tokens");
1063
1147
  const { built, estimate } = await this.prepare(await this.transferActions(o), feeLimit(this._config.transferMaxFee, writeOptions), "transfer");
1064
- return { hash: await this.broadcast(await this.signBuilt(built)), fee: estimate.fee, estimate };
1148
+ return { hash: await this.broadcast(await this.#signChecked(built)), fee: estimate.fee, estimate };
1149
+ }
1150
+ /**
1151
+ * One send at a time per account: two sends started together would read the same access-key
1152
+ * nonce before either is broadcast. A failed send does not block the next.
1153
+ */
1154
+ #serial(run) {
1155
+ const next = this._sendTail.then(run);
1156
+ this._sendTail = next.then(() => void 0, () => void 0);
1157
+ return next;
1065
1158
  }
1066
1159
  /** The same account as a {@link WalletAccountReadOnlyNear}. */
1067
1160
  toReadOnlyAccount() {
@@ -1159,6 +1252,7 @@ export {
1159
1252
  WalletAccountReadOnlyNear,
1160
1253
  WalletManagerNear,
1161
1254
  YOCTO,
1255
+ accessKeyPermissionTag,
1162
1256
  actionKey,
1163
1257
  argsBytes,
1164
1258
  assertWellFormed,