@medialane/sdk 0.120.0 → 0.121.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 +446 -0
- package/dist/starknet/index.cjs.map +1 -1
- package/dist/starknet/index.d.cts +186 -3
- package/dist/starknet/index.d.ts +186 -3
- package/dist/starknet/index.js +427 -2
- package/dist/starknet/index.js.map +1 -1
- package/package.json +2 -7
- 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/wallet/index.js
DELETED
|
@@ -1,786 +0,0 @@
|
|
|
1
|
-
import { validateAndParseAddress, Account, typedData, hash, num, ec } from 'starknet';
|
|
2
|
-
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
3
|
-
import { base32, base58 } from '@scure/base';
|
|
4
|
-
|
|
5
|
-
// src/wallet/store.ts
|
|
6
|
-
function createOwnerStore(config) {
|
|
7
|
-
const { storeKey, changeEvent } = config;
|
|
8
|
-
const announce = () => {
|
|
9
|
-
if (typeof window === "undefined") return;
|
|
10
|
-
window.dispatchEvent(new Event(changeEvent));
|
|
11
|
-
};
|
|
12
|
-
return {
|
|
13
|
-
load() {
|
|
14
|
-
if (typeof window === "undefined") return null;
|
|
15
|
-
try {
|
|
16
|
-
const raw = localStorage.getItem(storeKey);
|
|
17
|
-
return raw ? JSON.parse(raw) : null;
|
|
18
|
-
} catch {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
loadAddress() {
|
|
23
|
-
return this.load()?.address ?? null;
|
|
24
|
-
},
|
|
25
|
-
save(sealed) {
|
|
26
|
-
localStorage.setItem(storeKey, JSON.stringify(sealed));
|
|
27
|
-
announce();
|
|
28
|
-
},
|
|
29
|
-
clear() {
|
|
30
|
-
localStorage.removeItem(storeKey);
|
|
31
|
-
announce();
|
|
32
|
-
},
|
|
33
|
-
notifyChange: announce,
|
|
34
|
-
onChange(listener) {
|
|
35
|
-
window.addEventListener(changeEvent, listener);
|
|
36
|
-
return () => window.removeEventListener(changeEvent, listener);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/wallet/pairing.ts
|
|
42
|
-
var SCHEME = "medialane-device";
|
|
43
|
-
var VERSION = 1;
|
|
44
|
-
var LABEL_MAX = 32;
|
|
45
|
-
var STARK_PRIME = (1n << 251n) + 17n * (1n << 192n) + 1n;
|
|
46
|
-
var InvalidPairingPayloadError = class extends Error {
|
|
47
|
-
constructor(message = "This code is not a Medialane device request.") {
|
|
48
|
-
super(message);
|
|
49
|
-
this.name = "InvalidPairingPayloadError";
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
function normalisePublicKey(input) {
|
|
53
|
-
if (typeof input !== "string" || !/^0x[0-9a-fA-F]+$/.test(input)) {
|
|
54
|
-
throw new InvalidPairingPayloadError("That device key is not valid.");
|
|
55
|
-
}
|
|
56
|
-
const value = BigInt(input);
|
|
57
|
-
if (value === 0n || value >= STARK_PRIME) {
|
|
58
|
-
throw new InvalidPairingPayloadError("That device key is not valid.");
|
|
59
|
-
}
|
|
60
|
-
return `0x${value.toString(16)}`;
|
|
61
|
-
}
|
|
62
|
-
function sanitiseLabel(input) {
|
|
63
|
-
const raw = typeof input === "string" ? input : "";
|
|
64
|
-
return raw.replace(/\s+/g, " ").trim().slice(0, LABEL_MAX);
|
|
65
|
-
}
|
|
66
|
-
function encodePairingPayload(payload) {
|
|
67
|
-
return JSON.stringify({
|
|
68
|
-
scheme: SCHEME,
|
|
69
|
-
version: VERSION,
|
|
70
|
-
publicKey: normalisePublicKey(payload.publicKey),
|
|
71
|
-
label: sanitiseLabel(payload.label)
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
function parsePairingPayload(encoded) {
|
|
75
|
-
let data;
|
|
76
|
-
try {
|
|
77
|
-
data = JSON.parse(encoded);
|
|
78
|
-
} catch {
|
|
79
|
-
throw new InvalidPairingPayloadError();
|
|
80
|
-
}
|
|
81
|
-
if (data === null || typeof data !== "object") throw new InvalidPairingPayloadError();
|
|
82
|
-
if (data.scheme !== SCHEME || data.version !== VERSION) throw new InvalidPairingPayloadError();
|
|
83
|
-
return {
|
|
84
|
-
publicKey: normalisePublicKey(data.publicKey),
|
|
85
|
-
label: sanitiseLabel(data.label)
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function parseAccountAddress(input) {
|
|
89
|
-
const trimmed = typeof input === "string" ? input.trim() : "";
|
|
90
|
-
if (!/^0x[0-9a-fA-F]{50,64}$/.test(trimmed)) {
|
|
91
|
-
throw new InvalidPairingPayloadError("That does not look like an account address.");
|
|
92
|
-
}
|
|
93
|
-
if (BigInt(trimmed) === 0n) {
|
|
94
|
-
throw new InvalidPairingPayloadError("That does not look like an account address.");
|
|
95
|
-
}
|
|
96
|
-
return trimmed;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// src/chains.ts
|
|
100
|
-
var COORDINATES = {
|
|
101
|
-
STARKNET: {
|
|
102
|
-
rpcUrl: "https://rpc.starknet.lava.build",
|
|
103
|
-
marketplace721: "0x03eda9a2b6ad90845a43591bac8083ebaf677d51fdf20f503b2c01889e3131fc",
|
|
104
|
-
marketplace721ClassHash: "0x0700d9230d07e5203e27778c0dc70f9134d2b25bf319f7cf8348dc66a6923e90",
|
|
105
|
-
marketplace721StartBlock: 11198146,
|
|
106
|
-
marketplace1155: "0x07c4ce1c19ea48cc11135ed22b19ff745f5aec508c3828593002e4f76fdb1b38",
|
|
107
|
-
marketplace1155ClassHash: "0x0242f5c388da7cee2d99e2a69453c8159bf927fbec4e797a3cfdcbbcb5b68328",
|
|
108
|
-
marketplace1155StartBlock: 11198267,
|
|
109
|
-
collection721: "0x0225c3ae09506b8d97adc39649ca740dad5aac195b7f5f0441cc1852947acaea",
|
|
110
|
-
collection721StartBlock: 11198496,
|
|
111
|
-
dataTokenization721: "0x07421b4442f7f2052c65408fb3561484154cf8175a0bbb41e3cd38d9087af6d2",
|
|
112
|
-
dataTokenization721StartBlock: 14670294,
|
|
113
|
-
ipNftClassHash: "0x012d3ae40ba35c7e2be0946532dac60e48932447912fdf96b674da67c029b9cc",
|
|
114
|
-
ipCollectionClassHash: "0x022155a1a130a40e57aac4b89c07fab3f616bc351b1270fc40f756b963afe8b4",
|
|
115
|
-
collection1155: "0x015368976d46fae5bfa1c58600f641d5aa5dbbf53ebc6b78aa3922194aad3551",
|
|
116
|
-
collection1155FactoryClassHash: "0x04eb6b419770f13bd191f120b9fc9ee624c0613ad4490062d293ca2016b3b1d2",
|
|
117
|
-
collection1155ClassHash: "0x06cf3f5a2322dac35e07a6064a5b8802f19fda8aa3f4726f0cb7bc05dea1bd78",
|
|
118
|
-
collection1155StartBlock: 11199527,
|
|
119
|
-
popFactory: "0x00b32c34b427d8f346b5843ada6a37bd3368d879fc752cd52b68a87287f60111",
|
|
120
|
-
popCollectionClassHash: "0x077c421686f10851872561953ea16898d933364b7f8937a5d7e2b1ba0a36263f",
|
|
121
|
-
dropFactory: "0x03587f42e29daee1b193f6cf83bf8627908ed6632d0d83fcb26225c50547d800",
|
|
122
|
-
dropCollectionClassHash: "0x00092e72cdb63067521e803aaf7d4101c3e3ce026ae6bc045ec4228027e58282",
|
|
123
|
-
nftComments: "0x02cdac70c94447189af0389dfea63f4d5e4154ea8a563de288a5ab1c39e37843",
|
|
124
|
-
creatorCoinFactory: "0x50fa807b5274079fb19374673d7bab6d2dc3af7e1032ea43eb6e44bcbde4c3c",
|
|
125
|
-
creatorCoinEkuboLauncher: "0x4f7fceb5ac10f12f9544a09580592e5bdf1b7f04f48765eecf12286d8ccb7b4",
|
|
126
|
-
creatorCoinClassHash: "0x743e4c8a5b96bb83bbf4af04edbbb482d5ece89eed9b729a79fb7df0cd0b6b6",
|
|
127
|
-
creatorCoinFactoryClassHash: "0x51765926b1344c9a20b8cd4b5abe7b7d47375ae97cf6804db3ea5d4b05a9b55",
|
|
128
|
-
creatorCoinStartBlock: 10474544,
|
|
129
|
-
ekuboCore: "0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b",
|
|
130
|
-
ipTicketsFactory: "0x0767bf5b57e1f812463159b5ed683183e1b0c3f942b74871b5c6cd6a93c15e99",
|
|
131
|
-
ipTicketCollectionClassHash: "0x0449e8eb7c117740d07cb8e0157d32c8ba3d19d1cfd2784ed5e139f5a1e04acc",
|
|
132
|
-
ipTicketsFactoryClassHash: "0x04a739ac3a673ebd0db96bb24475600797c3ed34827e79517f9b2b1640276e6a",
|
|
133
|
-
ipTicketsStartBlock: 11933694,
|
|
134
|
-
ipClubFactory: "0x06a0b0be16d70c78f2e18119dbf90e5911cbfd5d8d484bc555dc61d96f56a2b9",
|
|
135
|
-
ipClubFactoryClassHash: "0x05d9d431bd3532b1fa4d5bab572f49c5ad8034ee3cc83951aa41ae82c9cad266",
|
|
136
|
-
ipClubCollectionClassHash: "0x05b8477c72e6bf0cf64967d71155021fd4d77d9a57e8805c6b40709121c002c5",
|
|
137
|
-
ipClubFactoryStartBlock: 11928775,
|
|
138
|
-
ipSponsorship: "0x03729ebe0fedf29ec97fca34db09174772af7f870af26a26e024a61040143e5c",
|
|
139
|
-
ipSponsorshipClassHash: "0x0626daac2ed7e2bf630ef5b10104b3202db1559216c0c1a504c0e99be2fbfec3",
|
|
140
|
-
ipSponsorshipStartBlock: 11896456,
|
|
141
|
-
mediaWalletClassHash: "0x014b210c7d47392691144bafecdca3c6c7791cc295ea305988da0a724c05ac31",
|
|
142
|
-
genesisMintLaunch: "0x06ed61abba98a44d45bed2c4b1a456df15053c3321cfd6e007afb33b7226c9f0",
|
|
143
|
-
genesisMintBR: "0x01f8b92e3b9e963b8eacb075207e2cc89d4614ff2ac6c2702c7ae10ad19a9db8",
|
|
144
|
-
genesisMintGlobal: "0x06ad4d55ed2d12ad5d6d55587d800874ef807b051bfefe13497e60ec5b019369"
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
function getCoordinates(chain) {
|
|
148
|
-
const c = COORDINATES[chain];
|
|
149
|
-
if (!c) throw new Error(`No coordinates configured for chain "${chain}"`);
|
|
150
|
-
return c;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// src/constants.ts
|
|
154
|
-
var SN = getCoordinates("STARKNET");
|
|
155
|
-
var STARKNET_MEDIAWALLET_CLASS_HASH = SN.mediaWalletClassHash;
|
|
156
|
-
|
|
157
|
-
// src/starknet/business-provisioning/account.ts
|
|
158
|
-
function ownerConstructorCalldata(ownerPubkey) {
|
|
159
|
-
return ["0x0", num.toHex(ownerPubkey), "0x1"];
|
|
160
|
-
}
|
|
161
|
-
function computeAccountAddress(ownerPubkey, salt = 0) {
|
|
162
|
-
return hash.calculateContractAddressFromHash(
|
|
163
|
-
num.toHex(salt),
|
|
164
|
-
STARKNET_MEDIAWALLET_CLASS_HASH,
|
|
165
|
-
ownerConstructorCalldata(ownerPubkey),
|
|
166
|
-
0
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// src/wallet/recovery-key.ts
|
|
171
|
-
function isRecoveryKeyForWallet(sealed) {
|
|
172
|
-
try {
|
|
173
|
-
return BigInt(computeAccountAddress(sealed.ownerPubKey, 0)) === BigInt(sealed.address);
|
|
174
|
-
} catch {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// src/wallet/guardian-status.ts
|
|
180
|
-
function describeGuardianStatus(guardians) {
|
|
181
|
-
if (guardians.length === 0) return { kind: "none" };
|
|
182
|
-
return { kind: "active", guardian: guardians[0] };
|
|
183
|
-
}
|
|
184
|
-
function describeRecoveryAction(escape) {
|
|
185
|
-
if (escape.escapeType !== "Owner") return "none";
|
|
186
|
-
if (escape.status === "Ready") return "complete";
|
|
187
|
-
if (escape.status === "Expired") return "start";
|
|
188
|
-
return "none";
|
|
189
|
-
}
|
|
190
|
-
function normalizeAddress(chain, address) {
|
|
191
|
-
switch (chain) {
|
|
192
|
-
case "STARKNET":
|
|
193
|
-
return normalizeStarknet(address);
|
|
194
|
-
case "ETHEREUM":
|
|
195
|
-
case "BASE":
|
|
196
|
-
return normalizeEvm(address);
|
|
197
|
-
case "SOLANA":
|
|
198
|
-
return normalizeSolana(address);
|
|
199
|
-
case "STELLAR":
|
|
200
|
-
return normalizeStellar(address);
|
|
201
|
-
case "BITCOIN":
|
|
202
|
-
throw new Error("BITCOIN address normalization not implemented");
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
function normalizeStarknet(address) {
|
|
206
|
-
try {
|
|
207
|
-
const hex = BigInt(address).toString(16);
|
|
208
|
-
return "0x" + hex.padStart(64, "0").toLowerCase();
|
|
209
|
-
} catch {
|
|
210
|
-
throw new Error(`Invalid STARKNET address: "${address}"`);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
function normalizeEvm(address) {
|
|
214
|
-
const m = /^0x([0-9a-fA-F]{40})$/.exec(address);
|
|
215
|
-
if (!m) throw new Error(`Invalid ETHEREUM/BASE address: "${address}"`);
|
|
216
|
-
const lower = m[1].toLowerCase();
|
|
217
|
-
const hash3 = keccak_256(new TextEncoder().encode(lower));
|
|
218
|
-
let out = "0x";
|
|
219
|
-
for (let i = 0; i < 40; i++) {
|
|
220
|
-
const nibble = hash3[i >> 1] >> (i % 2 === 0 ? 4 : 0) & 15;
|
|
221
|
-
out += nibble >= 8 ? lower[i].toUpperCase() : lower[i];
|
|
222
|
-
}
|
|
223
|
-
return out;
|
|
224
|
-
}
|
|
225
|
-
function normalizeSolana(address) {
|
|
226
|
-
try {
|
|
227
|
-
const bytes = base58.decode(address);
|
|
228
|
-
if (bytes.length !== 32) throw new Error("not a 32-byte key");
|
|
229
|
-
return address;
|
|
230
|
-
} catch {
|
|
231
|
-
throw new Error(`Invalid SOLANA address: "${address}"`);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
var STELLAR_VERSION_BYTES = /* @__PURE__ */ new Set([6 << 3, 2 << 3]);
|
|
235
|
-
function normalizeStellar(address) {
|
|
236
|
-
const upper = address.toUpperCase();
|
|
237
|
-
if (!/^[GC][A-Z2-7]{55}$/.test(upper)) {
|
|
238
|
-
throw new Error(`Invalid STELLAR address: "${address}"`);
|
|
239
|
-
}
|
|
240
|
-
let decoded;
|
|
241
|
-
try {
|
|
242
|
-
decoded = base32.decode(upper);
|
|
243
|
-
} catch {
|
|
244
|
-
throw new Error(`Invalid STELLAR address: "${address}"`);
|
|
245
|
-
}
|
|
246
|
-
if (decoded.length !== 35 || !STELLAR_VERSION_BYTES.has(decoded[0])) {
|
|
247
|
-
throw new Error(`Invalid STELLAR address: "${address}"`);
|
|
248
|
-
}
|
|
249
|
-
const payload = decoded.subarray(0, 33);
|
|
250
|
-
const checksum = decoded[33] | decoded[34] << 8;
|
|
251
|
-
if (crc16xmodem(payload) !== checksum) {
|
|
252
|
-
throw new Error(`Invalid STELLAR address: "${address}"`);
|
|
253
|
-
}
|
|
254
|
-
return upper;
|
|
255
|
-
}
|
|
256
|
-
function crc16xmodem(bytes) {
|
|
257
|
-
let crc = 0;
|
|
258
|
-
for (const byte of bytes) {
|
|
259
|
-
crc ^= byte << 8;
|
|
260
|
-
for (let i = 0; i < 8; i++) {
|
|
261
|
-
crc = crc & 32768 ? (crc << 1 ^ 4129) & 65535 : crc << 1 & 65535;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return crc;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// src/wallet/addresses.ts
|
|
268
|
-
function normalizeWalletAddress(address) {
|
|
269
|
-
return normalizeAddress("STARKNET", address);
|
|
270
|
-
}
|
|
271
|
-
function isValidStarknetAddress(address) {
|
|
272
|
-
try {
|
|
273
|
-
validateAndParseAddress(address.trim());
|
|
274
|
-
return true;
|
|
275
|
-
} catch {
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
async function isDeployed(provider, address) {
|
|
280
|
-
try {
|
|
281
|
-
await provider.getClassHashAt(normalizeWalletAddress(address));
|
|
282
|
-
return true;
|
|
283
|
-
} catch {
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// src/wallet/self-fund-consent.ts
|
|
289
|
-
function createSelfFundConsent(estimateFee) {
|
|
290
|
-
let handler = null;
|
|
291
|
-
return {
|
|
292
|
-
registerHandler(next) {
|
|
293
|
-
handler = next;
|
|
294
|
-
},
|
|
295
|
-
async request({ address, calls }) {
|
|
296
|
-
if (!handler) return false;
|
|
297
|
-
const feeEstimate = address && calls ? estimateFee(address, calls).catch(() => null) : Promise.resolve(null);
|
|
298
|
-
return handler(feeEstimate);
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
async function deriveAesKey(prfSecret, hkdfInfo) {
|
|
303
|
-
const hkdf = await crypto.subtle.importKey("raw", prfSecret, "HKDF", false, ["deriveKey"]);
|
|
304
|
-
return crypto.subtle.deriveKey(
|
|
305
|
-
{ name: "HKDF", hash: "SHA-256", salt: new Uint8Array(0), info: hkdfInfo },
|
|
306
|
-
hkdf,
|
|
307
|
-
{ name: "AES-GCM", length: 256 },
|
|
308
|
-
false,
|
|
309
|
-
["encrypt", "decrypt"]
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
function generateStarkKeyPair() {
|
|
313
|
-
const privateKeyHex = "0x" + Array.from(ec.starkCurve.utils.randomPrivateKey()).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
314
|
-
return { privateKeyHex, publicKeyHex: ec.starkCurve.getStarkKey(privateKeyHex) };
|
|
315
|
-
}
|
|
316
|
-
var InvalidStarkPrivateKeyError = class extends Error {
|
|
317
|
-
constructor(reason) {
|
|
318
|
-
super(`Not a valid Starknet private key: ${reason}`);
|
|
319
|
-
this.name = "InvalidStarkPrivateKeyError";
|
|
320
|
-
}
|
|
321
|
-
};
|
|
322
|
-
function starkKeyPairFromPrivateKey(input) {
|
|
323
|
-
const trimmed = input.trim().replace(/\s+/g, "");
|
|
324
|
-
const body = trimmed.startsWith("0x") || trimmed.startsWith("0X") ? trimmed.slice(2) : trimmed;
|
|
325
|
-
if (body.length === 0) throw new InvalidStarkPrivateKeyError("it is empty");
|
|
326
|
-
if (!/^[0-9a-fA-F]+$/.test(body)) throw new InvalidStarkPrivateKeyError("it is not hexadecimal");
|
|
327
|
-
if (body.length > 64) throw new InvalidStarkPrivateKeyError("it is too long");
|
|
328
|
-
const value = BigInt("0x" + body);
|
|
329
|
-
if (value === 0n) throw new InvalidStarkPrivateKeyError("it is zero");
|
|
330
|
-
if (value >= ec.starkCurve.CURVE.n) throw new InvalidStarkPrivateKeyError("it is outside the curve order");
|
|
331
|
-
const privateKeyHex = "0x" + value.toString(16).padStart(64, "0");
|
|
332
|
-
return { privateKeyHex, publicKeyHex: ec.starkCurve.getStarkKey(privateKeyHex) };
|
|
333
|
-
}
|
|
334
|
-
async function sealPrivateKey(aesKey, iv, privateKeyHex) {
|
|
335
|
-
return crypto.subtle.encrypt(
|
|
336
|
-
{ name: "AES-GCM", iv },
|
|
337
|
-
aesKey,
|
|
338
|
-
new TextEncoder().encode(privateKeyHex)
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
async function unsealPrivateKey(aesKey, iv, ciphertext) {
|
|
342
|
-
const buf = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, aesKey, ciphertext);
|
|
343
|
-
return new TextDecoder().decode(buf);
|
|
344
|
-
}
|
|
345
|
-
function signWithPrivateKey(privateKeyHex, msgHash) {
|
|
346
|
-
const sig = ec.starkCurve.sign(msgHash, privateKeyHex);
|
|
347
|
-
return [num.toHex(sig.r), num.toHex(sig.s)];
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// src/wallet/passkey.ts
|
|
351
|
-
var PasskeyCancelledError = class extends Error {
|
|
352
|
-
constructor(message = "Passkey prompt was cancelled.") {
|
|
353
|
-
super(message);
|
|
354
|
-
this.name = "PasskeyCancelledError";
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
var encodeBase64 = (buf) => {
|
|
358
|
-
const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
|
|
359
|
-
let binary = "";
|
|
360
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
361
|
-
return btoa(binary);
|
|
362
|
-
};
|
|
363
|
-
var decodeBase64 = (value) => {
|
|
364
|
-
const binary = atob(value);
|
|
365
|
-
const bytes = new Uint8Array(binary.length);
|
|
366
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
367
|
-
return bytes;
|
|
368
|
-
};
|
|
369
|
-
function isPasskeyCancellation(err) {
|
|
370
|
-
const name = err?.name;
|
|
371
|
-
return name === "NotAllowedError" || name === "AbortError";
|
|
372
|
-
}
|
|
373
|
-
function createPasskeyOwner(config) {
|
|
374
|
-
const randomBytes = config.randomBytes ?? ((length) => crypto.getRandomValues(new Uint8Array(length)));
|
|
375
|
-
const credentialsApi = () => {
|
|
376
|
-
const api = config.credentials ?? (typeof navigator === "undefined" ? void 0 : navigator.credentials);
|
|
377
|
-
if (!api) throw new Error("Passkeys are only available in a browser.");
|
|
378
|
-
return api;
|
|
379
|
-
};
|
|
380
|
-
const prfUnsupportedMessage = () => {
|
|
381
|
-
const isBrave = typeof navigator !== "undefined" && "brave" in navigator;
|
|
382
|
-
const cause = isBrave ? "Brave doesn't currently support the WebAuthn PRF extension." : "This browser didn't return a passkey PRF secret.";
|
|
383
|
-
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.`;
|
|
384
|
-
};
|
|
385
|
-
async function registerPasskey() {
|
|
386
|
-
let credential;
|
|
387
|
-
try {
|
|
388
|
-
credential = await credentialsApi().create({
|
|
389
|
-
publicKey: {
|
|
390
|
-
challenge: randomBytes(32),
|
|
391
|
-
rp: { name: config.relyingPartyName, id: config.relyingPartyId() },
|
|
392
|
-
user: await config.passkeyUser(),
|
|
393
|
-
excludeCredentials: config.knownCredentials(),
|
|
394
|
-
pubKeyCredParams: [
|
|
395
|
-
{ type: "public-key", alg: -7 },
|
|
396
|
-
{ type: "public-key", alg: -257 }
|
|
397
|
-
],
|
|
398
|
-
authenticatorSelection: {
|
|
399
|
-
residentKey: "required",
|
|
400
|
-
userVerification: "required",
|
|
401
|
-
authenticatorAttachment: "platform"
|
|
402
|
-
},
|
|
403
|
-
extensions: { prf: { eval: { first: config.prfSalt } } }
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
} catch (err) {
|
|
407
|
-
if (isPasskeyCancellation(err)) throw new PasskeyCancelledError();
|
|
408
|
-
throw err;
|
|
409
|
-
}
|
|
410
|
-
const prf = credential.getClientExtensionResults().prf;
|
|
411
|
-
return { credentialId: encodeBase64(credential.rawId), prfFirst: prf?.results?.first ?? null };
|
|
412
|
-
}
|
|
413
|
-
async function prfSecret(credentialId) {
|
|
414
|
-
let assertion;
|
|
415
|
-
try {
|
|
416
|
-
assertion = await credentialsApi().get({
|
|
417
|
-
publicKey: {
|
|
418
|
-
challenge: randomBytes(32),
|
|
419
|
-
rpId: config.relyingPartyId(),
|
|
420
|
-
allowCredentials: [{ type: "public-key", id: decodeBase64(credentialId) }],
|
|
421
|
-
userVerification: "required",
|
|
422
|
-
extensions: { prf: { eval: { first: config.prfSalt } } }
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
} catch (err) {
|
|
426
|
-
if (isPasskeyCancellation(err)) throw new PasskeyCancelledError();
|
|
427
|
-
throw err;
|
|
428
|
-
}
|
|
429
|
-
const result = assertion.getClientExtensionResults().prf?.results?.first;
|
|
430
|
-
if (!result) throw new Error("Passkey PRF unavailable on this device/browser.");
|
|
431
|
-
return new Uint8Array(result);
|
|
432
|
-
}
|
|
433
|
-
async function secretFromRegistration(registration) {
|
|
434
|
-
if (registration.prfFirst) return new Uint8Array(registration.prfFirst);
|
|
435
|
-
try {
|
|
436
|
-
return await prfSecret(registration.credentialId);
|
|
437
|
-
} catch {
|
|
438
|
-
throw new Error(prfUnsupportedMessage());
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
async function seal(secret, privateKeyHex) {
|
|
442
|
-
const aes = await deriveAesKey(secret, config.hkdfInfo);
|
|
443
|
-
const iv = randomBytes(12);
|
|
444
|
-
const ciphertext = await sealPrivateKey(aes, iv, privateKeyHex);
|
|
445
|
-
return { iv: encodeBase64(iv), ciphertext: encodeBase64(ciphertext) };
|
|
446
|
-
}
|
|
447
|
-
return {
|
|
448
|
-
async createOwnerKey() {
|
|
449
|
-
const registration = await registerPasskey();
|
|
450
|
-
const secret = await secretFromRegistration(registration);
|
|
451
|
-
const { privateKeyHex, publicKeyHex } = generateStarkKeyPair();
|
|
452
|
-
const { iv, ciphertext } = await seal(secret, privateKeyHex);
|
|
453
|
-
return {
|
|
454
|
-
sealed: {
|
|
455
|
-
credentialId: registration.credentialId,
|
|
456
|
-
ownerPubKey: publicKeyHex,
|
|
457
|
-
address: computeAccountAddress(publicKeyHex, 0),
|
|
458
|
-
iv,
|
|
459
|
-
ciphertext
|
|
460
|
-
},
|
|
461
|
-
privateKeyHex
|
|
462
|
-
};
|
|
463
|
-
},
|
|
464
|
-
async unlockOwnerKey(sealed) {
|
|
465
|
-
const secret = await prfSecret(sealed.credentialId);
|
|
466
|
-
const aes = await deriveAesKey(secret, config.hkdfInfo);
|
|
467
|
-
return unsealPrivateKey(aes, decodeBase64(sealed.iv), decodeBase64(sealed.ciphertext));
|
|
468
|
-
},
|
|
469
|
-
async sealImportedOwnerKey(privateKeyInput) {
|
|
470
|
-
const { privateKeyHex, publicKeyHex } = starkKeyPairFromPrivateKey(privateKeyInput);
|
|
471
|
-
const registration = await registerPasskey();
|
|
472
|
-
const secret = await secretFromRegistration(registration);
|
|
473
|
-
const { iv, ciphertext } = await seal(secret, privateKeyHex);
|
|
474
|
-
return {
|
|
475
|
-
credentialId: registration.credentialId,
|
|
476
|
-
ownerPubKey: publicKeyHex,
|
|
477
|
-
address: computeAccountAddress(publicKeyHex, 0),
|
|
478
|
-
iv,
|
|
479
|
-
ciphertext
|
|
480
|
-
};
|
|
481
|
-
},
|
|
482
|
-
walletAddressForPrivateKey(privateKeyInput) {
|
|
483
|
-
return computeAccountAddress(starkKeyPairFromPrivateKey(privateKeyInput).publicKeyHex, 0);
|
|
484
|
-
}
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// src/starknet/services/sponsoredExecutor.ts
|
|
489
|
-
var SponsoredCallRejectedError = class extends Error {
|
|
490
|
-
};
|
|
491
|
-
var USER_MAY_PAY = /* @__PURE__ */ new Set(["sponsor_unavailable", "credits_exhausted"]);
|
|
492
|
-
function userMayPayInstead(code, status, stage) {
|
|
493
|
-
if (code) return USER_MAY_PAY.has(code);
|
|
494
|
-
return stage === "build" ? status >= 500 : status === 503;
|
|
495
|
-
}
|
|
496
|
-
async function failureOf(res, fallback) {
|
|
497
|
-
const body = await res.json().catch(() => null);
|
|
498
|
-
return { reason: body?.error || fallback, code: typeof body?.code === "string" ? body.code : void 0 };
|
|
499
|
-
}
|
|
500
|
-
async function executeSponsored(config, signer, calls) {
|
|
501
|
-
const doFetch = config.fetchImpl ?? fetch;
|
|
502
|
-
const base = config.proxyUrl.replace(/\/$/, "");
|
|
503
|
-
const buildRes = await doFetch(`${base}/build`, {
|
|
504
|
-
method: "POST",
|
|
505
|
-
headers: { "Content-Type": "application/json" },
|
|
506
|
-
body: JSON.stringify({ userAddress: signer.address, calls })
|
|
507
|
-
});
|
|
508
|
-
if (!buildRes.ok) {
|
|
509
|
-
const { reason, code } = await failureOf(buildRes, "We couldn't prepare this transaction.");
|
|
510
|
-
if (userMayPayInstead(code, buildRes.status, "build")) return { status: "unavailable", reason };
|
|
511
|
-
throw new SponsoredCallRejectedError(reason);
|
|
512
|
-
}
|
|
513
|
-
const { typedData } = await buildRes.json();
|
|
514
|
-
const signature = await signer.signTypedData(typedData);
|
|
515
|
-
const executeRes = await doFetch(`${base}/execute`, {
|
|
516
|
-
method: "POST",
|
|
517
|
-
headers: { "Content-Type": "application/json" },
|
|
518
|
-
body: JSON.stringify({ userAddress: signer.address, typedData, signature, calls })
|
|
519
|
-
});
|
|
520
|
-
if (!executeRes.ok) {
|
|
521
|
-
const { reason, code } = await failureOf(executeRes, "We couldn't submit this transaction.");
|
|
522
|
-
if (userMayPayInstead(code, executeRes.status, "execute")) {
|
|
523
|
-
return { status: "unavailable", reason };
|
|
524
|
-
}
|
|
525
|
-
throw new SponsoredCallRejectedError(reason);
|
|
526
|
-
}
|
|
527
|
-
const { transactionHash } = await executeRes.json();
|
|
528
|
-
return { status: "sponsored", transactionHash };
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// src/wallet/executors.ts
|
|
532
|
-
function accountFor(provider, address, privateKeyHex) {
|
|
533
|
-
return new Account({ provider, address, signer: privateKeyHex, cairoVersion: "1" });
|
|
534
|
-
}
|
|
535
|
-
async function estimateSelfFundedFee(provider, address, calls) {
|
|
536
|
-
const account = new Account({ provider, address, signer: "0x1", cairoVersion: "1" });
|
|
537
|
-
const estimate = await account.estimateInvokeFee(calls);
|
|
538
|
-
return { feeRaw: estimate.overall_fee, unit: estimate.unit };
|
|
539
|
-
}
|
|
540
|
-
function selfFundedExecutor(deps) {
|
|
541
|
-
return {
|
|
542
|
-
async execute({ userAddress, privateKeyHex, calls }) {
|
|
543
|
-
const account = accountFor(deps.provider(), userAddress, privateKeyHex);
|
|
544
|
-
const { transaction_hash } = await account.execute(calls);
|
|
545
|
-
return { transactionHash: transaction_hash };
|
|
546
|
-
}
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
function sponsoredExecutor(deps) {
|
|
550
|
-
const fallback = deps.fallback ?? selfFundedExecutor(deps);
|
|
551
|
-
return {
|
|
552
|
-
async execute(input) {
|
|
553
|
-
const { userAddress, privateKeyHex, calls } = input;
|
|
554
|
-
const result = await executeSponsored(
|
|
555
|
-
{ proxyUrl: deps.proxyUrl, fetchImpl: deps.fetchImpl },
|
|
556
|
-
{
|
|
557
|
-
address: userAddress,
|
|
558
|
-
signTypedData: async (data) => signWithPrivateKey(privateKeyHex, typedData.getMessageHash(data, userAddress))
|
|
559
|
-
},
|
|
560
|
-
calls
|
|
561
|
-
);
|
|
562
|
-
if (result.status === "sponsored") return { transactionHash: result.transactionHash };
|
|
563
|
-
const consented = await deps.consent.request({ address: userAddress, calls });
|
|
564
|
-
if (!consented) throw new SponsoredCallRejectedError(result.reason);
|
|
565
|
-
return fallback.execute(input);
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
var norm = (address) => normalizeAddress("STARKNET", address);
|
|
570
|
-
var SIGNER_TYPE_NAMES = ["Starknet", "Secp256k1", "Secp256r1"];
|
|
571
|
-
function encodeFeltArray(items) {
|
|
572
|
-
return [num.toHex(items.length), ...items];
|
|
573
|
-
}
|
|
574
|
-
function encodeStarknetSigner(pubkey) {
|
|
575
|
-
return ["0x0", num.toHex(pubkey)];
|
|
576
|
-
}
|
|
577
|
-
function encodeStarknetSignerArray(pubkeys) {
|
|
578
|
-
return [num.toHex(pubkeys.length), ...pubkeys.flatMap(encodeStarknetSigner)];
|
|
579
|
-
}
|
|
580
|
-
function buildSetFirstGuardianCall(address, guardianPubkey) {
|
|
581
|
-
return {
|
|
582
|
-
contractAddress: norm(address),
|
|
583
|
-
entrypoint: "change_guardians",
|
|
584
|
-
calldata: [...encodeFeltArray([]), ...encodeStarknetSignerArray([guardianPubkey])]
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
function buildTriggerEscapeOwnerCall(targetAddress, newOwnerPubkey) {
|
|
588
|
-
return {
|
|
589
|
-
contractAddress: norm(targetAddress),
|
|
590
|
-
entrypoint: "trigger_escape_owner",
|
|
591
|
-
calldata: encodeStarknetSigner(newOwnerPubkey)
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
function buildCompleteEscapeOwnerCall(targetAddress) {
|
|
595
|
-
return { contractAddress: norm(targetAddress), entrypoint: "escape_owner", calldata: [] };
|
|
596
|
-
}
|
|
597
|
-
function buildCancelEscapeCall(address) {
|
|
598
|
-
return { contractAddress: norm(address), entrypoint: "cancel_escape", calldata: [] };
|
|
599
|
-
}
|
|
600
|
-
function decodeGuardiansInfo(res) {
|
|
601
|
-
const len = Number(res[0]);
|
|
602
|
-
const out = [];
|
|
603
|
-
for (let i = 0; i < len; i++) {
|
|
604
|
-
const base = 1 + i * 3;
|
|
605
|
-
out.push({
|
|
606
|
-
type: SIGNER_TYPE_NAMES[Number(res[base])] ?? "Starknet",
|
|
607
|
-
guid: res[base + 1],
|
|
608
|
-
storedValue: res[base + 2]
|
|
609
|
-
});
|
|
610
|
-
}
|
|
611
|
-
return out;
|
|
612
|
-
}
|
|
613
|
-
var ESCAPE_TYPE_NAMES = ["None", "Guardian", "Owner"];
|
|
614
|
-
var ESCAPE_STATUS_NAMES = ["None", "NotReady", "Ready", "Expired"];
|
|
615
|
-
function decodeEscapeAndStatus(res) {
|
|
616
|
-
const readyAt = Number(res[0]);
|
|
617
|
-
const escapeType = ESCAPE_TYPE_NAMES[Number(res[1])] ?? "None";
|
|
618
|
-
const optionTag = Number(res[2]);
|
|
619
|
-
const statusIndex = optionTag === 0 ? 5 : 3;
|
|
620
|
-
const status = ESCAPE_STATUS_NAMES[Number(res[statusIndex])] ?? "None";
|
|
621
|
-
return { readyAt, escapeType, status };
|
|
622
|
-
}
|
|
623
|
-
async function getGuardians(provider, address) {
|
|
624
|
-
const res = await provider.callContract({
|
|
625
|
-
contractAddress: norm(address),
|
|
626
|
-
entrypoint: "get_guardians_info",
|
|
627
|
-
calldata: []
|
|
628
|
-
});
|
|
629
|
-
return decodeGuardiansInfo(res);
|
|
630
|
-
}
|
|
631
|
-
async function getOwners(provider, address) {
|
|
632
|
-
const res = await provider.callContract({
|
|
633
|
-
contractAddress: norm(address),
|
|
634
|
-
entrypoint: "get_owners_info",
|
|
635
|
-
calldata: []
|
|
636
|
-
});
|
|
637
|
-
return decodeGuardiansInfo(res);
|
|
638
|
-
}
|
|
639
|
-
async function getEscape(provider, address) {
|
|
640
|
-
const res = await provider.callContract({
|
|
641
|
-
contractAddress: norm(address),
|
|
642
|
-
entrypoint: "get_escape_and_status",
|
|
643
|
-
calldata: []
|
|
644
|
-
});
|
|
645
|
-
return decodeEscapeAndStatus(res);
|
|
646
|
-
}
|
|
647
|
-
async function getEscapeSecurityPeriod(provider, address) {
|
|
648
|
-
const res = await provider.callContract({
|
|
649
|
-
contractAddress: norm(address),
|
|
650
|
-
entrypoint: "get_escape_security_period",
|
|
651
|
-
calldata: []
|
|
652
|
-
});
|
|
653
|
-
return Number(res[0]);
|
|
654
|
-
}
|
|
655
|
-
var STARKNET_SIGNER_TYPE = "0x537461726b6e6574205369676e6572";
|
|
656
|
-
var OPTION_NONE = "0x1";
|
|
657
|
-
var SIGNER_STARKNET = "0x0";
|
|
658
|
-
function computeOwnerGuid(ownerPubkey) {
|
|
659
|
-
return hash.computePoseidonHash(STARKNET_SIGNER_TYPE, num.toHex(ownerPubkey));
|
|
660
|
-
}
|
|
661
|
-
function changeOwners(accountAddress, guidsToRemove, pubkeysToAdd, ownerAlive) {
|
|
662
|
-
return {
|
|
663
|
-
contractAddress: accountAddress,
|
|
664
|
-
entrypoint: "change_owners",
|
|
665
|
-
calldata: [
|
|
666
|
-
num.toHex(guidsToRemove.length),
|
|
667
|
-
...guidsToRemove,
|
|
668
|
-
num.toHex(pubkeysToAdd.length),
|
|
669
|
-
...pubkeysToAdd.flatMap((p) => [SIGNER_STARKNET, num.toHex(p)]),
|
|
670
|
-
...[OPTION_NONE]
|
|
671
|
-
]
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
function buildAddOwnerCall(accountAddress, addOwnerPubkey) {
|
|
675
|
-
return changeOwners(accountAddress, [], [addOwnerPubkey]);
|
|
676
|
-
}
|
|
677
|
-
function buildRemoveOwnerByGuidCall(accountAddress, ownerGuid) {
|
|
678
|
-
return changeOwners(accountAddress, [num.toHex(ownerGuid)], []);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
// src/wallet/client.ts
|
|
682
|
-
function describeDevices(owners, thisDevicePubkey) {
|
|
683
|
-
const mine = computeOwnerGuid(thisDevicePubkey);
|
|
684
|
-
return owners.map((owner) => ({
|
|
685
|
-
guid: owner.guid,
|
|
686
|
-
type: owner.type,
|
|
687
|
-
isThisDevice: BigInt(owner.guid) === BigInt(mine)
|
|
688
|
-
}));
|
|
689
|
-
}
|
|
690
|
-
function canRemoveDevice(devices, guid) {
|
|
691
|
-
if (devices.length <= 1) return false;
|
|
692
|
-
return devices.some((device) => BigInt(device.guid) === BigInt(guid));
|
|
693
|
-
}
|
|
694
|
-
function createMediaWallet(config) {
|
|
695
|
-
const ttl = config.unlockTtlMs ?? 2e4;
|
|
696
|
-
const unlockCache = /* @__PURE__ */ new Map();
|
|
697
|
-
const lock = (address) => {
|
|
698
|
-
const entry = unlockCache.get(address);
|
|
699
|
-
if (!entry) return;
|
|
700
|
-
clearTimeout(entry.timer);
|
|
701
|
-
unlockCache.delete(address);
|
|
702
|
-
};
|
|
703
|
-
const unlockOnce = (sealed) => {
|
|
704
|
-
const existing = unlockCache.get(sealed.address);
|
|
705
|
-
if (existing) return existing.promise;
|
|
706
|
-
const promise = config.passkey.unlockOwnerKey(sealed).catch((err) => {
|
|
707
|
-
lock(sealed.address);
|
|
708
|
-
throw err;
|
|
709
|
-
});
|
|
710
|
-
const timer = setTimeout(() => lock(sealed.address), ttl);
|
|
711
|
-
unlockCache.set(sealed.address, { promise, timer });
|
|
712
|
-
return promise;
|
|
713
|
-
};
|
|
714
|
-
const run = async (sealed, calls, userAddress) => {
|
|
715
|
-
const privateKeyHex = await unlockOnce(sealed);
|
|
716
|
-
return config.executor.execute({
|
|
717
|
-
userAddress: userAddress ?? sealed.address,
|
|
718
|
-
privateKeyHex,
|
|
719
|
-
calls
|
|
720
|
-
});
|
|
721
|
-
};
|
|
722
|
-
return {
|
|
723
|
-
store: config.store,
|
|
724
|
-
passkey: config.passkey,
|
|
725
|
-
lock,
|
|
726
|
-
signerFor(sealed) {
|
|
727
|
-
return {
|
|
728
|
-
address: sealed.address,
|
|
729
|
-
signTypedData: async (data) => {
|
|
730
|
-
const privateKeyHex = await unlockOnce(sealed);
|
|
731
|
-
return signWithPrivateKey(privateKeyHex, typedData.getMessageHash(data, sealed.address));
|
|
732
|
-
},
|
|
733
|
-
execute: async (calls) => {
|
|
734
|
-
const { transactionHash } = await run(sealed, calls);
|
|
735
|
-
return { txHash: transactionHash };
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
|
-
},
|
|
739
|
-
run,
|
|
740
|
-
getGuardians: (address) => getGuardians(config.provider(), address),
|
|
741
|
-
getEscape: (address) => getEscape(config.provider(), address),
|
|
742
|
-
getEscapeSecurityPeriod: (address) => getEscapeSecurityPeriod(config.provider(), address),
|
|
743
|
-
getOwners: (address) => getOwners(config.provider(), address),
|
|
744
|
-
async isOwnerOf(accountAddress, devicePubkey) {
|
|
745
|
-
const owners = await getOwners(config.provider(), accountAddress);
|
|
746
|
-
const guid = BigInt(computeOwnerGuid(devicePubkey));
|
|
747
|
-
return owners.some((owner) => BigInt(owner.guid) === guid);
|
|
748
|
-
},
|
|
749
|
-
async setFirstGuardian(sealed, guardianPubkey) {
|
|
750
|
-
const { transactionHash } = await run(sealed, [buildSetFirstGuardianCall(sealed.address, guardianPubkey)]);
|
|
751
|
-
return transactionHash;
|
|
752
|
-
},
|
|
753
|
-
async triggerEscapeOwner(guardianSealed, targetAddress, newOwnerPubkey) {
|
|
754
|
-
const { transactionHash } = await run(
|
|
755
|
-
guardianSealed,
|
|
756
|
-
[buildTriggerEscapeOwnerCall(targetAddress, newOwnerPubkey)],
|
|
757
|
-
normalizeWalletAddress(targetAddress)
|
|
758
|
-
);
|
|
759
|
-
return transactionHash;
|
|
760
|
-
},
|
|
761
|
-
async completeEscapeOwner(guardianSealed, targetAddress) {
|
|
762
|
-
const { transactionHash } = await run(
|
|
763
|
-
guardianSealed,
|
|
764
|
-
[buildCompleteEscapeOwnerCall(targetAddress)],
|
|
765
|
-
normalizeWalletAddress(targetAddress)
|
|
766
|
-
);
|
|
767
|
-
return transactionHash;
|
|
768
|
-
},
|
|
769
|
-
async cancelEscape(sealed) {
|
|
770
|
-
const { transactionHash } = await run(sealed, [buildCancelEscapeCall(sealed.address)]);
|
|
771
|
-
return transactionHash;
|
|
772
|
-
},
|
|
773
|
-
async addDevice(sealed, devicePubkey) {
|
|
774
|
-
const { transactionHash } = await run(sealed, [buildAddOwnerCall(sealed.address, devicePubkey)]);
|
|
775
|
-
return transactionHash;
|
|
776
|
-
},
|
|
777
|
-
async removeDevice(sealed, ownerGuid) {
|
|
778
|
-
const { transactionHash } = await run(sealed, [buildRemoveOwnerByGuidCall(sealed.address, ownerGuid)]);
|
|
779
|
-
return transactionHash;
|
|
780
|
-
}
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
export { InvalidPairingPayloadError, PasskeyCancelledError, accountFor, canRemoveDevice, createMediaWallet, createOwnerStore, createPasskeyOwner, createSelfFundConsent, describeDevices, describeGuardianStatus, describeRecoveryAction, encodePairingPayload, estimateSelfFundedFee, isDeployed, isRecoveryKeyForWallet, isValidStarknetAddress, normalizeWalletAddress, parseAccountAddress, parsePairingPayload, selfFundedExecutor, sponsoredExecutor };
|
|
785
|
-
//# sourceMappingURL=index.js.map
|
|
786
|
-
//# sourceMappingURL=index.js.map
|