@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/{chunk-MX4CTCHL.js → chunk-ZWMEZA5A.js} +1 -1
- package/dist/chunk-ZWMEZA5A.js.map +1 -0
- package/dist/history.cjs.map +1 -1
- package/dist/history.d.cts +1 -1
- package/dist/history.d.ts +1 -1
- package/dist/history.js +1 -1
- package/dist/index.cjs +92 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -5
- package/dist/index.d.ts +15 -5
- package/dist/index.js +93 -12
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/chunk-MX4CTCHL.js.map +0 -1
package/dist/history.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -47,6 +47,7 @@ __export(src_exports, {
|
|
|
47
47
|
YOCTO: () => YOCTO,
|
|
48
48
|
actionKey: () => actionKey,
|
|
49
49
|
argsBytes: () => argsBytes,
|
|
50
|
+
assertWellFormed: () => assertWellFormed,
|
|
50
51
|
base58ToBytes: () => base58ToBytes,
|
|
51
52
|
bytesToBase58: () => bytesToBase58,
|
|
52
53
|
createClient: () => createClient,
|
|
@@ -67,6 +68,7 @@ __export(src_exports, {
|
|
|
67
68
|
implicitAccountId: () => implicitAccountId,
|
|
68
69
|
isDangerous: () => isDangerous,
|
|
69
70
|
isImplicitAccountId: () => isImplicitAccountId,
|
|
71
|
+
isPlainObject: () => isPlainObject,
|
|
70
72
|
isValidAccountId: () => isValidAccountId,
|
|
71
73
|
mapNearblocksGroup: () => mapNearblocksGroup,
|
|
72
74
|
mapNearblocksTxn: () => mapNearblocksTxn,
|
|
@@ -194,7 +196,7 @@ var bytesToBase58 = (b) => import_base.base58.encode(b);
|
|
|
194
196
|
|
|
195
197
|
// src/borsh.ts
|
|
196
198
|
var utf8 = new TextEncoder();
|
|
197
|
-
var utf8d = new TextDecoder();
|
|
199
|
+
var utf8d = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
198
200
|
var BorshWriter = class {
|
|
199
201
|
_buf = new Uint8Array(256);
|
|
200
202
|
_len = 0;
|
|
@@ -296,7 +298,10 @@ var BorshReader = class {
|
|
|
296
298
|
return utf8d.decode(this.vecU8());
|
|
297
299
|
}
|
|
298
300
|
option(read) {
|
|
299
|
-
|
|
301
|
+
const tag = this.u8();
|
|
302
|
+
if (tag === 0) return void 0;
|
|
303
|
+
if (tag !== 1) throw new RangeError(`borsh: option tag ${tag}`);
|
|
304
|
+
return read();
|
|
300
305
|
}
|
|
301
306
|
done() {
|
|
302
307
|
if (this.remaining !== 0) throw new RangeError(`borsh: ${this.remaining} trailing bytes`);
|
|
@@ -339,13 +344,21 @@ var ACTION_TAG = {
|
|
|
339
344
|
useGlobalContract: 10
|
|
340
345
|
};
|
|
341
346
|
function actionKey(a) {
|
|
342
|
-
const
|
|
343
|
-
if (
|
|
347
|
+
const keys = typeof a === "object" && a !== null ? Object.keys(a) : [];
|
|
348
|
+
if (keys.length !== 1) throw new RangeError(`an action must have exactly one key (has: ${keys.join(", ") || "none"})`);
|
|
349
|
+
const k = keys[0];
|
|
350
|
+
if (!Object.prototype.hasOwnProperty.call(ACTION_TAG, k)) throw new RangeError(`unknown action ${k}`);
|
|
344
351
|
return k;
|
|
345
352
|
}
|
|
353
|
+
function isPlainObject(v) {
|
|
354
|
+
if (typeof v !== "object" || v === null || Array.isArray(v)) return false;
|
|
355
|
+
const proto = Object.getPrototypeOf(v);
|
|
356
|
+
return proto === Object.prototype || proto === null;
|
|
357
|
+
}
|
|
346
358
|
function argsBytes(args) {
|
|
347
359
|
if (args instanceof Uint8Array) return args;
|
|
348
360
|
if (typeof args === "string") return utf8.encode(args);
|
|
361
|
+
if (!isPlainObject(args)) throw new TypeError("function-call args must be bytes, a string or a plain object");
|
|
349
362
|
return utf8.encode(JSON.stringify(args));
|
|
350
363
|
}
|
|
351
364
|
function writeAccessKey(w, k) {
|
|
@@ -403,6 +416,8 @@ function writeAction(w, a) {
|
|
|
403
416
|
return;
|
|
404
417
|
case "functionCall": {
|
|
405
418
|
const f = a.functionCall;
|
|
419
|
+
if (typeof f.methodName !== "string") throw new TypeError("functionCall.methodName must be a string");
|
|
420
|
+
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");
|
|
406
421
|
w.string(f.methodName).vecU8(argsBytes(f.args)).u64(f.gas ?? 30n * 10n ** 12n).u128(f.deposit ?? 0n);
|
|
407
422
|
return;
|
|
408
423
|
}
|
|
@@ -449,6 +464,11 @@ function writeAction(w, a) {
|
|
|
449
464
|
}
|
|
450
465
|
}
|
|
451
466
|
}
|
|
467
|
+
function mode(r) {
|
|
468
|
+
const m = r.u8();
|
|
469
|
+
if (m !== 0 && m !== 1) throw new RangeError(`borsh: unknown global-contract mode ${m}`);
|
|
470
|
+
return m;
|
|
471
|
+
}
|
|
452
472
|
function readAction(r) {
|
|
453
473
|
const tag = r.u8();
|
|
454
474
|
switch (tag) {
|
|
@@ -483,11 +503,11 @@ function readAction(r) {
|
|
|
483
503
|
}
|
|
484
504
|
case 9: {
|
|
485
505
|
const code = r.vecU8();
|
|
486
|
-
const m = r
|
|
506
|
+
const m = mode(r);
|
|
487
507
|
return { deployGlobalContract: { code, deployMode: m === 0 ? "codeHash" : "accountId" } };
|
|
488
508
|
}
|
|
489
509
|
case 10: {
|
|
490
|
-
const m = r
|
|
510
|
+
const m = mode(r);
|
|
491
511
|
return { useGlobalContract: m === 0 ? { codeHash: r.bytes(32) } : { accountId: r.string() } };
|
|
492
512
|
}
|
|
493
513
|
default:
|
|
@@ -958,7 +978,8 @@ var WalletAccountReadOnlyNear = class _WalletAccountReadOnlyNear {
|
|
|
958
978
|
}
|
|
959
979
|
/** Fill `signerId` / `publicKey` / `nonce` / `blockHash` (the last two from the node when missing). */
|
|
960
980
|
async buildTransaction(tx) {
|
|
961
|
-
if (typeof tx === "string") return
|
|
981
|
+
if (typeof tx === "string") return canonicalTransaction(tx);
|
|
982
|
+
assertWellFormed(tx);
|
|
962
983
|
const signerId = tx.signerId ?? this.address;
|
|
963
984
|
const publicKey = tx.publicKey ?? this.publicKey;
|
|
964
985
|
let nonce = tx.nonce;
|
|
@@ -1072,6 +1093,7 @@ var WalletAccountReadOnlyNear = class _WalletAccountReadOnlyNear {
|
|
|
1072
1093
|
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.");
|
|
1073
1094
|
if (!tx.actions.length) throw new UnsafeTransactionError("no-actions", "The transaction has no actions.");
|
|
1074
1095
|
if (!isValidAccountId(tx.receiverId)) throw new UnsafeTransactionError("invalid-account", `"${tx.receiverId}" is not a valid NEAR account id.`);
|
|
1096
|
+
assertWellFormed(tx);
|
|
1075
1097
|
if (tx.blockHash.length !== 32) throw new UnsafeTransactionError("missing-block-hash", "The transaction has no 32-byte block hash.");
|
|
1076
1098
|
if (tx.nonce <= 0n) throw new UnsafeTransactionError("missing-nonce", "The transaction nonce must be positive.");
|
|
1077
1099
|
if (!this._config.allowDangerousActions) {
|
|
@@ -1127,6 +1149,64 @@ function parseSignature(signature) {
|
|
|
1127
1149
|
}
|
|
1128
1150
|
return base58ToBytes(s, 64);
|
|
1129
1151
|
}
|
|
1152
|
+
var METHOD_NAME = /^[A-Za-z0-9_]{1,256}$/;
|
|
1153
|
+
function assertWellFormed(tx) {
|
|
1154
|
+
if (!Array.isArray(tx.actions)) throw new UnsafeTransactionError("malformed-action", "actions must be an array.");
|
|
1155
|
+
assertShape(tx.actions);
|
|
1156
|
+
assertNames(tx.actions);
|
|
1157
|
+
}
|
|
1158
|
+
function assertShape(actions, depth = 0) {
|
|
1159
|
+
for (const a of actions) {
|
|
1160
|
+
const keys = typeof a === "object" && a !== null ? Object.keys(a) : [];
|
|
1161
|
+
if (keys.length !== 1 || !Object.prototype.hasOwnProperty.call(ACTION_TAG, keys[0])) {
|
|
1162
|
+
throw new UnsafeTransactionError("malformed-action", `An action must have exactly one known key (has: ${keys.join(", ") || "none"}).`);
|
|
1163
|
+
}
|
|
1164
|
+
if ("functionCall" in a) {
|
|
1165
|
+
const f = a.functionCall;
|
|
1166
|
+
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.");
|
|
1167
|
+
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.");
|
|
1168
|
+
}
|
|
1169
|
+
if ("signedDelegate" in a && depth === 0) assertShape(a.signedDelegate.delegateAction.actions, depth + 1);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
function assertNames(actions, depth = 0) {
|
|
1173
|
+
const account = (id) => {
|
|
1174
|
+
if (typeof id !== "string" || !isValidAccountId(id)) throw new UnsafeTransactionError("invalid-account", `${JSON.stringify(id)} is not a valid NEAR account id.`);
|
|
1175
|
+
};
|
|
1176
|
+
const method = (name) => {
|
|
1177
|
+
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, '_').`);
|
|
1178
|
+
};
|
|
1179
|
+
for (const a of actions) {
|
|
1180
|
+
if ("functionCall" in a) method(a.functionCall.methodName);
|
|
1181
|
+
else if ("deleteAccount" in a) account(a.deleteAccount.beneficiaryId);
|
|
1182
|
+
else if ("addKey" in a && "functionCall" in a.addKey.accessKey.permission) {
|
|
1183
|
+
const p = a.addKey.accessKey.permission.functionCall;
|
|
1184
|
+
account(p.receiverId);
|
|
1185
|
+
for (const m of p.methodNames) method(m);
|
|
1186
|
+
} else if ("useGlobalContract" in a && "accountId" in a.useGlobalContract) account(a.useGlobalContract.accountId);
|
|
1187
|
+
else if ("signedDelegate" in a) {
|
|
1188
|
+
const d = a.signedDelegate.delegateAction;
|
|
1189
|
+
account(d.senderId);
|
|
1190
|
+
account(d.receiverId);
|
|
1191
|
+
if (depth > 0) throw new UnsafeTransactionError("unknown-action", "A delegated action inside a delegated action is not signed.");
|
|
1192
|
+
assertNames(d.actions, depth + 1);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
function canonicalTransaction(b64) {
|
|
1197
|
+
const bytes = fromBase64(b64);
|
|
1198
|
+
let decoded;
|
|
1199
|
+
try {
|
|
1200
|
+
decoded = decodeAnyTransaction(bytes);
|
|
1201
|
+
} catch (e) {
|
|
1202
|
+
throw new UnsafeTransactionError("non-canonical", `Not a borsh NEAR transaction: ${e.message}`);
|
|
1203
|
+
}
|
|
1204
|
+
const again = decoded.signature ? encodeSignedTransaction({ transaction: decoded.transaction, signature: decoded.signature }) : encodeTransaction(decoded.transaction);
|
|
1205
|
+
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.");
|
|
1206
|
+
if (!isValidAccountId(decoded.transaction.signerId) || !isValidAccountId(decoded.transaction.receiverId)) throw new UnsafeTransactionError("invalid-account", "The transaction names an invalid NEAR account id.");
|
|
1207
|
+
assertWellFormed(decoded.transaction);
|
|
1208
|
+
return decoded.transaction;
|
|
1209
|
+
}
|
|
1130
1210
|
function equalBytes(a, b) {
|
|
1131
1211
|
if (a.length !== b.length) return false;
|
|
1132
1212
|
let diff = 0;
|
|
@@ -1173,7 +1253,7 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
|
|
|
1173
1253
|
key() {
|
|
1174
1254
|
if (this._disposed) throw new import_core4.SignerError("This account has been disposed.");
|
|
1175
1255
|
}
|
|
1176
|
-
async signBytes(bytes, context) {
|
|
1256
|
+
async #signBytes(bytes, context) {
|
|
1177
1257
|
this.key();
|
|
1178
1258
|
return this.signer.sign(bytes, { scheme: "ed25519", context });
|
|
1179
1259
|
}
|
|
@@ -1188,16 +1268,17 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
|
|
|
1188
1268
|
async sign(message) {
|
|
1189
1269
|
const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
1190
1270
|
if (bytes.length === 32 || carriesKey(bytes, this.publicKey.data)) throw new MessageIsTransactionError();
|
|
1191
|
-
return `ed25519:${bytesToBase58(await this
|
|
1271
|
+
return `ed25519:${bytesToBase58(await this.#signBytes(bytes, "near-message"))}`;
|
|
1192
1272
|
}
|
|
1193
1273
|
/** NEP-413 off-chain message (what NEAR Intents and dApps ask wallets to sign). */
|
|
1194
1274
|
async signNep413(payload) {
|
|
1195
|
-
const sig = await this
|
|
1275
|
+
const sig = await this.#signBytes(nep413Hash(payload), "near-nep413");
|
|
1196
1276
|
return { signature: toBase64(sig), publicKey: publicKeyToString(this.publicKey), accountId: this.address };
|
|
1197
1277
|
}
|
|
1198
1278
|
/** Sign a fully built transaction. No checks — see `signTransaction`. */
|
|
1199
1279
|
async signBuilt(tx) {
|
|
1200
|
-
|
|
1280
|
+
assertWellFormed(tx);
|
|
1281
|
+
const sig = await this.#signBytes(WalletAccountReadOnlyNear.hashOf(tx), "near-tx");
|
|
1201
1282
|
return { transaction: tx, signature: { keyType: "ed25519", data: sig } };
|
|
1202
1283
|
}
|
|
1203
1284
|
/** Build → hard checks → preflight → fee cap. Shared by sign / send / transfer. */
|