@anywalletkit/wallet-near 0.1.8 → 0.2.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
@@ -1,5 +1,5 @@
1
1
  import { SignerError, IWalletAccountReadOnly, TransferResult, IWalletAccount, Signer, WriteOptions, WalletManager, FeeRates } from '@anywalletkit/core';
2
- export { HistoryFetch, HistoryUnavailableError, NearChainTx, NearHistoryCursor, NearHistoryOptions, NearHistoryPage, NearHistoryRaw, NearHistorySource, NearblocksFtRow, NearblocksReceiptRow, NearblocksTxn, RpcTxStatus, createNearHistory, decodeFunctionCallArgs, decodeCursor as decodeHistoryCursor, encodeCursor as encodeHistoryCursor, mapNearblocksGroup, mapNearblocksTxn, mapRpcTxStatus, nearExplorerTxUrl, parseJsonPreservingBigInts } from './history.cjs';
2
+ export { HistoryFetch, HistoryUnavailableError, NearChainTx, NearHistoryCursor, NearHistoryOptions, NearHistoryPage, NearHistoryRaw, NearHistorySource, NearblocksAction, NearblocksFtRow, NearblocksReceiptRow, NearblocksTxn, RpcAction, RpcTxStatus, createNearHistory, decodeFunctionCallArgs, decodeCursor as decodeHistoryCursor, encodeCursor as encodeHistoryCursor, mapNearblocksGroup, mapNearblocksTxn, mapRpcTxStatus, nearExplorerTxUrl, parseJsonPreservingBigInts } from './history.cjs';
3
3
 
4
4
  /** JSON-RPC transport: `method` + `params`, returns the `result` (throws on `error`). */
5
5
  type NearFetch = (method: string, params: unknown) => Promise<unknown>;
@@ -266,7 +266,7 @@ declare const STORAGE_DEPOSIT_GAS: bigint;
266
266
  declare const IMPLICIT_ACCOUNT_MIN_DEPOSIT: bigint;
267
267
 
268
268
  /** Why a transaction was refused before signing. */
269
- type UnsafeTransactionCode = 'signer-mismatch' | 'public-key-mismatch' | 'dangerous-action' | 'invalid-account' | 'no-actions' | 'gas-limit' | 'fee-limit' | 'missing-block-hash' | 'missing-nonce' | 'unknown-action' | 'insufficient-balance' | 'implicit-account-min-deposit' | 'no-access-key' | 'storage-deposit';
269
+ type UnsafeTransactionCode = 'signer-mismatch' | 'public-key-mismatch' | 'dangerous-action' | 'invalid-account' | 'no-actions' | 'gas-limit' | 'fee-limit' | 'missing-block-hash' | 'missing-nonce' | 'unknown-action' | 'insufficient-balance' | 'implicit-account-min-deposit' | 'no-access-key' | 'storage-deposit' | 'non-canonical' | 'invalid-method' | 'malformed-action';
270
270
  /** A transaction failed a hard check and was not signed. */
271
271
  declare class UnsafeTransactionError extends Error {
272
272
  readonly code: UnsafeTransactionCode;
@@ -395,8 +395,11 @@ declare const ACTION_TAG: {
395
395
  readonly useGlobalContract: 10;
396
396
  };
397
397
  type NearActionKey = keyof typeof ACTION_TAG;
398
+ /** The one key an action object has. Two keys (a deleteAccount next to a functionCall) is no action: whichever a reader picks, another reader may pick the other (scan 2026-10-27 F6). */
398
399
  declare function actionKey(a: NearAction): NearActionKey;
399
- /** Function-call args as bytes: raw bytes pass through; objects / strings become UTF-8 JSON / UTF-8. */
400
+ /** A plain `{…}` object: not an array, not a class instance. */
401
+ declare function isPlainObject(v: unknown): v is Record<string, unknown>;
402
+ /** Function-call args as bytes: raw bytes pass through; plain objects / strings become UTF-8 JSON / UTF-8. Anything else throws. */
400
403
  declare function argsBytes(args: Uint8Array | Record<string, unknown> | string): Uint8Array;
401
404
  declare function writeAction(w: BorshWriter, a: NearAction): void;
402
405
  declare function readAction(r: BorshReader): NearAction;
@@ -618,6 +621,13 @@ declare class WalletAccountReadOnlyNear implements IWalletAccountReadOnly {
618
621
  }
619
622
  declare function receiptOf(hash: string, o: RawFinalOutcome): NearReceipt;
620
623
  declare function parseSignature(signature: string): Uint8Array;
624
+ /**
625
+ * An object transaction has exactly the shape the encoder writes, before it is built or signed (also
626
+ * `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
628
+ * method name well formed. What the policies read is then what gets encoded (scan 2026-10-27 F6, F28).
629
+ */
630
+ declare function assertWellFormed(tx: Pick<NearBuiltTransaction, 'receiverId' | 'actions'>): void;
621
631
 
622
632
  interface NearTransferResult extends TransferResult {
623
633
  estimate?: NearFeeEstimate;
@@ -633,6 +643,7 @@ interface NearTransferResult extends TransferResult {
633
643
  * `accountId` for a named account whose full-access key this is.
634
644
  */
635
645
  declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWalletAccount {
646
+ #private;
636
647
  /** nonce / block hash come from the node, so building needs the network. */
637
648
  readonly needsNetwork = true;
638
649
  /** Derivation path, or `external` for an external signer. */
@@ -649,7 +660,6 @@ declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWa
649
660
  /** The same key bound to a named account (`alice.near`) that lists it as a full-access key. */
650
661
  withAccountId(accountId: string): WalletAccountNear;
651
662
  private key;
652
- private signBytes;
653
663
  /**
654
664
  * Raw ed25519 signature over the message bytes, as NEAR tooling prints it: "ed25519:<base58>".
655
665
  * A 32-byte message — string or bytes — is refused with {@link MessageIsTransactionError}: a NEAR
@@ -709,4 +719,4 @@ declare class WalletManagerNear extends WalletManager<WalletAccountNear, NearCon
709
719
  getFeeRates(): Promise<FeeRates>;
710
720
  }
711
721
 
712
- 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, STORAGE_DEPOSIT_GAS, STORAGE_PRICE_PER_BYTE, SimulationError, TGAS, type UnsafeTransactionCode, UnsafeTransactionError, WalletAccountNear, WalletAccountReadOnlyNear, WalletManagerNear, YOCTO, actionKey, argsBytes, base58ToBytes, bytesToBase58, createClient, decodeAnyTransaction, decodeSignedTransaction, decodeTransaction, WalletManagerNear as default, describeTransaction, ed25519Key, encodeSignedTransaction, encodeTransaction, failureOf, fromBase64, implicitAccountId, isDangerous, isImplicitAccountId, isValidAccountId, nep413Bytes, nep413Hash, outcomeFailed, parsePublicKey, parseSignature, publicKeyOfImplicit, publicKeyToString, readAction, readPublicKey, readSignature, receiptOf, toBase64, writeAction, writePublicKey, writeSignature };
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 };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SignerError, IWalletAccountReadOnly, TransferResult, IWalletAccount, Signer, WriteOptions, WalletManager, FeeRates } from '@anywalletkit/core';
2
- export { HistoryFetch, HistoryUnavailableError, NearChainTx, NearHistoryCursor, NearHistoryOptions, NearHistoryPage, NearHistoryRaw, NearHistorySource, NearblocksFtRow, NearblocksReceiptRow, NearblocksTxn, RpcTxStatus, createNearHistory, decodeFunctionCallArgs, decodeCursor as decodeHistoryCursor, encodeCursor as encodeHistoryCursor, mapNearblocksGroup, mapNearblocksTxn, mapRpcTxStatus, nearExplorerTxUrl, parseJsonPreservingBigInts } from './history.js';
2
+ export { HistoryFetch, HistoryUnavailableError, NearChainTx, NearHistoryCursor, NearHistoryOptions, NearHistoryPage, NearHistoryRaw, NearHistorySource, NearblocksAction, NearblocksFtRow, NearblocksReceiptRow, NearblocksTxn, RpcAction, RpcTxStatus, createNearHistory, decodeFunctionCallArgs, decodeCursor as decodeHistoryCursor, encodeCursor as encodeHistoryCursor, mapNearblocksGroup, mapNearblocksTxn, mapRpcTxStatus, nearExplorerTxUrl, parseJsonPreservingBigInts } from './history.js';
3
3
 
4
4
  /** JSON-RPC transport: `method` + `params`, returns the `result` (throws on `error`). */
5
5
  type NearFetch = (method: string, params: unknown) => Promise<unknown>;
@@ -266,7 +266,7 @@ declare const STORAGE_DEPOSIT_GAS: bigint;
266
266
  declare const IMPLICIT_ACCOUNT_MIN_DEPOSIT: bigint;
267
267
 
268
268
  /** Why a transaction was refused before signing. */
269
- type UnsafeTransactionCode = 'signer-mismatch' | 'public-key-mismatch' | 'dangerous-action' | 'invalid-account' | 'no-actions' | 'gas-limit' | 'fee-limit' | 'missing-block-hash' | 'missing-nonce' | 'unknown-action' | 'insufficient-balance' | 'implicit-account-min-deposit' | 'no-access-key' | 'storage-deposit';
269
+ type UnsafeTransactionCode = 'signer-mismatch' | 'public-key-mismatch' | 'dangerous-action' | 'invalid-account' | 'no-actions' | 'gas-limit' | 'fee-limit' | 'missing-block-hash' | 'missing-nonce' | 'unknown-action' | 'insufficient-balance' | 'implicit-account-min-deposit' | 'no-access-key' | 'storage-deposit' | 'non-canonical' | 'invalid-method' | 'malformed-action';
270
270
  /** A transaction failed a hard check and was not signed. */
271
271
  declare class UnsafeTransactionError extends Error {
272
272
  readonly code: UnsafeTransactionCode;
@@ -395,8 +395,11 @@ declare const ACTION_TAG: {
395
395
  readonly useGlobalContract: 10;
396
396
  };
397
397
  type NearActionKey = keyof typeof ACTION_TAG;
398
+ /** The one key an action object has. Two keys (a deleteAccount next to a functionCall) is no action: whichever a reader picks, another reader may pick the other (scan 2026-10-27 F6). */
398
399
  declare function actionKey(a: NearAction): NearActionKey;
399
- /** Function-call args as bytes: raw bytes pass through; objects / strings become UTF-8 JSON / UTF-8. */
400
+ /** A plain `{…}` object: not an array, not a class instance. */
401
+ declare function isPlainObject(v: unknown): v is Record<string, unknown>;
402
+ /** Function-call args as bytes: raw bytes pass through; plain objects / strings become UTF-8 JSON / UTF-8. Anything else throws. */
400
403
  declare function argsBytes(args: Uint8Array | Record<string, unknown> | string): Uint8Array;
401
404
  declare function writeAction(w: BorshWriter, a: NearAction): void;
402
405
  declare function readAction(r: BorshReader): NearAction;
@@ -618,6 +621,13 @@ declare class WalletAccountReadOnlyNear implements IWalletAccountReadOnly {
618
621
  }
619
622
  declare function receiptOf(hash: string, o: RawFinalOutcome): NearReceipt;
620
623
  declare function parseSignature(signature: string): Uint8Array;
624
+ /**
625
+ * An object transaction has exactly the shape the encoder writes, before it is built or signed (also
626
+ * `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
628
+ * method name well formed. What the policies read is then what gets encoded (scan 2026-10-27 F6, F28).
629
+ */
630
+ declare function assertWellFormed(tx: Pick<NearBuiltTransaction, 'receiverId' | 'actions'>): void;
621
631
 
622
632
  interface NearTransferResult extends TransferResult {
623
633
  estimate?: NearFeeEstimate;
@@ -633,6 +643,7 @@ interface NearTransferResult extends TransferResult {
633
643
  * `accountId` for a named account whose full-access key this is.
634
644
  */
635
645
  declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWalletAccount {
646
+ #private;
636
647
  /** nonce / block hash come from the node, so building needs the network. */
637
648
  readonly needsNetwork = true;
638
649
  /** Derivation path, or `external` for an external signer. */
@@ -649,7 +660,6 @@ declare class WalletAccountNear extends WalletAccountReadOnlyNear implements IWa
649
660
  /** The same key bound to a named account (`alice.near`) that lists it as a full-access key. */
650
661
  withAccountId(accountId: string): WalletAccountNear;
651
662
  private key;
652
- private signBytes;
653
663
  /**
654
664
  * Raw ed25519 signature over the message bytes, as NEAR tooling prints it: "ed25519:<base58>".
655
665
  * A 32-byte message — string or bytes — is refused with {@link MessageIsTransactionError}: a NEAR
@@ -709,4 +719,4 @@ declare class WalletManagerNear extends WalletManager<WalletAccountNear, NearCon
709
719
  getFeeRates(): Promise<FeeRates>;
710
720
  }
711
721
 
712
- 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, STORAGE_DEPOSIT_GAS, STORAGE_PRICE_PER_BYTE, SimulationError, TGAS, type UnsafeTransactionCode, UnsafeTransactionError, WalletAccountNear, WalletAccountReadOnlyNear, WalletManagerNear, YOCTO, actionKey, argsBytes, base58ToBytes, bytesToBase58, createClient, decodeAnyTransaction, decodeSignedTransaction, decodeTransaction, WalletManagerNear as default, describeTransaction, ed25519Key, encodeSignedTransaction, encodeTransaction, failureOf, fromBase64, implicitAccountId, isDangerous, isImplicitAccountId, isValidAccountId, nep413Bytes, nep413Hash, outcomeFailed, parsePublicKey, parseSignature, publicKeyOfImplicit, publicKeyToString, readAction, readPublicKey, readSignature, receiptOf, toBase64, writeAction, writePublicKey, writeSignature };
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 };
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
  outcomeFailed,
31
31
  parseJsonPreservingBigInts,
32
32
  toBase64
33
- } from "./chunk-MX4CTCHL.js";
33
+ } from "./chunk-ZWMEZA5A.js";
34
34
 
35
35
  // src/address.ts
36
36
  import { base58 } from "@scure/base";
@@ -74,7 +74,7 @@ var bytesToBase58 = (b) => base58.encode(b);
74
74
 
75
75
  // src/borsh.ts
76
76
  var utf8 = new TextEncoder();
77
- var utf8d = new TextDecoder();
77
+ var utf8d = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
78
78
  var BorshWriter = class {
79
79
  _buf = new Uint8Array(256);
80
80
  _len = 0;
@@ -176,7 +176,10 @@ var BorshReader = class {
176
176
  return utf8d.decode(this.vecU8());
177
177
  }
178
178
  option(read) {
179
- return this.u8() === 0 ? void 0 : read();
179
+ const tag = this.u8();
180
+ if (tag === 0) return void 0;
181
+ if (tag !== 1) throw new RangeError(`borsh: option tag ${tag}`);
182
+ return read();
180
183
  }
181
184
  done() {
182
185
  if (this.remaining !== 0) throw new RangeError(`borsh: ${this.remaining} trailing bytes`);
@@ -219,13 +222,21 @@ var ACTION_TAG = {
219
222
  useGlobalContract: 10
220
223
  };
221
224
  function actionKey(a) {
222
- const k = Object.keys(a)[0];
223
- if (!k || !(k in ACTION_TAG)) throw new RangeError(`unknown action ${k}`);
225
+ const keys = typeof a === "object" && a !== null ? Object.keys(a) : [];
226
+ if (keys.length !== 1) throw new RangeError(`an action must have exactly one key (has: ${keys.join(", ") || "none"})`);
227
+ const k = keys[0];
228
+ if (!Object.prototype.hasOwnProperty.call(ACTION_TAG, k)) throw new RangeError(`unknown action ${k}`);
224
229
  return k;
225
230
  }
231
+ function isPlainObject(v) {
232
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return false;
233
+ const proto = Object.getPrototypeOf(v);
234
+ return proto === Object.prototype || proto === null;
235
+ }
226
236
  function argsBytes(args) {
227
237
  if (args instanceof Uint8Array) return args;
228
238
  if (typeof args === "string") return utf8.encode(args);
239
+ if (!isPlainObject(args)) throw new TypeError("function-call args must be bytes, a string or a plain object");
229
240
  return utf8.encode(JSON.stringify(args));
230
241
  }
231
242
  function writeAccessKey(w, k) {
@@ -283,6 +294,8 @@ function writeAction(w, a) {
283
294
  return;
284
295
  case "functionCall": {
285
296
  const f = a.functionCall;
297
+ if (typeof f.methodName !== "string") throw new TypeError("functionCall.methodName must be a string");
298
+ if (f.gas !== void 0 && typeof f.gas !== "bigint" || f.deposit !== void 0 && typeof f.deposit !== "bigint") throw new TypeError("functionCall gas and deposit must be bigints");
286
299
  w.string(f.methodName).vecU8(argsBytes(f.args)).u64(f.gas ?? 30n * 10n ** 12n).u128(f.deposit ?? 0n);
287
300
  return;
288
301
  }
@@ -329,6 +342,11 @@ function writeAction(w, a) {
329
342
  }
330
343
  }
331
344
  }
345
+ function mode(r) {
346
+ const m = r.u8();
347
+ if (m !== 0 && m !== 1) throw new RangeError(`borsh: unknown global-contract mode ${m}`);
348
+ return m;
349
+ }
332
350
  function readAction(r) {
333
351
  const tag = r.u8();
334
352
  switch (tag) {
@@ -363,11 +381,11 @@ function readAction(r) {
363
381
  }
364
382
  case 9: {
365
383
  const code = r.vecU8();
366
- const m = r.u8();
384
+ const m = mode(r);
367
385
  return { deployGlobalContract: { code, deployMode: m === 0 ? "codeHash" : "accountId" } };
368
386
  }
369
387
  case 10: {
370
- const m = r.u8();
388
+ const m = mode(r);
371
389
  return { useGlobalContract: m === 0 ? { codeHash: r.bytes(32) } : { accountId: r.string() } };
372
390
  }
373
391
  default:
@@ -682,7 +700,8 @@ var WalletAccountReadOnlyNear = class _WalletAccountReadOnlyNear {
682
700
  }
683
701
  /** Fill `signerId` / `publicKey` / `nonce` / `blockHash` (the last two from the node when missing). */
684
702
  async buildTransaction(tx) {
685
- if (typeof tx === "string") return decodeAnyTransaction(fromBase64(tx)).transaction;
703
+ if (typeof tx === "string") return canonicalTransaction(tx);
704
+ assertWellFormed(tx);
686
705
  const signerId = tx.signerId ?? this.address;
687
706
  const publicKey = tx.publicKey ?? this.publicKey;
688
707
  let nonce = tx.nonce;
@@ -796,6 +815,7 @@ var WalletAccountReadOnlyNear = class _WalletAccountReadOnlyNear {
796
815
  if (tx.publicKey.keyType !== this.publicKey.keyType || !equalBytes(tx.publicKey.data, this.publicKey.data)) throw new UnsafeTransactionError("public-key-mismatch", "The transaction public key is not this account's key.");
797
816
  if (!tx.actions.length) throw new UnsafeTransactionError("no-actions", "The transaction has no actions.");
798
817
  if (!isValidAccountId(tx.receiverId)) throw new UnsafeTransactionError("invalid-account", `"${tx.receiverId}" is not a valid NEAR account id.`);
818
+ assertWellFormed(tx);
799
819
  if (tx.blockHash.length !== 32) throw new UnsafeTransactionError("missing-block-hash", "The transaction has no 32-byte block hash.");
800
820
  if (tx.nonce <= 0n) throw new UnsafeTransactionError("missing-nonce", "The transaction nonce must be positive.");
801
821
  if (!this._config.allowDangerousActions) {
@@ -851,6 +871,64 @@ function parseSignature(signature) {
851
871
  }
852
872
  return base58ToBytes(s, 64);
853
873
  }
874
+ var METHOD_NAME = /^[A-Za-z0-9_]{1,256}$/;
875
+ function assertWellFormed(tx) {
876
+ if (!Array.isArray(tx.actions)) throw new UnsafeTransactionError("malformed-action", "actions must be an array.");
877
+ assertShape(tx.actions);
878
+ assertNames(tx.actions);
879
+ }
880
+ function assertShape(actions, depth = 0) {
881
+ for (const a of actions) {
882
+ const keys = typeof a === "object" && a !== null ? Object.keys(a) : [];
883
+ if (keys.length !== 1 || !Object.prototype.hasOwnProperty.call(ACTION_TAG, keys[0])) {
884
+ throw new UnsafeTransactionError("malformed-action", `An action must have exactly one known key (has: ${keys.join(", ") || "none"}).`);
885
+ }
886
+ if ("functionCall" in a) {
887
+ const f = a.functionCall;
888
+ 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
+ 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
+ }
891
+ if ("signedDelegate" in a && depth === 0) assertShape(a.signedDelegate.delegateAction.actions, depth + 1);
892
+ }
893
+ }
894
+ function assertNames(actions, depth = 0) {
895
+ const account = (id) => {
896
+ if (typeof id !== "string" || !isValidAccountId(id)) throw new UnsafeTransactionError("invalid-account", `${JSON.stringify(id)} is not a valid NEAR account id.`);
897
+ };
898
+ const method = (name) => {
899
+ if (typeof name !== "string" || !METHOD_NAME.test(name)) throw new UnsafeTransactionError("invalid-method", `${JSON.stringify(name)} is not a method name this wallet signs (ASCII letters, digits, '_').`);
900
+ };
901
+ for (const a of actions) {
902
+ if ("functionCall" in a) method(a.functionCall.methodName);
903
+ else if ("deleteAccount" in a) account(a.deleteAccount.beneficiaryId);
904
+ else if ("addKey" in a && "functionCall" in a.addKey.accessKey.permission) {
905
+ const p = a.addKey.accessKey.permission.functionCall;
906
+ account(p.receiverId);
907
+ for (const m of p.methodNames) method(m);
908
+ } else if ("useGlobalContract" in a && "accountId" in a.useGlobalContract) account(a.useGlobalContract.accountId);
909
+ else if ("signedDelegate" in a) {
910
+ const d = a.signedDelegate.delegateAction;
911
+ account(d.senderId);
912
+ account(d.receiverId);
913
+ if (depth > 0) throw new UnsafeTransactionError("unknown-action", "A delegated action inside a delegated action is not signed.");
914
+ assertNames(d.actions, depth + 1);
915
+ }
916
+ }
917
+ }
918
+ function canonicalTransaction(b64) {
919
+ const bytes = fromBase64(b64);
920
+ let decoded;
921
+ try {
922
+ decoded = decodeAnyTransaction(bytes);
923
+ } catch (e) {
924
+ throw new UnsafeTransactionError("non-canonical", `Not a borsh NEAR transaction: ${e.message}`);
925
+ }
926
+ const again = decoded.signature ? encodeSignedTransaction({ transaction: decoded.transaction, signature: decoded.signature }) : encodeTransaction(decoded.transaction);
927
+ if (!equalBytes(again, bytes)) throw new UnsafeTransactionError("non-canonical", "This borsh transaction does not re-encode to the same bytes, so what was reviewed may not be what gets signed.");
928
+ if (!isValidAccountId(decoded.transaction.signerId) || !isValidAccountId(decoded.transaction.receiverId)) throw new UnsafeTransactionError("invalid-account", "The transaction names an invalid NEAR account id.");
929
+ assertWellFormed(decoded.transaction);
930
+ return decoded.transaction;
931
+ }
854
932
  function equalBytes(a, b) {
855
933
  if (a.length !== b.length) return false;
856
934
  let diff = 0;
@@ -897,7 +975,7 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
897
975
  key() {
898
976
  if (this._disposed) throw new SignerError("This account has been disposed.");
899
977
  }
900
- async signBytes(bytes, context) {
978
+ async #signBytes(bytes, context) {
901
979
  this.key();
902
980
  return this.signer.sign(bytes, { scheme: "ed25519", context });
903
981
  }
@@ -912,16 +990,17 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
912
990
  async sign(message) {
913
991
  const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
914
992
  if (bytes.length === 32 || carriesKey(bytes, this.publicKey.data)) throw new MessageIsTransactionError();
915
- return `ed25519:${bytesToBase58(await this.signBytes(bytes, "near-message"))}`;
993
+ return `ed25519:${bytesToBase58(await this.#signBytes(bytes, "near-message"))}`;
916
994
  }
917
995
  /** NEP-413 off-chain message (what NEAR Intents and dApps ask wallets to sign). */
918
996
  async signNep413(payload) {
919
- const sig = await this.signBytes(nep413Hash(payload), "near-nep413");
997
+ const sig = await this.#signBytes(nep413Hash(payload), "near-nep413");
920
998
  return { signature: toBase64(sig), publicKey: publicKeyToString(this.publicKey), accountId: this.address };
921
999
  }
922
1000
  /** Sign a fully built transaction. No checks — see `signTransaction`. */
923
1001
  async signBuilt(tx) {
924
- const sig = await this.signBytes(WalletAccountReadOnlyNear.hashOf(tx), "near-tx");
1002
+ assertWellFormed(tx);
1003
+ const sig = await this.#signBytes(WalletAccountReadOnlyNear.hashOf(tx), "near-tx");
925
1004
  return { transaction: tx, signature: { keyType: "ed25519", data: sig } };
926
1005
  }
927
1006
  /** Build → hard checks → preflight → fee cap. Shared by sign / send / transfer. */
@@ -1075,6 +1154,7 @@ export {
1075
1154
  YOCTO,
1076
1155
  actionKey,
1077
1156
  argsBytes,
1157
+ assertWellFormed,
1078
1158
  base58ToBytes,
1079
1159
  bytesToBase58,
1080
1160
  createClient,
@@ -1095,6 +1175,7 @@ export {
1095
1175
  implicitAccountId,
1096
1176
  isDangerous,
1097
1177
  isImplicitAccountId,
1178
+ isPlainObject,
1098
1179
  isValidAccountId,
1099
1180
  mapNearblocksGroup,
1100
1181
  mapNearblocksTxn,