@chipi-stack/chipi-react 14.15.0 → 14.16.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/hooks.d.mts +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +72 -18
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.mjs +72 -18
- package/dist/hooks.mjs.map +1 -1
- package/dist/{index-B8OIdrOX.d.mts → index-Dbqp9oNS.d.mts} +90 -14
- package/dist/{index-B8OIdrOX.d.ts → index-Dbqp9oNS.d.ts} +90 -14
- package/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +132 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +132 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -20394,6 +20394,41 @@ function hexEq(a, b) {
|
|
|
20394
20394
|
return a === b;
|
|
20395
20395
|
}
|
|
20396
20396
|
}
|
|
20397
|
+
function parseCapAmount(value, field, token) {
|
|
20398
|
+
try {
|
|
20399
|
+
const v = typeof value === "bigint" ? value : BigInt(String(value).trim());
|
|
20400
|
+
if (v < 0n) throw new Error("negative");
|
|
20401
|
+
return v;
|
|
20402
|
+
} catch {
|
|
20403
|
+
throw new Error(
|
|
20404
|
+
`session_spend_cap_invalid: ${field} for token ${token} must be a non-negative integer in base units (got "${String(value)}")`
|
|
20405
|
+
);
|
|
20406
|
+
}
|
|
20407
|
+
}
|
|
20408
|
+
function toSpendingPolicies(caps, lifetimeSeconds) {
|
|
20409
|
+
return caps.map((cap) => {
|
|
20410
|
+
const policy = "maxPerWindow" in cap ? {
|
|
20411
|
+
token: cap.token,
|
|
20412
|
+
maxPerCall: parseCapAmount(cap.maxPerCall, "maxPerCall", cap.token),
|
|
20413
|
+
maxPerWindow: parseCapAmount(cap.maxPerWindow, "maxPerWindow", cap.token),
|
|
20414
|
+
windowSeconds: cap.windowSeconds
|
|
20415
|
+
} : (() => {
|
|
20416
|
+
const amount = parseCapAmount(cap.amount, "amount", cap.token);
|
|
20417
|
+
return {
|
|
20418
|
+
token: cap.token,
|
|
20419
|
+
maxPerCall: amount,
|
|
20420
|
+
maxPerWindow: amount,
|
|
20421
|
+
windowSeconds: Math.max(1, lifetimeSeconds)
|
|
20422
|
+
};
|
|
20423
|
+
})();
|
|
20424
|
+
if (policy.maxPerWindow === 0n) {
|
|
20425
|
+
throw new Error(
|
|
20426
|
+
`session_spend_cap_zero: the cap for token ${cap.token} resolves to maxPerWindow = 0, which means unlimited on-chain. Use a positive cap.`
|
|
20427
|
+
);
|
|
20428
|
+
}
|
|
20429
|
+
return policy;
|
|
20430
|
+
});
|
|
20431
|
+
}
|
|
20397
20432
|
function sessionCovers(policy, calls) {
|
|
20398
20433
|
if (!policy?.allowedCalls?.length) return false;
|
|
20399
20434
|
return calls.every(
|
|
@@ -20408,6 +20443,10 @@ function useChipiWalletObject(config3) {
|
|
|
20408
20443
|
const { signTypedDataAsync } = useSignTypedData();
|
|
20409
20444
|
const { createSessionKeyAsync } = useCreateSessionKey();
|
|
20410
20445
|
const { addSessionKeyToContractAsync } = useAddSessionKeyToContract();
|
|
20446
|
+
const { chipiSDK } = useChipiContext();
|
|
20447
|
+
const sdk = useRef(chipiSDK);
|
|
20448
|
+
sdk.current = chipiSDK;
|
|
20449
|
+
const warnedMissingApproval = useRef(false);
|
|
20411
20450
|
const cfg = useRef(config3);
|
|
20412
20451
|
cfg.current = config3;
|
|
20413
20452
|
const requireWallet = () => {
|
|
@@ -20420,28 +20459,33 @@ function useChipiWalletObject(config3) {
|
|
|
20420
20459
|
if (policy.validUntil <= nowSec()) throw new Error("session_policy_expired");
|
|
20421
20460
|
const c = cfg.current;
|
|
20422
20461
|
const wallet = requireWallet();
|
|
20462
|
+
const lifetimeSeconds = Math.max(1, policy.validUntil - nowSec());
|
|
20463
|
+
const spendingPolicies = policy.spendCaps?.length ? toSpendingPolicies(policy.spendCaps, lifetimeSeconds) : [];
|
|
20423
20464
|
const encryptKey = await c.getEncryptKey();
|
|
20424
20465
|
const session = await createSessionKeyAsync({
|
|
20425
20466
|
encryptKey,
|
|
20426
|
-
durationSeconds:
|
|
20467
|
+
durationSeconds: lifetimeSeconds
|
|
20427
20468
|
});
|
|
20428
20469
|
const bearerToken = await c.getBearerToken();
|
|
20429
|
-
|
|
20430
|
-
|
|
20431
|
-
|
|
20432
|
-
|
|
20433
|
-
|
|
20434
|
-
|
|
20435
|
-
|
|
20436
|
-
|
|
20437
|
-
|
|
20438
|
-
|
|
20439
|
-
|
|
20440
|
-
|
|
20441
|
-
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
|
|
20470
|
+
const params = {
|
|
20471
|
+
encryptKey,
|
|
20472
|
+
wallet,
|
|
20473
|
+
sessionConfig: {
|
|
20474
|
+
sessionPublicKey: session.publicKey,
|
|
20475
|
+
validUntil: policy.validUntil,
|
|
20476
|
+
maxCalls: 1e3,
|
|
20477
|
+
// Selectors; empty = all entrypoints allowed. On-chain this is a
|
|
20478
|
+
// per-selector whitelist, NOT scoped to allowedCalls' contracts.
|
|
20479
|
+
allowedEntrypoints: policy.allowedCalls.map(
|
|
20480
|
+
(a) => hash_exports.getSelectorFromName(a.entrypoint)
|
|
20481
|
+
)
|
|
20482
|
+
}
|
|
20483
|
+
};
|
|
20484
|
+
if (spendingPolicies.length > 0) {
|
|
20485
|
+
await sdk.current.sessions.setupSession({ ...params, spendingPolicies }, bearerToken);
|
|
20486
|
+
} else {
|
|
20487
|
+
await addSessionKeyToContractAsync({ params, bearerToken });
|
|
20488
|
+
}
|
|
20445
20489
|
return session;
|
|
20446
20490
|
},
|
|
20447
20491
|
[createSessionKeyAsync, addSessionKeyToContractAsync]
|
|
@@ -20486,7 +20530,17 @@ function useChipiWalletObject(config3) {
|
|
|
20486
20530
|
createSession: async (policy) => {
|
|
20487
20531
|
await createSession(policy);
|
|
20488
20532
|
},
|
|
20489
|
-
requestApproval: (req) =>
|
|
20533
|
+
requestApproval: (req) => {
|
|
20534
|
+
const gate = cfg.current.requestApproval;
|
|
20535
|
+
if (gate) return gate(req);
|
|
20536
|
+
if (!warnedMissingApproval.current) {
|
|
20537
|
+
warnedMissingApproval.current = true;
|
|
20538
|
+
console.warn(
|
|
20539
|
+
"[ChipiSDK:Connect] No `requestApproval` was provided to useChipiWalletObject, so every approval (connect, execute, signTypedData, session) is denied. Pass `requestApproval` to show the user an approval UI and resolve true/false."
|
|
20540
|
+
);
|
|
20541
|
+
}
|
|
20542
|
+
return Promise.resolve(false);
|
|
20543
|
+
}
|
|
20490
20544
|
}),
|
|
20491
20545
|
[callAnyContractAsync, executeWithSessionAsync, signTypedDataAsync, createSession]
|
|
20492
20546
|
);
|
|
@@ -21166,10 +21220,33 @@ var USER_REFUSED_OP = 113;
|
|
|
21166
21220
|
var INVALID_REQUEST_PAYLOAD = 114;
|
|
21167
21221
|
var ACCOUNT_ALREADY_DEPLOYED = 115;
|
|
21168
21222
|
var UNKNOWN_ERROR = 163;
|
|
21223
|
+
var MISSING_APPROVAL_WARNING = "[ChipiSDK:Connect] No `requestApproval` was provided, so every approval (connect, execute, signTypedData, session) is denied. Pass `requestApproval` to show the user an approval UI and resolve true/false.";
|
|
21224
|
+
function normalizeChainId(value) {
|
|
21225
|
+
try {
|
|
21226
|
+
if (typeof value === "bigint") return value;
|
|
21227
|
+
if (typeof value === "number") {
|
|
21228
|
+
return Number.isSafeInteger(value) && value >= 0 ? BigInt(value) : null;
|
|
21229
|
+
}
|
|
21230
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
21231
|
+
if (/^0x[0-9a-f]+$/i.test(value) || /^[0-9]+$/.test(value)) return BigInt(value);
|
|
21232
|
+
return BigInt(shortString_exports.encodeShortString(value));
|
|
21233
|
+
} catch {
|
|
21234
|
+
return null;
|
|
21235
|
+
}
|
|
21236
|
+
}
|
|
21169
21237
|
function createChipiWindowObject(deps) {
|
|
21170
21238
|
const accountListeners = /* @__PURE__ */ new Set();
|
|
21171
21239
|
const networkListeners = /* @__PURE__ */ new Set();
|
|
21172
|
-
|
|
21240
|
+
let approved = false;
|
|
21241
|
+
let pendingConnect = null;
|
|
21242
|
+
let warnedMissingApproval = false;
|
|
21243
|
+
const approve = deps.requestApproval ?? (async () => {
|
|
21244
|
+
if (!warnedMissingApproval) {
|
|
21245
|
+
warnedMissingApproval = true;
|
|
21246
|
+
console.warn(MISSING_APPROVAL_WARNING);
|
|
21247
|
+
}
|
|
21248
|
+
return false;
|
|
21249
|
+
});
|
|
21173
21250
|
async function requireApproval(req) {
|
|
21174
21251
|
const ok = await approve(req);
|
|
21175
21252
|
if (!ok) throw new RpcError2(USER_REFUSED_OP, "User refused the operation");
|
|
@@ -21177,19 +21254,27 @@ function createChipiWindowObject(deps) {
|
|
|
21177
21254
|
const request = (async (call) => {
|
|
21178
21255
|
switch (call.type) {
|
|
21179
21256
|
case "wallet_requestAccounts": {
|
|
21180
|
-
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21257
|
+
if (call.params?.silent_mode) {
|
|
21258
|
+
return approved ? deps.getAccounts() : [];
|
|
21259
|
+
}
|
|
21260
|
+
if (approved) {
|
|
21261
|
+
const accounts = await deps.getAccounts();
|
|
21262
|
+
if (accounts.length > 0) return accounts;
|
|
21184
21263
|
}
|
|
21185
|
-
|
|
21264
|
+
if (!pendingConnect) {
|
|
21265
|
+
pendingConnect = requireApproval({ type: "connect" }).then(() => {
|
|
21266
|
+
approved = true;
|
|
21267
|
+
}).finally(() => {
|
|
21268
|
+
pendingConnect = null;
|
|
21269
|
+
});
|
|
21270
|
+
}
|
|
21271
|
+
await pendingConnect;
|
|
21272
|
+
return deps.getAccounts();
|
|
21186
21273
|
}
|
|
21187
21274
|
case "wallet_requestChainId":
|
|
21188
21275
|
return deps.chainId;
|
|
21189
|
-
case "wallet_getPermissions":
|
|
21190
|
-
|
|
21191
|
-
return accounts.length > 0 ? ["accounts"] : [];
|
|
21192
|
-
}
|
|
21276
|
+
case "wallet_getPermissions":
|
|
21277
|
+
return approved ? ["accounts"] : [];
|
|
21193
21278
|
case "wallet_addInvokeTransaction": {
|
|
21194
21279
|
const wireCalls = call.params?.calls ?? [];
|
|
21195
21280
|
if (wireCalls.length === 0) {
|
|
@@ -21202,14 +21287,31 @@ function createChipiWindowObject(deps) {
|
|
|
21202
21287
|
}
|
|
21203
21288
|
case "wallet_signTypedData": {
|
|
21204
21289
|
const typedData = call.params;
|
|
21290
|
+
const domainChainId = typedData?.domain?.chainId;
|
|
21291
|
+
if (domainChainId !== void 0 && domainChainId !== null) {
|
|
21292
|
+
const expected = normalizeChainId(deps.chainId);
|
|
21293
|
+
const actual = normalizeChainId(domainChainId);
|
|
21294
|
+
if (actual === null || expected === null || actual !== expected) {
|
|
21295
|
+
throw new RpcError2(
|
|
21296
|
+
INVALID_REQUEST_PAYLOAD,
|
|
21297
|
+
`wallet_signTypedData: domain.chainId ${String(domainChainId)} does not match the wallet chain ${deps.chainId}`
|
|
21298
|
+
);
|
|
21299
|
+
}
|
|
21300
|
+
}
|
|
21205
21301
|
await requireApproval({ type: "signTypedData", typedData });
|
|
21206
21302
|
return deps.signTypedData(typedData);
|
|
21207
21303
|
}
|
|
21208
21304
|
case "wallet_deploymentData":
|
|
21209
21305
|
try {
|
|
21210
21306
|
return await deps.getDeploymentData();
|
|
21211
|
-
} catch {
|
|
21212
|
-
|
|
21307
|
+
} catch (err2) {
|
|
21308
|
+
if (err2 instanceof Error && err2.message === "account_already_deployed") {
|
|
21309
|
+
throw new RpcError2(ACCOUNT_ALREADY_DEPLOYED, "Account already deployed");
|
|
21310
|
+
}
|
|
21311
|
+
throw new RpcError2(
|
|
21312
|
+
UNKNOWN_ERROR,
|
|
21313
|
+
err2 instanceof Error ? err2.message : "Could not read deployment data"
|
|
21314
|
+
);
|
|
21213
21315
|
}
|
|
21214
21316
|
case "wallet_supportedSpecs":
|
|
21215
21317
|
return SUPPORTED_SPECS;
|