@medialane/sdk 0.120.0 → 0.122.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/starknet/index.cjs +566 -0
- package/dist/starknet/index.cjs.map +1 -1
- package/dist/starknet/index.d.cts +237 -3
- package/dist/starknet/index.d.ts +237 -3
- package/dist/starknet/index.js +544 -2
- package/dist/starknet/index.js.map +1 -1
- package/package.json +1 -6
- package/dist/guardian-4rnV78dm.d.cts +0 -28
- package/dist/guardian-4rnV78dm.d.ts +0 -28
- package/dist/wallet/index.cjs +0 -808
- package/dist/wallet/index.cjs.map +0 -1
- package/dist/wallet/index.d.cts +0 -163
- package/dist/wallet/index.d.ts +0 -163
- package/dist/wallet/index.js +0 -786
- package/dist/wallet/index.js.map +0 -1
package/dist/starknet/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
3
3
|
import { base32, base58 } from '@scure/base';
|
|
4
|
-
import { hash, cairo, uint256, RpcProvider, CairoOption, CairoOptionVariant, num, ec, encode, Contract, TypedDataRevision, constants, shortString } from 'starknet';
|
|
4
|
+
import { hash, cairo, uint256, RpcProvider, CairoOption, CairoOptionVariant, num, ec, encode, validateAndParseAddress, Account, typedData, stark, Contract, TypedDataRevision, constants, shortString } from 'starknet';
|
|
5
5
|
import { extract, expand } from '@noble/hashes/hkdf.js';
|
|
6
6
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
7
7
|
|
|
@@ -12327,6 +12327,548 @@ function signWithPrivateKey(privateKeyHex, msgHash) {
|
|
|
12327
12327
|
return [num.toHex(sig.r), num.toHex(sig.s)];
|
|
12328
12328
|
}
|
|
12329
12329
|
|
|
12330
|
-
|
|
12330
|
+
// src/wallet/store.ts
|
|
12331
|
+
function createOwnerStore(config) {
|
|
12332
|
+
const { storeKey, changeEvent } = config;
|
|
12333
|
+
const announce = () => {
|
|
12334
|
+
if (typeof window === "undefined") return;
|
|
12335
|
+
window.dispatchEvent(new Event(changeEvent));
|
|
12336
|
+
};
|
|
12337
|
+
return {
|
|
12338
|
+
load() {
|
|
12339
|
+
if (typeof window === "undefined") return null;
|
|
12340
|
+
try {
|
|
12341
|
+
const raw = localStorage.getItem(storeKey);
|
|
12342
|
+
return raw ? JSON.parse(raw) : null;
|
|
12343
|
+
} catch {
|
|
12344
|
+
return null;
|
|
12345
|
+
}
|
|
12346
|
+
},
|
|
12347
|
+
loadAddress() {
|
|
12348
|
+
return this.load()?.address ?? null;
|
|
12349
|
+
},
|
|
12350
|
+
save(sealed) {
|
|
12351
|
+
localStorage.setItem(storeKey, JSON.stringify(sealed));
|
|
12352
|
+
announce();
|
|
12353
|
+
},
|
|
12354
|
+
clear() {
|
|
12355
|
+
localStorage.removeItem(storeKey);
|
|
12356
|
+
announce();
|
|
12357
|
+
},
|
|
12358
|
+
notifyChange: announce,
|
|
12359
|
+
onChange(listener) {
|
|
12360
|
+
window.addEventListener(changeEvent, listener);
|
|
12361
|
+
return () => window.removeEventListener(changeEvent, listener);
|
|
12362
|
+
}
|
|
12363
|
+
};
|
|
12364
|
+
}
|
|
12365
|
+
|
|
12366
|
+
// src/wallet/pairing.ts
|
|
12367
|
+
var SCHEME = "medialane-device";
|
|
12368
|
+
var VERSION = 1;
|
|
12369
|
+
var LABEL_MAX = 32;
|
|
12370
|
+
var STARK_PRIME = (1n << 251n) + 17n * (1n << 192n) + 1n;
|
|
12371
|
+
var InvalidPairingPayloadError = class extends Error {
|
|
12372
|
+
constructor(message = "This code is not a Medialane device request.") {
|
|
12373
|
+
super(message);
|
|
12374
|
+
this.name = "InvalidPairingPayloadError";
|
|
12375
|
+
}
|
|
12376
|
+
};
|
|
12377
|
+
function normalisePublicKey(input) {
|
|
12378
|
+
if (typeof input !== "string" || !/^0x[0-9a-fA-F]+$/.test(input)) {
|
|
12379
|
+
throw new InvalidPairingPayloadError("That device key is not valid.");
|
|
12380
|
+
}
|
|
12381
|
+
const value = BigInt(input);
|
|
12382
|
+
if (value === 0n || value >= STARK_PRIME) {
|
|
12383
|
+
throw new InvalidPairingPayloadError("That device key is not valid.");
|
|
12384
|
+
}
|
|
12385
|
+
return `0x${value.toString(16)}`;
|
|
12386
|
+
}
|
|
12387
|
+
function sanitiseLabel(input) {
|
|
12388
|
+
const raw = typeof input === "string" ? input : "";
|
|
12389
|
+
return raw.replace(/\s+/g, " ").trim().slice(0, LABEL_MAX);
|
|
12390
|
+
}
|
|
12391
|
+
function encodePairingPayload(payload) {
|
|
12392
|
+
return JSON.stringify({
|
|
12393
|
+
scheme: SCHEME,
|
|
12394
|
+
version: VERSION,
|
|
12395
|
+
publicKey: normalisePublicKey(payload.publicKey),
|
|
12396
|
+
label: sanitiseLabel(payload.label)
|
|
12397
|
+
});
|
|
12398
|
+
}
|
|
12399
|
+
function parsePairingPayload(encoded) {
|
|
12400
|
+
let data;
|
|
12401
|
+
try {
|
|
12402
|
+
data = JSON.parse(encoded);
|
|
12403
|
+
} catch {
|
|
12404
|
+
throw new InvalidPairingPayloadError();
|
|
12405
|
+
}
|
|
12406
|
+
if (data === null || typeof data !== "object") throw new InvalidPairingPayloadError();
|
|
12407
|
+
if (data.scheme !== SCHEME || data.version !== VERSION) throw new InvalidPairingPayloadError();
|
|
12408
|
+
return {
|
|
12409
|
+
publicKey: normalisePublicKey(data.publicKey),
|
|
12410
|
+
label: sanitiseLabel(data.label)
|
|
12411
|
+
};
|
|
12412
|
+
}
|
|
12413
|
+
function parseAccountAddress(input) {
|
|
12414
|
+
const trimmed = typeof input === "string" ? input.trim() : "";
|
|
12415
|
+
if (!/^0x[0-9a-fA-F]{50,64}$/.test(trimmed)) {
|
|
12416
|
+
throw new InvalidPairingPayloadError("That does not look like an account address.");
|
|
12417
|
+
}
|
|
12418
|
+
if (BigInt(trimmed) === 0n) {
|
|
12419
|
+
throw new InvalidPairingPayloadError("That does not look like an account address.");
|
|
12420
|
+
}
|
|
12421
|
+
return trimmed;
|
|
12422
|
+
}
|
|
12423
|
+
|
|
12424
|
+
// src/wallet/recovery-key.ts
|
|
12425
|
+
function isRecoveryKeyForWallet(sealed) {
|
|
12426
|
+
try {
|
|
12427
|
+
return BigInt(computeAccountAddress(sealed.ownerPubKey, 0)) === BigInt(sealed.address);
|
|
12428
|
+
} catch {
|
|
12429
|
+
return false;
|
|
12430
|
+
}
|
|
12431
|
+
}
|
|
12432
|
+
|
|
12433
|
+
// src/wallet/guardian-status.ts
|
|
12434
|
+
function describeGuardianStatus(guardians) {
|
|
12435
|
+
if (guardians.length === 0) return { kind: "none" };
|
|
12436
|
+
return { kind: "active", guardian: guardians[0] };
|
|
12437
|
+
}
|
|
12438
|
+
function describeRecoveryAction(escape) {
|
|
12439
|
+
if (escape.escapeType !== "Owner") return "none";
|
|
12440
|
+
if (escape.status === "Ready") return "complete";
|
|
12441
|
+
if (escape.status === "Expired") return "start";
|
|
12442
|
+
return "none";
|
|
12443
|
+
}
|
|
12444
|
+
function normalizeWalletAddress(address) {
|
|
12445
|
+
return normalizeAddress("STARKNET", address);
|
|
12446
|
+
}
|
|
12447
|
+
function isValidStarknetAddress(address) {
|
|
12448
|
+
try {
|
|
12449
|
+
validateAndParseAddress(address.trim());
|
|
12450
|
+
return true;
|
|
12451
|
+
} catch {
|
|
12452
|
+
return false;
|
|
12453
|
+
}
|
|
12454
|
+
}
|
|
12455
|
+
async function isDeployed(provider, address) {
|
|
12456
|
+
try {
|
|
12457
|
+
await provider.getClassHashAt(normalizeWalletAddress(address));
|
|
12458
|
+
return true;
|
|
12459
|
+
} catch {
|
|
12460
|
+
return false;
|
|
12461
|
+
}
|
|
12462
|
+
}
|
|
12463
|
+
|
|
12464
|
+
// src/wallet/self-fund-consent.ts
|
|
12465
|
+
function createSelfFundConsent(estimateFee) {
|
|
12466
|
+
let handler = null;
|
|
12467
|
+
return {
|
|
12468
|
+
registerHandler(next) {
|
|
12469
|
+
handler = next;
|
|
12470
|
+
},
|
|
12471
|
+
async request({ address, calls }) {
|
|
12472
|
+
if (!handler) return false;
|
|
12473
|
+
const feeEstimate = address && calls ? estimateFee(address, calls).catch(() => null) : Promise.resolve(null);
|
|
12474
|
+
return handler(feeEstimate);
|
|
12475
|
+
}
|
|
12476
|
+
};
|
|
12477
|
+
}
|
|
12478
|
+
|
|
12479
|
+
// src/wallet/passkey.ts
|
|
12480
|
+
var PasskeyCancelledError = class extends Error {
|
|
12481
|
+
constructor(message = "Passkey prompt was cancelled.") {
|
|
12482
|
+
super(message);
|
|
12483
|
+
this.name = "PasskeyCancelledError";
|
|
12484
|
+
}
|
|
12485
|
+
};
|
|
12486
|
+
var encodeBase64 = (buf) => {
|
|
12487
|
+
const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
|
|
12488
|
+
let binary = "";
|
|
12489
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
12490
|
+
return btoa(binary);
|
|
12491
|
+
};
|
|
12492
|
+
var decodeBase64 = (value) => {
|
|
12493
|
+
const binary = atob(value);
|
|
12494
|
+
const bytes = new Uint8Array(binary.length);
|
|
12495
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
12496
|
+
return bytes;
|
|
12497
|
+
};
|
|
12498
|
+
function isPasskeyCancellation(err) {
|
|
12499
|
+
const name = err?.name;
|
|
12500
|
+
return name === "NotAllowedError" || name === "AbortError";
|
|
12501
|
+
}
|
|
12502
|
+
function createPasskeyOwner(config) {
|
|
12503
|
+
const randomBytes = config.randomBytes ?? ((length) => crypto.getRandomValues(new Uint8Array(length)));
|
|
12504
|
+
const credentialsApi = () => {
|
|
12505
|
+
const api = config.credentials ?? (typeof navigator === "undefined" ? void 0 : navigator.credentials);
|
|
12506
|
+
if (!api) throw new Error("Passkeys are only available in a browser.");
|
|
12507
|
+
return api;
|
|
12508
|
+
};
|
|
12509
|
+
const prfUnsupportedMessage = () => {
|
|
12510
|
+
const isBrave = typeof navigator !== "undefined" && "brave" in navigator;
|
|
12511
|
+
const cause = isBrave ? "Brave doesn't currently support the WebAuthn PRF extension." : "This browser didn't return a passkey PRF secret.";
|
|
12512
|
+
return `${cause} ${config.appName} needs it to seal your key. Your device passkey (Touch ID) is fine, the limitation is the browser. Please open this in Safari or Chrome on an up-to-date OS.`;
|
|
12513
|
+
};
|
|
12514
|
+
async function registerPasskey() {
|
|
12515
|
+
let credential;
|
|
12516
|
+
try {
|
|
12517
|
+
credential = await credentialsApi().create({
|
|
12518
|
+
publicKey: {
|
|
12519
|
+
challenge: randomBytes(32),
|
|
12520
|
+
rp: { name: config.relyingPartyName, id: config.relyingPartyId() },
|
|
12521
|
+
user: await config.passkeyUser(),
|
|
12522
|
+
excludeCredentials: config.knownCredentials(),
|
|
12523
|
+
pubKeyCredParams: [
|
|
12524
|
+
{ type: "public-key", alg: -7 },
|
|
12525
|
+
{ type: "public-key", alg: -257 }
|
|
12526
|
+
],
|
|
12527
|
+
authenticatorSelection: {
|
|
12528
|
+
residentKey: "required",
|
|
12529
|
+
userVerification: "required",
|
|
12530
|
+
authenticatorAttachment: "platform"
|
|
12531
|
+
},
|
|
12532
|
+
extensions: { prf: { eval: { first: config.prfSalt } } }
|
|
12533
|
+
}
|
|
12534
|
+
});
|
|
12535
|
+
} catch (err) {
|
|
12536
|
+
if (isPasskeyCancellation(err)) throw new PasskeyCancelledError();
|
|
12537
|
+
throw err;
|
|
12538
|
+
}
|
|
12539
|
+
const prf = credential.getClientExtensionResults().prf;
|
|
12540
|
+
return { credentialId: encodeBase64(credential.rawId), prfFirst: prf?.results?.first ?? null };
|
|
12541
|
+
}
|
|
12542
|
+
async function prfSecret(credentialId) {
|
|
12543
|
+
let assertion;
|
|
12544
|
+
try {
|
|
12545
|
+
assertion = await credentialsApi().get({
|
|
12546
|
+
publicKey: {
|
|
12547
|
+
challenge: randomBytes(32),
|
|
12548
|
+
rpId: config.relyingPartyId(),
|
|
12549
|
+
allowCredentials: [{ type: "public-key", id: decodeBase64(credentialId) }],
|
|
12550
|
+
userVerification: "required",
|
|
12551
|
+
extensions: { prf: { eval: { first: config.prfSalt } } }
|
|
12552
|
+
}
|
|
12553
|
+
});
|
|
12554
|
+
} catch (err) {
|
|
12555
|
+
if (isPasskeyCancellation(err)) throw new PasskeyCancelledError();
|
|
12556
|
+
throw err;
|
|
12557
|
+
}
|
|
12558
|
+
const result = assertion.getClientExtensionResults().prf?.results?.first;
|
|
12559
|
+
if (!result) throw new Error("Passkey PRF unavailable on this device/browser.");
|
|
12560
|
+
return new Uint8Array(result);
|
|
12561
|
+
}
|
|
12562
|
+
async function secretFromRegistration(registration) {
|
|
12563
|
+
if (registration.prfFirst) return new Uint8Array(registration.prfFirst);
|
|
12564
|
+
try {
|
|
12565
|
+
return await prfSecret(registration.credentialId);
|
|
12566
|
+
} catch {
|
|
12567
|
+
throw new Error(prfUnsupportedMessage());
|
|
12568
|
+
}
|
|
12569
|
+
}
|
|
12570
|
+
async function seal(secret, privateKeyHex) {
|
|
12571
|
+
const aes = await deriveAesKey(secret, config.hkdfInfo);
|
|
12572
|
+
const iv = randomBytes(12);
|
|
12573
|
+
const ciphertext = await sealPrivateKey(aes, iv, privateKeyHex);
|
|
12574
|
+
return { iv: encodeBase64(iv), ciphertext: encodeBase64(ciphertext) };
|
|
12575
|
+
}
|
|
12576
|
+
return {
|
|
12577
|
+
async createOwnerKey() {
|
|
12578
|
+
const registration = await registerPasskey();
|
|
12579
|
+
const secret = await secretFromRegistration(registration);
|
|
12580
|
+
const { privateKeyHex, publicKeyHex } = generateStarkKeyPair();
|
|
12581
|
+
const { iv, ciphertext } = await seal(secret, privateKeyHex);
|
|
12582
|
+
return {
|
|
12583
|
+
sealed: {
|
|
12584
|
+
credentialId: registration.credentialId,
|
|
12585
|
+
ownerPubKey: publicKeyHex,
|
|
12586
|
+
address: computeAccountAddress(publicKeyHex, 0),
|
|
12587
|
+
iv,
|
|
12588
|
+
ciphertext
|
|
12589
|
+
},
|
|
12590
|
+
privateKeyHex
|
|
12591
|
+
};
|
|
12592
|
+
},
|
|
12593
|
+
async unlockOwnerKey(sealed) {
|
|
12594
|
+
const secret = await prfSecret(sealed.credentialId);
|
|
12595
|
+
const aes = await deriveAesKey(secret, config.hkdfInfo);
|
|
12596
|
+
return unsealPrivateKey(aes, decodeBase64(sealed.iv), decodeBase64(sealed.ciphertext));
|
|
12597
|
+
},
|
|
12598
|
+
async sealImportedOwnerKey(privateKeyInput) {
|
|
12599
|
+
const { privateKeyHex, publicKeyHex } = starkKeyPairFromPrivateKey(privateKeyInput);
|
|
12600
|
+
const registration = await registerPasskey();
|
|
12601
|
+
const secret = await secretFromRegistration(registration);
|
|
12602
|
+
const { iv, ciphertext } = await seal(secret, privateKeyHex);
|
|
12603
|
+
return {
|
|
12604
|
+
credentialId: registration.credentialId,
|
|
12605
|
+
ownerPubKey: publicKeyHex,
|
|
12606
|
+
address: computeAccountAddress(publicKeyHex, 0),
|
|
12607
|
+
iv,
|
|
12608
|
+
ciphertext
|
|
12609
|
+
};
|
|
12610
|
+
},
|
|
12611
|
+
walletAddressForPrivateKey(privateKeyInput) {
|
|
12612
|
+
return computeAccountAddress(starkKeyPairFromPrivateKey(privateKeyInput).publicKeyHex, 0);
|
|
12613
|
+
}
|
|
12614
|
+
};
|
|
12615
|
+
}
|
|
12616
|
+
function accountFor(provider, address, privateKeyHex) {
|
|
12617
|
+
return new Account({ provider, address, signer: privateKeyHex, cairoVersion: "1" });
|
|
12618
|
+
}
|
|
12619
|
+
async function estimateSelfFundedFee(provider, address, calls) {
|
|
12620
|
+
const account = new Account({ provider, address, signer: "0x1", cairoVersion: "1" });
|
|
12621
|
+
const estimate = await account.estimateInvokeFee(calls);
|
|
12622
|
+
return { feeRaw: estimate.overall_fee, unit: estimate.unit };
|
|
12623
|
+
}
|
|
12624
|
+
function selfFundedExecutor(deps) {
|
|
12625
|
+
return {
|
|
12626
|
+
async execute({ userAddress, privateKeyHex, calls }) {
|
|
12627
|
+
const account = accountFor(deps.provider(), userAddress, privateKeyHex);
|
|
12628
|
+
const { transaction_hash } = await account.execute(calls);
|
|
12629
|
+
return { transactionHash: transaction_hash };
|
|
12630
|
+
}
|
|
12631
|
+
};
|
|
12632
|
+
}
|
|
12633
|
+
function sponsoredExecutor(deps) {
|
|
12634
|
+
const fallback = deps.fallback ?? selfFundedExecutor(deps);
|
|
12635
|
+
return {
|
|
12636
|
+
async execute(input) {
|
|
12637
|
+
const { userAddress, privateKeyHex, calls } = input;
|
|
12638
|
+
const result = await executeSponsored(
|
|
12639
|
+
{ proxyUrl: deps.proxyUrl, fetchImpl: deps.fetchImpl },
|
|
12640
|
+
{
|
|
12641
|
+
address: userAddress,
|
|
12642
|
+
signTypedData: async (data) => signWithPrivateKey(privateKeyHex, typedData.getMessageHash(data, userAddress))
|
|
12643
|
+
},
|
|
12644
|
+
calls
|
|
12645
|
+
);
|
|
12646
|
+
if (result.status === "sponsored") return { transactionHash: result.transactionHash };
|
|
12647
|
+
const consented = await deps.consent.request({ address: userAddress, calls });
|
|
12648
|
+
if (!consented) throw new SponsoredCallRejectedError(result.reason);
|
|
12649
|
+
return fallback.execute(input);
|
|
12650
|
+
}
|
|
12651
|
+
};
|
|
12652
|
+
}
|
|
12653
|
+
async function describeFailure(res, fallback) {
|
|
12654
|
+
const body = await res.json().catch(() => null);
|
|
12655
|
+
throw new Error(body?.error || fallback);
|
|
12656
|
+
}
|
|
12657
|
+
async function deploySponsored(input) {
|
|
12658
|
+
const doFetch = input.fetchImpl ?? fetch;
|
|
12659
|
+
const base = input.proxyUrl.replace(/\/$/, "");
|
|
12660
|
+
const buildRes = await doFetch(`${base}/build`, {
|
|
12661
|
+
method: "POST",
|
|
12662
|
+
headers: { "Content-Type": "application/json" },
|
|
12663
|
+
body: JSON.stringify({
|
|
12664
|
+
ownerPubkey: input.ownerPubKey,
|
|
12665
|
+
ownerAddress: input.ownerAddress,
|
|
12666
|
+
salt: input.salt ?? "0x0"
|
|
12667
|
+
})
|
|
12668
|
+
});
|
|
12669
|
+
if (!buildRes.ok) {
|
|
12670
|
+
await describeFailure(buildRes, "We couldn't prepare your wallet deployment. Please try again.");
|
|
12671
|
+
}
|
|
12672
|
+
const { typedData, deployment, calls } = await buildRes.json();
|
|
12673
|
+
const account = new Account({
|
|
12674
|
+
provider: input.provider,
|
|
12675
|
+
address: input.ownerAddress,
|
|
12676
|
+
signer: input.privateKeyHex,
|
|
12677
|
+
cairoVersion: "1"
|
|
12678
|
+
});
|
|
12679
|
+
const signature = stark.signatureToHexArray(await account.signMessage(typedData));
|
|
12680
|
+
const executeRes = await doFetch(`${base}/execute`, {
|
|
12681
|
+
method: "POST",
|
|
12682
|
+
headers: { "Content-Type": "application/json" },
|
|
12683
|
+
body: JSON.stringify({ ownerAddress: input.ownerAddress, typedData, signature, deployment, calls })
|
|
12684
|
+
});
|
|
12685
|
+
if (!executeRes.ok) {
|
|
12686
|
+
await describeFailure(executeRes, "We couldn't complete your wallet deployment. Please try again.");
|
|
12687
|
+
}
|
|
12688
|
+
const { transactionHash } = await executeRes.json();
|
|
12689
|
+
return { transactionHash };
|
|
12690
|
+
}
|
|
12691
|
+
async function deploySelfFunded(input) {
|
|
12692
|
+
const classHash = getCoordinates("STARKNET").mediaWalletClassHash;
|
|
12693
|
+
if (!classHash) throw new Error("Media Wallet class hash is not configured");
|
|
12694
|
+
const account = new Account({
|
|
12695
|
+
provider: input.provider,
|
|
12696
|
+
address: input.ownerAddress,
|
|
12697
|
+
signer: input.privateKeyHex,
|
|
12698
|
+
cairoVersion: "1"
|
|
12699
|
+
});
|
|
12700
|
+
const { transaction_hash } = await account.deployAccount({
|
|
12701
|
+
classHash,
|
|
12702
|
+
constructorCalldata: ownerConstructorCalldata(input.ownerPubKey),
|
|
12703
|
+
addressSalt: 0,
|
|
12704
|
+
contractAddress: input.ownerAddress
|
|
12705
|
+
});
|
|
12706
|
+
return { transactionHash: transaction_hash };
|
|
12707
|
+
}
|
|
12708
|
+
async function completeDeployment(deps, onStep, options = {}) {
|
|
12709
|
+
let sealed = options.forceNew ? null : deps.store.load();
|
|
12710
|
+
let privateKeyHex;
|
|
12711
|
+
if (!sealed) {
|
|
12712
|
+
onStep("creating-passkey");
|
|
12713
|
+
const created = await deps.passkey.createOwnerKey();
|
|
12714
|
+
sealed = created.sealed;
|
|
12715
|
+
privateKeyHex = created.privateKeyHex;
|
|
12716
|
+
deps.store.save(sealed);
|
|
12717
|
+
} else {
|
|
12718
|
+
privateKeyHex = await deps.passkey.unlockOwnerKey(sealed);
|
|
12719
|
+
}
|
|
12720
|
+
onStep("deploying");
|
|
12721
|
+
const wallet = { ownerAddress: sealed.address, ownerPubKey: sealed.ownerPubKey, privateKeyHex };
|
|
12722
|
+
const sponsored = deps.deploySponsoredImpl ?? deploySponsored;
|
|
12723
|
+
const selfFunded = deps.deploySelfFundedImpl ?? deploySelfFunded;
|
|
12724
|
+
if (deps.deployProxyUrl) {
|
|
12725
|
+
try {
|
|
12726
|
+
await sponsored({
|
|
12727
|
+
proxyUrl: deps.deployProxyUrl,
|
|
12728
|
+
provider: deps.provider(),
|
|
12729
|
+
fetchImpl: deps.fetchImpl,
|
|
12730
|
+
...wallet
|
|
12731
|
+
});
|
|
12732
|
+
} catch (sponsoredErr) {
|
|
12733
|
+
try {
|
|
12734
|
+
await selfFunded({ provider: deps.provider(), ...wallet });
|
|
12735
|
+
} catch (selfFundedErr) {
|
|
12736
|
+
const sponsored2 = sponsoredErr instanceof Error ? sponsoredErr.message : String(sponsoredErr);
|
|
12737
|
+
const selfFunded2 = selfFundedErr instanceof Error ? selfFundedErr.message : String(selfFundedErr);
|
|
12738
|
+
throw new Error(`Sponsored deploy failed: ${sponsored2}. Self-funded fallback failed: ${selfFunded2}`);
|
|
12739
|
+
}
|
|
12740
|
+
}
|
|
12741
|
+
} else {
|
|
12742
|
+
await selfFunded({ provider: deps.provider(), ...wallet });
|
|
12743
|
+
}
|
|
12744
|
+
onStep("signing-in");
|
|
12745
|
+
const address = sealed.address;
|
|
12746
|
+
const siwsToken = await (deps.requestSiwsTokenImpl ?? requestSiwsToken)({
|
|
12747
|
+
backendUrl: deps.backendUrl,
|
|
12748
|
+
walletAddress: address,
|
|
12749
|
+
signer: {
|
|
12750
|
+
signMessage: async (td) => signWithPrivateKey(privateKeyHex, typedData.getMessageHash(td, address))
|
|
12751
|
+
}
|
|
12752
|
+
});
|
|
12753
|
+
deps.store.notifyChange();
|
|
12754
|
+
return { sealed, siwsToken };
|
|
12755
|
+
}
|
|
12756
|
+
|
|
12757
|
+
// src/wallet/client.ts
|
|
12758
|
+
function describeDevices(owners, thisDevicePubkey) {
|
|
12759
|
+
const mine = computeOwnerGuid(thisDevicePubkey);
|
|
12760
|
+
return owners.map((owner) => ({
|
|
12761
|
+
guid: owner.guid,
|
|
12762
|
+
type: owner.type,
|
|
12763
|
+
isThisDevice: BigInt(owner.guid) === BigInt(mine)
|
|
12764
|
+
}));
|
|
12765
|
+
}
|
|
12766
|
+
function canRemoveDevice(devices, guid) {
|
|
12767
|
+
if (devices.length <= 1) return false;
|
|
12768
|
+
return devices.some((device) => BigInt(device.guid) === BigInt(guid));
|
|
12769
|
+
}
|
|
12770
|
+
function createMediaWallet(config) {
|
|
12771
|
+
const ttl = config.unlockTtlMs ?? 2e4;
|
|
12772
|
+
const unlockCache = /* @__PURE__ */ new Map();
|
|
12773
|
+
const lock = (address) => {
|
|
12774
|
+
const entry = unlockCache.get(address);
|
|
12775
|
+
if (!entry) return;
|
|
12776
|
+
clearTimeout(entry.timer);
|
|
12777
|
+
unlockCache.delete(address);
|
|
12778
|
+
};
|
|
12779
|
+
const unlockOnce = (sealed) => {
|
|
12780
|
+
const existing = unlockCache.get(sealed.address);
|
|
12781
|
+
if (existing) return existing.promise;
|
|
12782
|
+
const promise = config.passkey.unlockOwnerKey(sealed).catch((err) => {
|
|
12783
|
+
lock(sealed.address);
|
|
12784
|
+
throw err;
|
|
12785
|
+
});
|
|
12786
|
+
const timer = setTimeout(() => lock(sealed.address), ttl);
|
|
12787
|
+
unlockCache.set(sealed.address, { promise, timer });
|
|
12788
|
+
return promise;
|
|
12789
|
+
};
|
|
12790
|
+
const run = async (sealed, calls, userAddress) => {
|
|
12791
|
+
const privateKeyHex = await unlockOnce(sealed);
|
|
12792
|
+
return config.executor.execute({
|
|
12793
|
+
userAddress: userAddress ?? sealed.address,
|
|
12794
|
+
privateKeyHex,
|
|
12795
|
+
calls
|
|
12796
|
+
});
|
|
12797
|
+
};
|
|
12798
|
+
return {
|
|
12799
|
+
store: config.store,
|
|
12800
|
+
passkey: config.passkey,
|
|
12801
|
+
lock,
|
|
12802
|
+
signerFor(sealed) {
|
|
12803
|
+
return {
|
|
12804
|
+
address: sealed.address,
|
|
12805
|
+
signTypedData: async (data) => {
|
|
12806
|
+
const privateKeyHex = await unlockOnce(sealed);
|
|
12807
|
+
return signWithPrivateKey(privateKeyHex, typedData.getMessageHash(data, sealed.address));
|
|
12808
|
+
},
|
|
12809
|
+
execute: async (calls) => {
|
|
12810
|
+
const { transactionHash } = await run(sealed, calls);
|
|
12811
|
+
return { txHash: transactionHash };
|
|
12812
|
+
}
|
|
12813
|
+
};
|
|
12814
|
+
},
|
|
12815
|
+
run,
|
|
12816
|
+
getGuardians: (address) => getGuardians(config.provider(), address),
|
|
12817
|
+
getEscape: (address) => getEscape(config.provider(), address),
|
|
12818
|
+
getEscapeSecurityPeriod: (address) => getEscapeSecurityPeriod(config.provider(), address),
|
|
12819
|
+
getOwners: (address) => getOwners(config.provider(), address),
|
|
12820
|
+
async isOwnerOf(accountAddress, devicePubkey) {
|
|
12821
|
+
const owners = await getOwners(config.provider(), accountAddress);
|
|
12822
|
+
const guid = BigInt(computeOwnerGuid(devicePubkey));
|
|
12823
|
+
return owners.some((owner) => BigInt(owner.guid) === guid);
|
|
12824
|
+
},
|
|
12825
|
+
async setFirstGuardian(sealed, guardianPubkey) {
|
|
12826
|
+
const { transactionHash } = await run(sealed, [buildSetFirstGuardianCall(sealed.address, guardianPubkey)]);
|
|
12827
|
+
return transactionHash;
|
|
12828
|
+
},
|
|
12829
|
+
async triggerEscapeOwner(guardianSealed, targetAddress, newOwnerPubkey) {
|
|
12830
|
+
const { transactionHash } = await run(
|
|
12831
|
+
guardianSealed,
|
|
12832
|
+
[buildTriggerEscapeOwnerCall(targetAddress, newOwnerPubkey)],
|
|
12833
|
+
normalizeWalletAddress(targetAddress)
|
|
12834
|
+
);
|
|
12835
|
+
return transactionHash;
|
|
12836
|
+
},
|
|
12837
|
+
async completeEscapeOwner(guardianSealed, targetAddress) {
|
|
12838
|
+
const { transactionHash } = await run(
|
|
12839
|
+
guardianSealed,
|
|
12840
|
+
[buildCompleteEscapeOwnerCall(targetAddress)],
|
|
12841
|
+
normalizeWalletAddress(targetAddress)
|
|
12842
|
+
);
|
|
12843
|
+
return transactionHash;
|
|
12844
|
+
},
|
|
12845
|
+
async cancelEscape(sealed) {
|
|
12846
|
+
const { transactionHash } = await run(sealed, [buildCancelEscapeCall(sealed.address)]);
|
|
12847
|
+
return transactionHash;
|
|
12848
|
+
},
|
|
12849
|
+
async addDevice(sealed, devicePubkey) {
|
|
12850
|
+
const { transactionHash } = await run(sealed, [buildAddOwnerCall(sealed.address, devicePubkey)]);
|
|
12851
|
+
return transactionHash;
|
|
12852
|
+
},
|
|
12853
|
+
async removeDevice(sealed, ownerGuid) {
|
|
12854
|
+
const { transactionHash } = await run(sealed, [buildRemoveOwnerByGuidCall(sealed.address, ownerGuid)]);
|
|
12855
|
+
return transactionHash;
|
|
12856
|
+
},
|
|
12857
|
+
completeDeployment(onStep, options = {}) {
|
|
12858
|
+
if (!config.backendUrl) throw new Error("This wallet has no backend url configured for sign-in");
|
|
12859
|
+
const deps = {
|
|
12860
|
+
store: config.store,
|
|
12861
|
+
passkey: config.passkey,
|
|
12862
|
+
provider: config.provider,
|
|
12863
|
+
backendUrl: config.backendUrl,
|
|
12864
|
+
deployProxyUrl: config.deployProxyUrl,
|
|
12865
|
+
fetchImpl: config.fetchImpl
|
|
12866
|
+
};
|
|
12867
|
+
return completeDeployment(deps, onStep, options);
|
|
12868
|
+
}
|
|
12869
|
+
};
|
|
12870
|
+
}
|
|
12871
|
+
|
|
12872
|
+
export { ADMIN_HEADERS, ADMIN_SCOPE, MAX_SUPPLY as COIN_MAX_SUPPLY, MIN_SUPPLY as COIN_MIN_SUPPLY, ClubService, CreatorCoinFactoryABI, CreatorCoinService, DropCollectionABI, DropFactoryABI, DropService, ERC1155CollectionService, IPClubCollectionABI, IPClubFactoryABI, IPCollection1155ABI, IPCollection1155FactoryABI, IPCollectionABI, IPGenesisABI, IPMarketplaceABI, IPNftABI, IPSponsorshipABI, IPTicketCollectionABI, IPTicketCollectionFactoryABI, InvalidPairingPayloadError, InvalidStarkPrivateKeyError, MAX_HOLDERS_AT_LAUNCH, MAX_TEAM_ALLOCATION_PERCENT, Medialane1155ABI, MedialaneClient, MedialaneError, POPCollectionABI, POPFactoryABI, PasskeyCancelledError, PopService, SUGGESTED_DEFAULT_PRICE, SponsoredCallRejectedError, SponsorshipService, StarknetVenue, TicketService, VALIDATED_EKUBO_PARAMS, accountFor, adminRequestDigest, assertTransactionSucceeded, build1155CancellationTypedData, build1155OrderTypedData, buildAddOwnerCall, buildAdminSessionTypedData, buildCancelEscapeCall, buildCancellationTypedData, buildChangeOwnersCall, buildCompleteEscapeOwnerCall, buildCreateCreatorCoinCall, buildDeployAccountParams, buildFeeCall, buildLaunchOnEkuboCalls, buildOrderTypedData, buildRemoveOwnerByGuidCall, buildRemoveOwnerCall, buildSetFirstGuardianCall, buildTriggerEscapeOwnerCall, buybackQuoteRaw, canRemoveDevice, toRaw as coinToRaw, completeDeployment, computeAccountAddress, computeOwnerGuid, confirmIntentBestEffort, createAdminSessionGrant, createMediaWallet, createOwnerStore, createPasskeyOwner, createSelfFundConsent, decodeEscapeAndStatus, decodeGuardiansInfo, deploySelfFunded, deploySponsored, deployedCollectionFromReceipt, deriveAesKey, deriveOwnerKeyPair, describeDevices, describeGuardianStatus, describeRecoveryAction, encodeAdminHeaders, encodeByteArray, encodePairingPayload, estimateSelfFundedFee, executeIntent, executeIntents, executeSponsored, fdvHuman, generateStarkKeyPair, getCounter, getCounter1155, getCreatorCoinGuarantees, getEscape, getEscapeSecurityPeriod, getGuardians, getOrderDetails, getOrderDetails1155, getOwners, getSiwsStorageKey, getStoredSiwsToken, isDeployed, isRecoveryKeyForWallet, isSiwsTokenValid, isValidStarknetAddress, mintedTokenIdFromReceipt, normalizeSiwsSignature, normalizeWalletAddress, ownerAliveTypedData, ownerConstructorCalldata, parseAccountAddress, parseAdminHeaders, parseCreatorCoinCreated, parsePairingPayload, priceToEkuboParams, randomNonce, requestSiwsToken, sealPrivateKey, selfFundedExecutor, sessionKeyHashOf, signAdminRequest, signWithPrivateKey, sponsoredExecutor, starkKeyPairFromPrivateKey, storeSiwsToken, syncTransactionBestEffort, teamCoinsRaw, toContractConditions as toDropContractConditions, unsealPrivateKey, userMayPayInstead, validateName as validateCoinName, validateSupply as validateCoinSupply, validateSymbol as validateCoinSymbol, validatePrice, verifyAdminRequestSig };
|
|
12331
12873
|
//# sourceMappingURL=index.js.map
|
|
12332
12874
|
//# sourceMappingURL=index.js.map
|