decane-connect-kit 2.1.0 → 2.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.cjs +65 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +65 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2267,6 +2267,12 @@ var TeeClient = class {
|
|
|
2267
2267
|
this.teeUrl = teeUrl;
|
|
2268
2268
|
this.handle = null;
|
|
2269
2269
|
this.attested = false;
|
|
2270
|
+
/** Mirrors what the signer confirmed for this session, not what we asked for. */
|
|
2271
|
+
this.assertionPerSignature = false;
|
|
2272
|
+
}
|
|
2273
|
+
/** Whether this session actually got per-signature assertions. */
|
|
2274
|
+
requiresAssertionPerSignature() {
|
|
2275
|
+
return this.assertionPerSignature;
|
|
2270
2276
|
}
|
|
2271
2277
|
async ensureAttested() {
|
|
2272
2278
|
if (this.attested) return;
|
|
@@ -2282,16 +2288,20 @@ var TeeClient = class {
|
|
|
2282
2288
|
* couldn't derive them (older signer build, or a transient share-fetch
|
|
2283
2289
|
* failure); callers fall back to the backend's addresses in that case.
|
|
2284
2290
|
*/
|
|
2285
|
-
async openSession(deviceShare, jwt) {
|
|
2291
|
+
async openSession(deviceShare, jwt, requireAssertionPerSignature = false) {
|
|
2286
2292
|
await this.ensureAttested();
|
|
2287
2293
|
const res = await fetch(`${this.teeUrl}/signer/session`, {
|
|
2288
2294
|
method: "POST",
|
|
2289
2295
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
2290
|
-
body: JSON.stringify({
|
|
2296
|
+
body: JSON.stringify({
|
|
2297
|
+
deviceShare: bytesToBase64(deviceShare),
|
|
2298
|
+
requireAssertionPerSignature
|
|
2299
|
+
})
|
|
2291
2300
|
});
|
|
2292
2301
|
if (!res.ok) throw new Error("session open failed");
|
|
2293
2302
|
const body = await res.json();
|
|
2294
2303
|
this.handle = body.handle;
|
|
2304
|
+
this.assertionPerSignature = body.requireAssertionPerSignature === true;
|
|
2295
2305
|
return body.addresses ?? null;
|
|
2296
2306
|
}
|
|
2297
2307
|
/**
|
|
@@ -2382,14 +2392,33 @@ var TeeClient = class {
|
|
|
2382
2392
|
hasSession() {
|
|
2383
2393
|
return this.handle !== null;
|
|
2384
2394
|
}
|
|
2385
|
-
|
|
2395
|
+
/**
|
|
2396
|
+
* `jwt` is only needed when this session requires per-signature assertions —
|
|
2397
|
+
* it authenticates the challenge request. Passed per call rather than cached
|
|
2398
|
+
* on the instance deliberately: the backend's JWTs are shorter-lived than the
|
|
2399
|
+
* TEE session TTL, so a stored copy would go stale mid-session.
|
|
2400
|
+
*/
|
|
2401
|
+
async sign(req, jwt) {
|
|
2386
2402
|
if (!this.handle) throw new Error("no session");
|
|
2403
|
+
let gate = null;
|
|
2404
|
+
if (this.assertionPerSignature) {
|
|
2405
|
+
if (!jwt) throw new Error("sign requires a jwt when per-signature assertion is enabled");
|
|
2406
|
+
gate = await this.completeAssertion(jwt);
|
|
2407
|
+
}
|
|
2387
2408
|
const res = await fetch(`${this.teeUrl}/signer/sign`, {
|
|
2388
2409
|
method: "POST",
|
|
2389
2410
|
headers: { "Content-Type": "application/json" },
|
|
2390
|
-
body: JSON.stringify({
|
|
2411
|
+
body: JSON.stringify({
|
|
2412
|
+
handle: this.handle,
|
|
2413
|
+
...req,
|
|
2414
|
+
...gate ? { ...gate, origin: window.location.origin } : {}
|
|
2415
|
+
})
|
|
2391
2416
|
});
|
|
2392
2417
|
if (res.status === 401) {
|
|
2418
|
+
const body = await res.clone().json().catch(() => ({}));
|
|
2419
|
+
if (body?.error === "assertion_required") {
|
|
2420
|
+
throw new ExportNotAuthorizedError();
|
|
2421
|
+
}
|
|
2393
2422
|
this.handle = null;
|
|
2394
2423
|
throw new SessionExpiredError();
|
|
2395
2424
|
}
|
|
@@ -2412,10 +2441,11 @@ var TeeClient = class {
|
|
|
2412
2441
|
// src/social/session.ts
|
|
2413
2442
|
init_errors();
|
|
2414
2443
|
var SessionManager = class {
|
|
2415
|
-
constructor(events, durationMs, teeUrl) {
|
|
2444
|
+
constructor(events, durationMs, teeUrl, requireAssertionPerSignature = false) {
|
|
2416
2445
|
this.events = events;
|
|
2417
2446
|
this.durationMs = durationMs;
|
|
2418
2447
|
this.teeUrl = teeUrl;
|
|
2448
|
+
this.requireAssertionPerSignature = requireAssertionPerSignature;
|
|
2419
2449
|
this.tee = null;
|
|
2420
2450
|
this.evmAddress = null;
|
|
2421
2451
|
this.solanaAddress = null;
|
|
@@ -2435,7 +2465,18 @@ var SessionManager = class {
|
|
|
2435
2465
|
*/
|
|
2436
2466
|
async start(deviceShare, jwt, fallback) {
|
|
2437
2467
|
this.tee = new TeeClient(this.teeUrl);
|
|
2438
|
-
const verified = await this.tee.openSession(
|
|
2468
|
+
const verified = await this.tee.openSession(
|
|
2469
|
+
deviceShare,
|
|
2470
|
+
jwt,
|
|
2471
|
+
this.requireAssertionPerSignature
|
|
2472
|
+
);
|
|
2473
|
+
if (this.requireAssertionPerSignature && !this.tee.requiresAssertionPerSignature()) {
|
|
2474
|
+
void this.tee.closeSession();
|
|
2475
|
+
this.tee = null;
|
|
2476
|
+
throw new Error(
|
|
2477
|
+
"requireAssertionPerSignature was requested but this signer does not support it \u2014 refusing to open a session with weaker authority than configured."
|
|
2478
|
+
);
|
|
2479
|
+
}
|
|
2439
2480
|
const addresses = verified ?? fallback;
|
|
2440
2481
|
if (!addresses) {
|
|
2441
2482
|
this.tee = null;
|
|
@@ -2664,15 +2705,15 @@ async function verifyEmailCode(api, email, code) {
|
|
|
2664
2705
|
|
|
2665
2706
|
// src/social/signers/evm.ts
|
|
2666
2707
|
var import_ethers = require("ethers");
|
|
2667
|
-
async function signEvmTransaction(tee, chain, tx) {
|
|
2708
|
+
async function signEvmTransaction(tee, chain, tx, jwt) {
|
|
2668
2709
|
const resolved = await (0, import_ethers.resolveProperties)(tx);
|
|
2669
2710
|
const unsigned = import_ethers.Transaction.from(resolved).unsignedSerialized;
|
|
2670
2711
|
const payload = unsigned.startsWith("0x") ? unsigned.slice(2) : unsigned;
|
|
2671
2712
|
const txHash = (0, import_ethers.keccak256)("0x" + payload);
|
|
2672
|
-
return tee.sign({ chain, kind: "transaction", payload, txHash });
|
|
2713
|
+
return tee.sign({ chain, kind: "transaction", payload, txHash }, jwt);
|
|
2673
2714
|
}
|
|
2674
|
-
async function signEvmMessage(tee, chain, message) {
|
|
2675
|
-
return tee.sign({ chain, kind: "message", payload: message });
|
|
2715
|
+
async function signEvmMessage(tee, chain, message, jwt) {
|
|
2716
|
+
return tee.sign({ chain, kind: "message", payload: message }, jwt);
|
|
2676
2717
|
}
|
|
2677
2718
|
|
|
2678
2719
|
// src/social/signers/solana.ts
|
|
@@ -2685,13 +2726,13 @@ function b64(bytes) {
|
|
|
2685
2726
|
function unb64(s) {
|
|
2686
2727
|
return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
|
|
2687
2728
|
}
|
|
2688
|
-
async function signSolanaTransaction(tee, chain, tx) {
|
|
2729
|
+
async function signSolanaTransaction(tee, chain, tx, jwt) {
|
|
2689
2730
|
const bytes = tx instanceof import_web3.VersionedTransaction ? tx.serialize() : tx.serialize({ requireAllSignatures: false });
|
|
2690
|
-
const signed = await tee.sign({ chain, kind: "transaction", payload: b64(bytes) });
|
|
2731
|
+
const signed = await tee.sign({ chain, kind: "transaction", payload: b64(bytes) }, jwt);
|
|
2691
2732
|
return unb64(signed);
|
|
2692
2733
|
}
|
|
2693
|
-
async function signSolanaMessage(tee, chain, message) {
|
|
2694
|
-
const sig = await tee.sign({ chain, kind: "message", payload: b64(message) });
|
|
2734
|
+
async function signSolanaMessage(tee, chain, message, jwt) {
|
|
2735
|
+
const sig = await tee.sign({ chain, kind: "message", payload: b64(message) }, jwt);
|
|
2695
2736
|
return unb64(sig);
|
|
2696
2737
|
}
|
|
2697
2738
|
|
|
@@ -2964,7 +3005,12 @@ async function createDecaneConnect(config) {
|
|
|
2964
3005
|
const events = new EventEmitter();
|
|
2965
3006
|
const api = new ApiClient(baseUrl, config.apiKey, config.appId);
|
|
2966
3007
|
const storage = new Storage();
|
|
2967
|
-
const session = new SessionManager(
|
|
3008
|
+
const session = new SessionManager(
|
|
3009
|
+
events,
|
|
3010
|
+
durationMs,
|
|
3011
|
+
teeUrl,
|
|
3012
|
+
config.requireAssertionPerSignature === true
|
|
3013
|
+
);
|
|
2968
3014
|
let auth = null;
|
|
2969
3015
|
let persisted = loadPersisted(PERSIST_KEY);
|
|
2970
3016
|
async function pinSetup() {
|
|
@@ -3363,11 +3409,11 @@ async function createDecaneConnect(config) {
|
|
|
3363
3409
|
async signMessage(req) {
|
|
3364
3410
|
const tee = session.requireActive();
|
|
3365
3411
|
if (req.chain.startsWith("evm:")) {
|
|
3366
|
-
return signEvmMessage(tee, req.chain, req.message);
|
|
3412
|
+
return signEvmMessage(tee, req.chain, req.message, auth?.jwt);
|
|
3367
3413
|
}
|
|
3368
3414
|
if (req.chain.startsWith("solana:")) {
|
|
3369
3415
|
const msg = typeof req.message === "string" ? new TextEncoder().encode(req.message) : req.message;
|
|
3370
|
-
const sig = await signSolanaMessage(tee, req.chain, msg);
|
|
3416
|
+
const sig = await signSolanaMessage(tee, req.chain, msg, auth?.jwt);
|
|
3371
3417
|
return bufferToB64u(sig);
|
|
3372
3418
|
}
|
|
3373
3419
|
throw new CallSequenceError(`Unsupported chain: ${req.chain}`);
|
|
@@ -3415,7 +3461,7 @@ async function createDecaneConnect(config) {
|
|
|
3415
3461
|
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas ?? 0n
|
|
3416
3462
|
} : { gasPrice: req.gasPrice ?? feeData.gasPrice ?? void 0 }
|
|
3417
3463
|
};
|
|
3418
|
-
const signedTx = await signEvmTransaction(tee, req.chain, tx);
|
|
3464
|
+
const signedTx = await signEvmTransaction(tee, req.chain, tx, auth?.jwt);
|
|
3419
3465
|
const txResponse = await provider.broadcastTransaction(signedTx);
|
|
3420
3466
|
return txResponse.hash;
|
|
3421
3467
|
},
|
|
@@ -3428,7 +3474,7 @@ async function createDecaneConnect(config) {
|
|
|
3428
3474
|
tx = import_web32.Transaction.from(serializedTx);
|
|
3429
3475
|
}
|
|
3430
3476
|
const solChain = config.chains.find((c) => c.startsWith("solana:")) ?? "solana:mainnet";
|
|
3431
|
-
return signSolanaTransaction(tee, solChain, tx);
|
|
3477
|
+
return signSolanaTransaction(tee, solChain, tx, auth?.jwt);
|
|
3432
3478
|
},
|
|
3433
3479
|
async disconnect() {
|
|
3434
3480
|
session.end();
|