@anywalletkit/wallet-near 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +53 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +53 -12
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ __export(src_exports, {
|
|
|
45
45
|
WalletAccountReadOnlyNear: () => WalletAccountReadOnlyNear,
|
|
46
46
|
WalletManagerNear: () => WalletManagerNear,
|
|
47
47
|
YOCTO: () => YOCTO,
|
|
48
|
+
accessKeyPermissionTag: () => accessKeyPermissionTag,
|
|
48
49
|
actionKey: () => actionKey,
|
|
49
50
|
argsBytes: () => argsBytes,
|
|
50
51
|
assertWellFormed: () => assertWellFormed,
|
|
@@ -361,17 +362,34 @@ function argsBytes(args) {
|
|
|
361
362
|
if (!isPlainObject(args)) throw new TypeError("function-call args must be bytes, a string or a plain object");
|
|
362
363
|
return utf8.encode(JSON.stringify(args));
|
|
363
364
|
}
|
|
365
|
+
var FUNCTION_CALL_PERMISSION_KEYS = /* @__PURE__ */ new Set(["allowance", "receiverId", "methodNames"]);
|
|
366
|
+
function accessKeyPermissionTag(permission) {
|
|
367
|
+
const keys = isPlainObject(permission) ? Object.keys(permission) : [];
|
|
368
|
+
if (keys.length !== 1) throw new TypeError(`an access-key permission must have exactly one variant, fullAccess or functionCall (has: ${keys.join(", ") || "none"})`);
|
|
369
|
+
const variant = permission[keys[0]];
|
|
370
|
+
if (keys[0] === "fullAccess") {
|
|
371
|
+
if (!isPlainObject(variant)) throw new TypeError("fullAccess must be a plain object");
|
|
372
|
+
return 1;
|
|
373
|
+
}
|
|
374
|
+
if (keys[0] === "functionCall") {
|
|
375
|
+
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");
|
|
376
|
+
if (typeof variant.receiverId !== "string") throw new TypeError("functionCall.receiverId must be a string");
|
|
377
|
+
if (!Array.isArray(variant.methodNames) || !variant.methodNames.every((m) => typeof m === "string")) throw new TypeError("functionCall.methodNames must be an array of strings");
|
|
378
|
+
if (variant.allowance !== void 0 && typeof variant.allowance !== "bigint") throw new TypeError("functionCall.allowance must be a bigint or absent");
|
|
379
|
+
return 0;
|
|
380
|
+
}
|
|
381
|
+
throw new TypeError(`unknown access-key permission ${JSON.stringify(keys[0])}`);
|
|
382
|
+
}
|
|
364
383
|
function writeAccessKey(w, k) {
|
|
365
384
|
w.u64(k.nonce);
|
|
366
|
-
|
|
385
|
+
const tag = accessKeyPermissionTag(k.permission);
|
|
386
|
+
w.u8(tag);
|
|
387
|
+
if (tag === 0) {
|
|
367
388
|
const p = k.permission.functionCall;
|
|
368
|
-
w.u8(0);
|
|
369
389
|
w.option(p.allowance, (a) => w.u128(a));
|
|
370
390
|
w.string(p.receiverId);
|
|
371
391
|
w.u32(p.methodNames.length);
|
|
372
392
|
for (const m of p.methodNames) w.string(m);
|
|
373
|
-
} else {
|
|
374
|
-
w.u8(1);
|
|
375
393
|
}
|
|
376
394
|
}
|
|
377
395
|
function readAccessKey(r) {
|
|
@@ -767,8 +785,15 @@ function describeTransaction(tx, ctx = {}) {
|
|
|
767
785
|
if (DANGEROUS_ACTIONS.has(key)) {
|
|
768
786
|
dangerous ??= KIND_OF_DANGEROUS[key];
|
|
769
787
|
warnings.push({ code: "dangerous-action", message: `${key} changes the account, its keys or its code.` });
|
|
770
|
-
if (key === "addKey"
|
|
771
|
-
|
|
788
|
+
if (key === "addKey") {
|
|
789
|
+
let tag;
|
|
790
|
+
try {
|
|
791
|
+
tag = accessKeyPermissionTag(a.addKey?.accessKey?.permission);
|
|
792
|
+
} catch {
|
|
793
|
+
tag = void 0;
|
|
794
|
+
}
|
|
795
|
+
if (tag === 1) warnings.push({ code: "full-access-key", message: "Adds a FULL ACCESS key: whoever holds it owns the account." });
|
|
796
|
+
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." });
|
|
772
797
|
}
|
|
773
798
|
continue;
|
|
774
799
|
}
|
|
@@ -1166,6 +1191,15 @@ function assertShape(actions, depth = 0) {
|
|
|
1166
1191
|
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
1192
|
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
1193
|
}
|
|
1194
|
+
if ("addKey" in a) {
|
|
1195
|
+
const k = a.addKey;
|
|
1196
|
+
if (!isPlainObject(k) || !isPlainObject(k.accessKey)) throw new UnsafeTransactionError("malformed-action", "addKey must carry an accessKey object.");
|
|
1197
|
+
try {
|
|
1198
|
+
accessKeyPermissionTag(k.accessKey.permission);
|
|
1199
|
+
} catch (e) {
|
|
1200
|
+
throw new UnsafeTransactionError("malformed-action", `AddKey: ${e.message}.`);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1169
1203
|
if ("signedDelegate" in a && depth === 0) assertShape(a.signedDelegate.delegateAction.actions, depth + 1);
|
|
1170
1204
|
}
|
|
1171
1205
|
}
|
|
@@ -1228,13 +1262,20 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
|
|
|
1228
1262
|
needsNetwork = true;
|
|
1229
1263
|
/** Derivation path, or `external` for an external signer. */
|
|
1230
1264
|
path;
|
|
1231
|
-
/**
|
|
1232
|
-
|
|
1265
|
+
/**
|
|
1266
|
+
* The signer that holds the key, in a private field: not a property of the account, so no code
|
|
1267
|
+
* the account is handed to (a protocol module, a logger) can reach it and sign around the
|
|
1268
|
+
* account's checks (audit 2026-10-29 A1).
|
|
1269
|
+
*/
|
|
1270
|
+
#signer;
|
|
1271
|
+
/** What holds the key: `seed`, `key` (one imported key) or `external`. */
|
|
1272
|
+
signerKind;
|
|
1233
1273
|
_disposed = false;
|
|
1234
1274
|
_readOnly;
|
|
1235
1275
|
constructor(signer, publicKey, path, config = {}, accountId) {
|
|
1236
1276
|
super(accountId ?? implicitAccountId(publicKey), config, ed25519Key(publicKey));
|
|
1237
|
-
this
|
|
1277
|
+
this.#signer = (0, import_core4.requireCurve)(signer, "ed25519");
|
|
1278
|
+
this.signerKind = this.#signer.kind;
|
|
1238
1279
|
this.path = path;
|
|
1239
1280
|
}
|
|
1240
1281
|
/** Wrap a raw derived key (takes ownership; zeroized on dispose). */
|
|
@@ -1248,14 +1289,14 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
|
|
|
1248
1289
|
}
|
|
1249
1290
|
/** The same key bound to a named account (`alice.near`) that lists it as a full-access key. */
|
|
1250
1291
|
withAccountId(accountId) {
|
|
1251
|
-
return new _WalletAccountNear(this
|
|
1292
|
+
return new _WalletAccountNear(this.#signer, this.publicKey.data, this.path, this._config, accountId);
|
|
1252
1293
|
}
|
|
1253
1294
|
key() {
|
|
1254
1295
|
if (this._disposed) throw new import_core4.SignerError("This account has been disposed.");
|
|
1255
1296
|
}
|
|
1256
1297
|
async #signBytes(bytes, context) {
|
|
1257
1298
|
this.key();
|
|
1258
|
-
return this
|
|
1299
|
+
return this.#signer.sign(bytes, { scheme: "ed25519", context });
|
|
1259
1300
|
}
|
|
1260
1301
|
/**
|
|
1261
1302
|
* Raw ed25519 signature over the message bytes, as NEAR tooling prints it: "ed25519:<base58>".
|
|
@@ -1342,7 +1383,7 @@ var WalletAccountNear = class _WalletAccountNear extends WalletAccountReadOnlyNe
|
|
|
1342
1383
|
/** Dispose the signer (zeroizes a local key). Idempotent. */
|
|
1343
1384
|
dispose() {
|
|
1344
1385
|
this._disposed = true;
|
|
1345
|
-
this
|
|
1386
|
+
this.#signer.dispose();
|
|
1346
1387
|
}
|
|
1347
1388
|
};
|
|
1348
1389
|
function decodeSigned(b64) {
|