@mysten-incubation/dev-wallet 0.0.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/README.md +250 -0
- package/dist/_virtual/_@oxc-project_runtime@0.107.0/helpers/decorate.mjs +10 -0
- package/dist/adapters/base-adapter.d.mts +33 -0
- package/dist/adapters/base-adapter.d.mts.map +1 -0
- package/dist/adapters/base-adapter.mjs +77 -0
- package/dist/adapters/base-adapter.mjs.map +1 -0
- package/dist/adapters/browser.d.mts +8 -0
- package/dist/adapters/browser.mjs +8 -0
- package/dist/adapters/build-managed-account.d.mts +12 -0
- package/dist/adapters/build-managed-account.d.mts.map +1 -0
- package/dist/adapters/build-managed-account.mjs +30 -0
- package/dist/adapters/build-managed-account.mjs.map +1 -0
- package/dist/adapters/idb-store.mjs +73 -0
- package/dist/adapters/idb-store.mjs.map +1 -0
- package/dist/adapters/in-memory-adapter.d.mts +16 -0
- package/dist/adapters/in-memory-adapter.d.mts.map +1 -0
- package/dist/adapters/in-memory-adapter.mjs +44 -0
- package/dist/adapters/in-memory-adapter.mjs.map +1 -0
- package/dist/adapters/passkey-adapter.d.mts +31 -0
- package/dist/adapters/passkey-adapter.d.mts.map +1 -0
- package/dist/adapters/passkey-adapter.mjs +87 -0
- package/dist/adapters/passkey-adapter.mjs.map +1 -0
- package/dist/adapters/remote-cli-adapter.d.mts +65 -0
- package/dist/adapters/remote-cli-adapter.d.mts.map +1 -0
- package/dist/adapters/remote-cli-adapter.mjs +299 -0
- package/dist/adapters/remote-cli-adapter.mjs.map +1 -0
- package/dist/adapters/webcrypto-adapter.d.mts +20 -0
- package/dist/adapters/webcrypto-adapter.d.mts.map +1 -0
- package/dist/adapters/webcrypto-adapter.mjs +68 -0
- package/dist/adapters/webcrypto-adapter.mjs.map +1 -0
- package/dist/bin/cli.d.mts +1 -0
- package/dist/bin/cli.mjs +183 -0
- package/dist/bin/cli.mjs.map +1 -0
- package/dist/client/dev-wallet-client.d.mts +57 -0
- package/dist/client/dev-wallet-client.d.mts.map +1 -0
- package/dist/client/dev-wallet-client.mjs +223 -0
- package/dist/client/dev-wallet-client.mjs.map +1 -0
- package/dist/client/index.d.mts +3 -0
- package/dist/client/index.mjs +4 -0
- package/dist/client/request-handler.d.mts +42 -0
- package/dist/client/request-handler.d.mts.map +1 -0
- package/dist/client/request-handler.mjs +115 -0
- package/dist/client/request-handler.mjs.map +1 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +4 -0
- package/dist/react/components.d.mts +32 -0
- package/dist/react/components.d.mts.map +1 -0
- package/dist/react/components.mjs +53 -0
- package/dist/react/components.mjs.map +1 -0
- package/dist/react/context.d.mts +22 -0
- package/dist/react/context.d.mts.map +1 -0
- package/dist/react/context.mjs +25 -0
- package/dist/react/context.mjs.map +1 -0
- package/dist/react/index.d.mts +4 -0
- package/dist/react/index.mjs +5 -0
- package/dist/react/useDevWallet.d.mts +38 -0
- package/dist/react/useDevWallet.d.mts.map +1 -0
- package/dist/react/useDevWallet.mjs +89 -0
- package/dist/react/useDevWallet.mjs.map +1 -0
- package/dist/server/cli-signing-middleware.d.mts +22 -0
- package/dist/server/cli-signing-middleware.d.mts.map +1 -0
- package/dist/server/cli-signing-middleware.mjs +117 -0
- package/dist/server/cli-signing-middleware.mjs.map +1 -0
- package/dist/server/index.d.mts +2 -0
- package/dist/server/index.mjs +3 -0
- package/dist/standalone/assets/in-memory-adapter-CBF4h2KD.js +1 -0
- package/dist/standalone/assets/main-VE4olb-Q.js +2841 -0
- package/dist/standalone/assets/webcrypto-adapter-DysAubFb.js +1 -0
- package/dist/standalone/bookmarklet.js +5 -0
- package/dist/standalone/index.html +48 -0
- package/dist/types.d.mts +55 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/ui/copy-controller.mjs +43 -0
- package/dist/ui/copy-controller.mjs.map +1 -0
- package/dist/ui/dev-wallet-account-selector.d.mts +24 -0
- package/dist/ui/dev-wallet-account-selector.d.mts.map +1 -0
- package/dist/ui/dev-wallet-account-selector.mjs +268 -0
- package/dist/ui/dev-wallet-account-selector.mjs.map +1 -0
- package/dist/ui/dev-wallet-accounts.d.mts +29 -0
- package/dist/ui/dev-wallet-accounts.d.mts.map +1 -0
- package/dist/ui/dev-wallet-accounts.mjs +524 -0
- package/dist/ui/dev-wallet-accounts.mjs.map +1 -0
- package/dist/ui/dev-wallet-balances.d.mts +26 -0
- package/dist/ui/dev-wallet-balances.d.mts.map +1 -0
- package/dist/ui/dev-wallet-balances.mjs +130 -0
- package/dist/ui/dev-wallet-balances.mjs.map +1 -0
- package/dist/ui/dev-wallet-connect.d.mts +31 -0
- package/dist/ui/dev-wallet-connect.d.mts.map +1 -0
- package/dist/ui/dev-wallet-connect.mjs +225 -0
- package/dist/ui/dev-wallet-connect.mjs.map +1 -0
- package/dist/ui/dev-wallet-dropdown.d.mts +27 -0
- package/dist/ui/dev-wallet-dropdown.d.mts.map +1 -0
- package/dist/ui/dev-wallet-dropdown.mjs +121 -0
- package/dist/ui/dev-wallet-dropdown.mjs.map +1 -0
- package/dist/ui/dev-wallet-network-badge.d.mts +21 -0
- package/dist/ui/dev-wallet-network-badge.d.mts.map +1 -0
- package/dist/ui/dev-wallet-network-badge.mjs +121 -0
- package/dist/ui/dev-wallet-network-badge.mjs.map +1 -0
- package/dist/ui/dev-wallet-new-account.d.mts +31 -0
- package/dist/ui/dev-wallet-new-account.d.mts.map +1 -0
- package/dist/ui/dev-wallet-new-account.mjs +577 -0
- package/dist/ui/dev-wallet-new-account.mjs.map +1 -0
- package/dist/ui/dev-wallet-objects.d.mts +26 -0
- package/dist/ui/dev-wallet-objects.d.mts.map +1 -0
- package/dist/ui/dev-wallet-objects.mjs +276 -0
- package/dist/ui/dev-wallet-objects.mjs.map +1 -0
- package/dist/ui/dev-wallet-panel.d.mts +22 -0
- package/dist/ui/dev-wallet-panel.d.mts.map +1 -0
- package/dist/ui/dev-wallet-panel.mjs +192 -0
- package/dist/ui/dev-wallet-panel.mjs.map +1 -0
- package/dist/ui/dev-wallet-popup.d.mts +36 -0
- package/dist/ui/dev-wallet-popup.d.mts.map +1 -0
- package/dist/ui/dev-wallet-popup.mjs +137 -0
- package/dist/ui/dev-wallet-popup.mjs.map +1 -0
- package/dist/ui/dev-wallet-settings.d.mts +33 -0
- package/dist/ui/dev-wallet-settings.d.mts.map +1 -0
- package/dist/ui/dev-wallet-settings.mjs +635 -0
- package/dist/ui/dev-wallet-settings.mjs.map +1 -0
- package/dist/ui/dev-wallet-signing-modal.d.mts +32 -0
- package/dist/ui/dev-wallet-signing-modal.d.mts.map +1 -0
- package/dist/ui/dev-wallet-signing-modal.mjs +115 -0
- package/dist/ui/dev-wallet-signing-modal.mjs.map +1 -0
- package/dist/ui/dev-wallet-signing.d.mts +25 -0
- package/dist/ui/dev-wallet-signing.d.mts.map +1 -0
- package/dist/ui/dev-wallet-signing.mjs +544 -0
- package/dist/ui/dev-wallet-signing.mjs.map +1 -0
- package/dist/ui/dev-wallet-standalone.d.mts +23 -0
- package/dist/ui/dev-wallet-standalone.d.mts.map +1 -0
- package/dist/ui/dev-wallet-standalone.mjs +129 -0
- package/dist/ui/dev-wallet-standalone.mjs.map +1 -0
- package/dist/ui/dev-wallet-tab-bar.d.mts +19 -0
- package/dist/ui/dev-wallet-tab-bar.d.mts.map +1 -0
- package/dist/ui/dev-wallet-tab-bar.mjs +143 -0
- package/dist/ui/dev-wallet-tab-bar.mjs.map +1 -0
- package/dist/ui/index.d.mts +17 -0
- package/dist/ui/index.mjs +18 -0
- package/dist/ui/mount.d.mts +11 -0
- package/dist/ui/mount.d.mts.map +1 -0
- package/dist/ui/mount.mjs +17 -0
- package/dist/ui/mount.mjs.map +1 -0
- package/dist/ui/styles.mjs +250 -0
- package/dist/ui/styles.mjs.map +1 -0
- package/dist/ui/transaction-analyzer.mjs +58 -0
- package/dist/ui/transaction-analyzer.mjs.map +1 -0
- package/dist/ui/utils.mjs +98 -0
- package/dist/ui/utils.mjs.map +1 -0
- package/dist/ui/wallet-controller.mjs +275 -0
- package/dist/ui/wallet-controller.mjs.map +1 -0
- package/dist/wallet/constants.mjs +11 -0
- package/dist/wallet/constants.mjs.map +1 -0
- package/dist/wallet/dev-wallet.d.mts +118 -0
- package/dist/wallet/dev-wallet.d.mts.map +1 -0
- package/dist/wallet/dev-wallet.mjs +424 -0
- package/dist/wallet/dev-wallet.mjs.map +1 -0
- package/dist/wallet/initializer.d.mts +63 -0
- package/dist/wallet/initializer.d.mts.map +1 -0
- package/dist/wallet/initializer.mjs +75 -0
- package/dist/wallet/initializer.mjs.map +1 -0
- package/dist/wallet/signing.d.mts +35 -0
- package/dist/wallet/signing.d.mts.map +1 -0
- package/dist/wallet/signing.mjs +69 -0
- package/dist/wallet/signing.mjs.map +1 -0
- package/package.json +124 -0
- package/src/adapters/base-adapter.ts +93 -0
- package/src/adapters/browser.ts +15 -0
- package/src/adapters/build-managed-account.ts +33 -0
- package/src/adapters/idb-store.ts +87 -0
- package/src/adapters/in-memory-adapter.ts +51 -0
- package/src/adapters/passkey-adapter.ts +120 -0
- package/src/adapters/remote-cli-adapter.ts +388 -0
- package/src/adapters/webcrypto-adapter.ts +96 -0
- package/src/app/bookmarklet-entry.ts +77 -0
- package/src/app/index.html +48 -0
- package/src/app/main.ts +245 -0
- package/src/app/tsconfig.json +3 -0
- package/src/bin/cli.ts +214 -0
- package/src/client/dev-wallet-client.ts +280 -0
- package/src/client/index.ts +7 -0
- package/src/client/request-handler.ts +161 -0
- package/src/index.ts +19 -0
- package/src/react/components.ts +64 -0
- package/src/react/context.ts +38 -0
- package/src/react/index.ts +16 -0
- package/src/react/useDevWallet.ts +118 -0
- package/src/server/cli-signing-middleware.ts +146 -0
- package/src/server/index.ts +8 -0
- package/src/types.ts +58 -0
- package/src/ui/copy-controller.ts +49 -0
- package/src/ui/dev-wallet-account-selector.ts +283 -0
- package/src/ui/dev-wallet-accounts.ts +578 -0
- package/src/ui/dev-wallet-balances.ts +171 -0
- package/src/ui/dev-wallet-connect.ts +259 -0
- package/src/ui/dev-wallet-dropdown.ts +138 -0
- package/src/ui/dev-wallet-network-badge.ts +128 -0
- package/src/ui/dev-wallet-new-account.ts +662 -0
- package/src/ui/dev-wallet-objects.ts +336 -0
- package/src/ui/dev-wallet-panel.ts +207 -0
- package/src/ui/dev-wallet-popup.ts +169 -0
- package/src/ui/dev-wallet-settings.ts +692 -0
- package/src/ui/dev-wallet-signing-modal.ts +137 -0
- package/src/ui/dev-wallet-signing.ts +624 -0
- package/src/ui/dev-wallet-standalone.ts +136 -0
- package/src/ui/dev-wallet-tab-bar.ts +151 -0
- package/src/ui/index.ts +26 -0
- package/src/ui/mount.ts +21 -0
- package/src/ui/styles.ts +252 -0
- package/src/ui/transaction-analyzer.ts +60 -0
- package/src/ui/utils.ts +118 -0
- package/src/ui/wallet-controller.ts +340 -0
- package/src/wallet/constants.ts +17 -0
- package/src/wallet/dev-wallet.ts +597 -0
- package/src/wallet/initializer.ts +124 -0
- package/src/wallet/signing.ts +85 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.d.mts","names":[],"sources":["../../src/wallet/signing.ts"],"mappings":";;;;KAQK,kBAAA;AAAA,UAKK,qBAAA;EACT,IAAA,EAAM,kBAAA;EACN,MAAA,EAAQ,MAAA;EACR,IAAA,WAAe,UAAA;EACf,MAAA,GAAS,iBAAA;AAAA;AAAA,KAGE,aAAA;EACP,IAAA;EAA+B,KAAA;EAAe,SAAA;AAAA;EAC9C,IAAA;EAA0B,KAAA;EAAe,SAAA;AAAA;EAE3C,IAAA;EACA,KAAA;EACA,SAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,iBAImB,cAAA,CAAA;EACrB,IAAA;EACA,MAAA;EACA,IAAA;EACA;AAAA,GACE,qBAAA,GAAwB,OAAA,CAAQ,aAAA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
2
|
+
import { fromBase64, toBase64 } from "@mysten/sui/utils";
|
|
3
|
+
|
|
4
|
+
//#region src/wallet/signing.ts
|
|
5
|
+
async function executeSigning({ type, signer, data, client }) {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case "sign-personal-message": {
|
|
8
|
+
if (!(data instanceof Uint8Array)) {
|
|
9
|
+
throw new Error("sign-personal-message expects data to be a Uint8Array");
|
|
10
|
+
}
|
|
11
|
+
const { bytes, signature } = await signer.signPersonalMessage(data);
|
|
12
|
+
return {
|
|
13
|
+
type,
|
|
14
|
+
bytes,
|
|
15
|
+
signature
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
case "sign-transaction": {
|
|
19
|
+
if (!client) throw new Error("No client provided for sign-transaction");
|
|
20
|
+
if (typeof data !== "string") {
|
|
21
|
+
throw new Error("sign-transaction expects data to be a JSON string");
|
|
22
|
+
}
|
|
23
|
+
const tx = Transaction.from(data);
|
|
24
|
+
const { bytes, signature } = await tx.sign({
|
|
25
|
+
client,
|
|
26
|
+
signer
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
type,
|
|
30
|
+
bytes,
|
|
31
|
+
signature
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
case "sign-and-execute-transaction": {
|
|
35
|
+
if (!client) throw new Error("No client provided for sign-and-execute-transaction");
|
|
36
|
+
if (typeof data !== "string") {
|
|
37
|
+
throw new Error("sign-and-execute-transaction expects data to be a JSON string");
|
|
38
|
+
}
|
|
39
|
+
const tx = Transaction.from(data);
|
|
40
|
+
const { bytes, signature } = await tx.sign({
|
|
41
|
+
client,
|
|
42
|
+
signer
|
|
43
|
+
});
|
|
44
|
+
const result = await client.core.executeTransaction({
|
|
45
|
+
transaction: fromBase64(bytes),
|
|
46
|
+
signatures: [signature],
|
|
47
|
+
include: { effects: true }
|
|
48
|
+
});
|
|
49
|
+
const txResult = result.Transaction ?? result.FailedTransaction;
|
|
50
|
+
if (!txResult) {
|
|
51
|
+
throw new Error("Transaction execution returned empty result");
|
|
52
|
+
}
|
|
53
|
+
if (!txResult.status.success) {
|
|
54
|
+
throw new Error(txResult.status.error?.message ?? "Transaction execution failed");
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
type,
|
|
58
|
+
bytes,
|
|
59
|
+
signature,
|
|
60
|
+
digest: txResult.digest,
|
|
61
|
+
effects: txResult.effects?.bcs ? toBase64(txResult.effects.bcs) : ""
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
export { executeSigning };
|
|
69
|
+
//# sourceMappingURL=signing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.mjs","names":[],"sources":["../../src/wallet/signing.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Transaction } from '@mysten/sui/transactions';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\n\ntype SigningRequestType =\n\t| 'sign-personal-message'\n\t| 'sign-transaction'\n\t| 'sign-and-execute-transaction';\n\ninterface ExecuteSigningOptions {\n\ttype: SigningRequestType;\n\tsigner: Signer;\n\tdata: string | Uint8Array;\n\tclient?: ClientWithCoreApi;\n}\n\nexport type SigningResult =\n\t| { type: 'sign-personal-message'; bytes: string; signature: string }\n\t| { type: 'sign-transaction'; bytes: string; signature: string }\n\t| {\n\t\t\ttype: 'sign-and-execute-transaction';\n\t\t\tbytes: string;\n\t\t\tsignature: string;\n\t\t\tdigest: string;\n\t\t\teffects: string;\n\t };\n\n// Shared between the embedded DevWallet and the standalone popup request-handler.\nexport async function executeSigning({\n\ttype,\n\tsigner,\n\tdata,\n\tclient,\n}: ExecuteSigningOptions): Promise<SigningResult> {\n\tswitch (type) {\n\t\tcase 'sign-personal-message': {\n\t\t\tif (!(data instanceof Uint8Array)) {\n\t\t\t\tthrow new Error('sign-personal-message expects data to be a Uint8Array');\n\t\t\t}\n\t\t\tconst { bytes, signature } = await signer.signPersonalMessage(data);\n\t\t\treturn { type, bytes, signature };\n\t\t}\n\t\tcase 'sign-transaction': {\n\t\t\tif (!client) throw new Error('No client provided for sign-transaction');\n\t\t\tif (typeof data !== 'string') {\n\t\t\t\tthrow new Error('sign-transaction expects data to be a JSON string');\n\t\t\t}\n\t\t\tconst tx = Transaction.from(data);\n\t\t\tconst { bytes, signature } = await tx.sign({ client, signer });\n\t\t\treturn { type, bytes, signature };\n\t\t}\n\t\tcase 'sign-and-execute-transaction': {\n\t\t\tif (!client) throw new Error('No client provided for sign-and-execute-transaction');\n\t\t\tif (typeof data !== 'string') {\n\t\t\t\tthrow new Error('sign-and-execute-transaction expects data to be a JSON string');\n\t\t\t}\n\t\t\tconst tx = Transaction.from(data);\n\t\t\tconst { bytes, signature } = await tx.sign({ client, signer });\n\t\t\tconst result = await client.core.executeTransaction({\n\t\t\t\ttransaction: fromBase64(bytes),\n\t\t\t\tsignatures: [signature],\n\t\t\t\tinclude: { effects: true },\n\t\t\t});\n\t\t\tconst txResult = result.Transaction ?? result.FailedTransaction;\n\t\t\tif (!txResult) {\n\t\t\t\tthrow new Error('Transaction execution returned empty result');\n\t\t\t}\n\t\t\tif (!txResult.status.success) {\n\t\t\t\tthrow new Error(txResult.status.error?.message ?? 'Transaction execution failed');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype,\n\t\t\t\tbytes,\n\t\t\t\tsignature,\n\t\t\t\tdigest: txResult.digest,\n\t\t\t\t// Empty string when effects BCS is unavailable — the wallet-standard protocol requires a string\n\t\t\t\teffects: txResult.effects?.bcs ? toBase64(txResult.effects.bcs) : '',\n\t\t\t};\n\t\t}\n\t}\n}\n"],"mappings":";;;;AAgCA,eAAsB,eAAe,EACpC,MACA,QACA,MACA,UACiD;AACjD,SAAQ,MAAR;EACC,KAAK,yBAAyB;AAC7B,OAAI,EAAE,gBAAgB,aAAa;AAClC,UAAM,IAAI,MAAM,wDAAwD;;GAEzE,MAAM,EAAE,OAAO,cAAc,MAAM,OAAO,oBAAoB,KAAK;AACnE,UAAO;IAAE;IAAM;IAAO;IAAW;;EAElC,KAAK,oBAAoB;AACxB,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,0CAA0C;AACvE,OAAI,OAAO,SAAS,UAAU;AAC7B,UAAM,IAAI,MAAM,oDAAoD;;GAErE,MAAM,KAAK,YAAY,KAAK,KAAK;GACjC,MAAM,EAAE,OAAO,cAAc,MAAM,GAAG,KAAK;IAAE;IAAQ;IAAQ,CAAC;AAC9D,UAAO;IAAE;IAAM;IAAO;IAAW;;EAElC,KAAK,gCAAgC;AACpC,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,sDAAsD;AACnF,OAAI,OAAO,SAAS,UAAU;AAC7B,UAAM,IAAI,MAAM,gEAAgE;;GAEjF,MAAM,KAAK,YAAY,KAAK,KAAK;GACjC,MAAM,EAAE,OAAO,cAAc,MAAM,GAAG,KAAK;IAAE;IAAQ;IAAQ,CAAC;GAC9D,MAAM,SAAS,MAAM,OAAO,KAAK,mBAAmB;IACnD,aAAa,WAAW,MAAM;IAC9B,YAAY,CAAC,UAAU;IACvB,SAAS,EAAE,SAAS,MAAM;IAC1B,CAAC;GACF,MAAM,WAAW,OAAO,eAAe,OAAO;AAC9C,OAAI,CAAC,UAAU;AACd,UAAM,IAAI,MAAM,8CAA8C;;AAE/D,OAAI,CAAC,SAAS,OAAO,SAAS;AAC7B,UAAM,IAAI,MAAM,SAAS,OAAO,OAAO,WAAW,+BAA+B;;AAElF,UAAO;IACN;IACA;IACA;IACA,QAAQ,SAAS;IAEjB,SAAS,SAAS,SAAS,MAAM,SAAS,SAAS,QAAQ,IAAI,GAAG;IAClE"}
|
package/package.json
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mysten-incubation/dev-wallet",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "A modular dev wallet for Sui",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Mysten Labs <build@mystenlabs.com>",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.mts",
|
|
10
|
+
"bin": {
|
|
11
|
+
"dev-wallet": "dist/bin/cli.mjs"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"import": "./dist/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./adapters": {
|
|
19
|
+
"types": "./dist/adapters/browser.d.mts",
|
|
20
|
+
"import": "./dist/adapters/browser.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./ui": {
|
|
23
|
+
"types": "./dist/ui/index.d.mts",
|
|
24
|
+
"import": "./dist/ui/index.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./react": {
|
|
27
|
+
"types": "./dist/react/index.d.mts",
|
|
28
|
+
"import": "./dist/react/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"./client": {
|
|
31
|
+
"types": "./dist/client/index.d.mts",
|
|
32
|
+
"import": "./dist/client/index.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./server": {
|
|
35
|
+
"types": "./dist/server/index.d.mts",
|
|
36
|
+
"import": "./dist/server/index.mjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"sideEffects": [
|
|
40
|
+
"dist/ui/*.mjs"
|
|
41
|
+
],
|
|
42
|
+
"files": [
|
|
43
|
+
"CHANGELOG.md",
|
|
44
|
+
"dist",
|
|
45
|
+
"src"
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"clean": "rm -rf tsconfig.tsbuildinfo ./dist",
|
|
49
|
+
"build": "rm -rf dist && tsc --noEmit && tsdown && vite build --config vite.standalone.config.ts && vite build --config vite.bookmarklet.config.ts",
|
|
50
|
+
"prettier:check": "prettier -c --ignore-unknown .",
|
|
51
|
+
"prettier:fix": "prettier -w --ignore-unknown .",
|
|
52
|
+
"oxlint:check": "oxlint .",
|
|
53
|
+
"oxlint:fix": "oxlint --fix",
|
|
54
|
+
"lint": "pnpm run oxlint:check && pnpm run prettier:check",
|
|
55
|
+
"lint:fix": "pnpm run oxlint:fix && pnpm run prettier:fix",
|
|
56
|
+
"test": "vitest run --config vitest.config.ts",
|
|
57
|
+
"test:node": "vitest run --config vitest.config.ts",
|
|
58
|
+
"test:browser": "vitest run --config vitest.browser.config.ts"
|
|
59
|
+
},
|
|
60
|
+
"repository": {
|
|
61
|
+
"type": "git",
|
|
62
|
+
"url": "git+https://github.com/MystenLabs/ts-incubation.git"
|
|
63
|
+
},
|
|
64
|
+
"bugs": {
|
|
65
|
+
"url": "https://github.com/MystenLabs/ts-incubation/issues"
|
|
66
|
+
},
|
|
67
|
+
"keywords": [
|
|
68
|
+
"sui",
|
|
69
|
+
"wallet",
|
|
70
|
+
"development",
|
|
71
|
+
"testing",
|
|
72
|
+
"dapp",
|
|
73
|
+
"web3",
|
|
74
|
+
"wallet-standard"
|
|
75
|
+
],
|
|
76
|
+
"homepage": "https://github.com/MystenLabs/ts-incubation/tree/main/packages/dev-wallet#readme",
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@lit/react": "^1.0.8",
|
|
79
|
+
"@mysten/signers": "^1.0.1",
|
|
80
|
+
"@mysten/sui": "^2.9.1",
|
|
81
|
+
"@testing-library/react": "^16.3.1",
|
|
82
|
+
"@types/node": "^25.0.8",
|
|
83
|
+
"@types/react": "^19.2.8",
|
|
84
|
+
"@vitest/browser": "^4.0.18",
|
|
85
|
+
"@vitest/browser-playwright": "^4.0.18",
|
|
86
|
+
"happy-dom": "^20.1.0",
|
|
87
|
+
"playwright": "*",
|
|
88
|
+
"react": "^19.2.3",
|
|
89
|
+
"react-dom": "^19.2.3",
|
|
90
|
+
"typescript": "^5.9.3",
|
|
91
|
+
"vite": "^7.3.1",
|
|
92
|
+
"vitest": "^4.0.17"
|
|
93
|
+
},
|
|
94
|
+
"dependencies": {
|
|
95
|
+
"@hono/node-server": "^1.19.9",
|
|
96
|
+
"@mysten/utils": "^0.3.1",
|
|
97
|
+
"@mysten/wallet-sdk": "^0.1.1",
|
|
98
|
+
"@mysten/wallet-standard": "^0.20.1",
|
|
99
|
+
"@mysten/window-wallet-core": "^0.1.4",
|
|
100
|
+
"hono": "^4.12.3",
|
|
101
|
+
"lit": "^3.3.2"
|
|
102
|
+
},
|
|
103
|
+
"peerDependencies": {
|
|
104
|
+
"@lit/react": "^1.0.8",
|
|
105
|
+
"@mysten/signers": "^1.0.1",
|
|
106
|
+
"@mysten/sui": "^2.9.1",
|
|
107
|
+
"@types/react": ">=17.0.0",
|
|
108
|
+
"react": ">=17.0.0"
|
|
109
|
+
},
|
|
110
|
+
"peerDependenciesMeta": {
|
|
111
|
+
"react": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"@types/react": {
|
|
115
|
+
"optional": true
|
|
116
|
+
},
|
|
117
|
+
"@mysten/signers": {
|
|
118
|
+
"optional": true
|
|
119
|
+
},
|
|
120
|
+
"@lit/react": {
|
|
121
|
+
"optional": true
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { ManagedAccount, SignerAdapter } from '../types.js';
|
|
5
|
+
import { buildManagedAccount } from './build-managed-account.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Abstract base class implementing the shared boilerplate of {@link SignerAdapter}.
|
|
9
|
+
*
|
|
10
|
+
* Subclasses only need to implement `initialize()`, `id`, and `name`.
|
|
11
|
+
* All account list management, listener notification, and cleanup are handled here.
|
|
12
|
+
*/
|
|
13
|
+
export abstract class BaseSignerAdapter implements SignerAdapter {
|
|
14
|
+
abstract readonly id: string;
|
|
15
|
+
abstract readonly name: string;
|
|
16
|
+
readonly allowAutoSign: boolean = true;
|
|
17
|
+
|
|
18
|
+
#accounts: ManagedAccount[] = [];
|
|
19
|
+
#listeners = new Set<(accounts: ManagedAccount[]) => void>();
|
|
20
|
+
|
|
21
|
+
abstract initialize(): Promise<void>;
|
|
22
|
+
|
|
23
|
+
getAccounts(): ManagedAccount[] {
|
|
24
|
+
return [...this.#accounts];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getAccount(address: string): ManagedAccount | undefined {
|
|
28
|
+
return this.#accounts.find((account) => account.address === address);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onAccountsChanged(callback: (accounts: ManagedAccount[]) => void): () => void {
|
|
32
|
+
this.#listeners.add(callback);
|
|
33
|
+
return () => {
|
|
34
|
+
this.#listeners.delete(callback);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
destroy(): void {
|
|
39
|
+
this.#accounts = [];
|
|
40
|
+
this.#listeners.clear();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── Protected helpers for subclasses ─────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
protected get _accounts(): readonly ManagedAccount[] {
|
|
46
|
+
return this.#accounts;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected setInitialAccounts(accounts: ManagedAccount[]): void {
|
|
50
|
+
this.#accounts = accounts;
|
|
51
|
+
this.notifyListeners();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected addAccount(account: ManagedAccount): void {
|
|
55
|
+
this.#accounts.push(account);
|
|
56
|
+
this.notifyListeners();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected removeAccountByAddress(address: string): boolean {
|
|
60
|
+
const index = this.#accounts.findIndex((a) => a.address === address);
|
|
61
|
+
if (index === -1) return false;
|
|
62
|
+
this.#accounts.splice(index, 1);
|
|
63
|
+
this.notifyListeners();
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Replace an account by address (e.g. after rename). */
|
|
68
|
+
protected replaceAccount(address: string, account: ManagedAccount): boolean {
|
|
69
|
+
const index = this.#accounts.findIndex((a) => a.address === address);
|
|
70
|
+
if (index === -1) return false;
|
|
71
|
+
this.#accounts[index] = account;
|
|
72
|
+
this.notifyListeners();
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Rename an account by rebuilding its ManagedAccount with a new label. */
|
|
77
|
+
protected _performRename(address: string, label: string): boolean {
|
|
78
|
+
const account = this.getAccount(address);
|
|
79
|
+
if (!account) return false;
|
|
80
|
+
return this.replaceAccount(address, buildManagedAccount(account.signer, address, label));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected getDefaultLabel(): string {
|
|
84
|
+
return `Account ${this.getAccounts().length + 1}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
protected notifyListeners(): void {
|
|
88
|
+
const accounts = this.getAccounts();
|
|
89
|
+
for (const listener of this.#listeners) {
|
|
90
|
+
listener(accounts);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export type {
|
|
5
|
+
SignerAdapter,
|
|
6
|
+
ManagedAccount,
|
|
7
|
+
CreateAccountOptions,
|
|
8
|
+
ImportAccountOptions,
|
|
9
|
+
} from '../types.js';
|
|
10
|
+
export { BaseSignerAdapter } from './base-adapter.js';
|
|
11
|
+
export { buildManagedAccount } from './build-managed-account.js';
|
|
12
|
+
export { InMemorySignerAdapter } from './in-memory-adapter.js';
|
|
13
|
+
export { RemoteCliAdapter, CliProxySigner } from './remote-cli-adapter.js';
|
|
14
|
+
export { WebCryptoSignerAdapter } from './webcrypto-adapter.js';
|
|
15
|
+
export { PasskeySignerAdapter } from './passkey-adapter.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { Signer } from '@mysten/sui/cryptography';
|
|
5
|
+
import type { IdentifierString } from '@mysten/wallet-standard';
|
|
6
|
+
import { ReadonlyWalletAccount, SUI_CHAINS } from '@mysten/wallet-standard';
|
|
7
|
+
|
|
8
|
+
import type { ManagedAccount } from '../types.js';
|
|
9
|
+
|
|
10
|
+
const DEFAULT_FEATURES: IdentifierString[] = [
|
|
11
|
+
'sui:signTransaction',
|
|
12
|
+
'sui:signAndExecuteTransaction',
|
|
13
|
+
'sui:signPersonalMessage',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build a {@link ManagedAccount} from a signer, address, label, and optional feature list.
|
|
18
|
+
*/
|
|
19
|
+
export function buildManagedAccount(
|
|
20
|
+
signer: Signer,
|
|
21
|
+
address: string,
|
|
22
|
+
label: string,
|
|
23
|
+
features?: readonly IdentifierString[],
|
|
24
|
+
): ManagedAccount {
|
|
25
|
+
const walletAccount = new ReadonlyWalletAccount({
|
|
26
|
+
address,
|
|
27
|
+
label,
|
|
28
|
+
publicKey: signer.getPublicKey().toSuiBytes(),
|
|
29
|
+
chains: [...SUI_CHAINS],
|
|
30
|
+
features: [...(features ?? DEFAULT_FEATURES)],
|
|
31
|
+
});
|
|
32
|
+
return { address, label, signer, walletAccount };
|
|
33
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Minimal IndexedDB key-value store replacing the `idb-keyval` package.
|
|
6
|
+
*
|
|
7
|
+
* The database connection is opened lazily on first use and reused for all
|
|
8
|
+
* subsequent operations.
|
|
9
|
+
*/
|
|
10
|
+
export class IDBStore {
|
|
11
|
+
#dbName: string;
|
|
12
|
+
#storeName: string;
|
|
13
|
+
#db: Promise<IDBDatabase> | null = null;
|
|
14
|
+
|
|
15
|
+
constructor(dbName: string, storeName: string) {
|
|
16
|
+
this.#dbName = dbName;
|
|
17
|
+
this.#storeName = storeName;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get<T>(key: IDBValidKey): Promise<T | undefined> {
|
|
21
|
+
return this.#withTx('readonly', (s) => s.get(key) as IDBRequest<T | undefined>);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async set(key: IDBValidKey, value: unknown): Promise<void> {
|
|
25
|
+
await this.#withTx('readwrite', (s) => s.put(value, key));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
del(key: IDBValidKey): Promise<void> {
|
|
29
|
+
return this.#withTx('readwrite', (s) => s.delete(key) as IDBRequest<void>);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
entries<K extends IDBValidKey, V>(): Promise<[K, V][]> {
|
|
33
|
+
return this.#open().then(
|
|
34
|
+
(db) =>
|
|
35
|
+
new Promise((resolve, reject) => {
|
|
36
|
+
const tx = db.transaction(this.#storeName, 'readonly');
|
|
37
|
+
const objectStore = tx.objectStore(this.#storeName);
|
|
38
|
+
const results: [K, V][] = [];
|
|
39
|
+
const cursor = objectStore.openCursor();
|
|
40
|
+
cursor.onsuccess = () => {
|
|
41
|
+
const c = cursor.result;
|
|
42
|
+
if (c) {
|
|
43
|
+
results.push([c.key as K, c.value as V]);
|
|
44
|
+
c.continue();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
tx.oncomplete = () => resolve(results);
|
|
48
|
+
tx.onerror = () => reject(tx.error);
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#open(): Promise<IDBDatabase> {
|
|
54
|
+
if (!this.#db) {
|
|
55
|
+
this.#db = new Promise((resolve, reject) => {
|
|
56
|
+
const request = indexedDB.open(this.#dbName);
|
|
57
|
+
request.onupgradeneeded = () => {
|
|
58
|
+
if (!request.result.objectStoreNames.contains(this.#storeName)) {
|
|
59
|
+
request.result.createObjectStore(this.#storeName);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
request.onsuccess = () => resolve(request.result);
|
|
63
|
+
request.onerror = () => {
|
|
64
|
+
this.#db = null;
|
|
65
|
+
reject(request.error);
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return this.#db;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#withTx<T>(
|
|
73
|
+
mode: IDBTransactionMode,
|
|
74
|
+
fn: (objectStore: IDBObjectStore) => IDBRequest<T>,
|
|
75
|
+
): Promise<T> {
|
|
76
|
+
return this.#open().then(
|
|
77
|
+
(db) =>
|
|
78
|
+
new Promise((resolve, reject) => {
|
|
79
|
+
const tx = db.transaction(this.#storeName, mode);
|
|
80
|
+
const req = fn(tx.objectStore(this.#storeName));
|
|
81
|
+
tx.oncomplete = () => resolve(req.result);
|
|
82
|
+
tx.onerror = () => reject(tx.error);
|
|
83
|
+
tx.onabort = () => reject(tx.error);
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
5
|
+
|
|
6
|
+
import type { CreateAccountOptions, ImportAccountOptions, ManagedAccount } from '../types.js';
|
|
7
|
+
import { BaseSignerAdapter } from './base-adapter.js';
|
|
8
|
+
import { buildManagedAccount } from './build-managed-account.js';
|
|
9
|
+
|
|
10
|
+
export class InMemorySignerAdapter extends BaseSignerAdapter {
|
|
11
|
+
readonly id = 'in-memory';
|
|
12
|
+
readonly name = 'In-Memory Signer';
|
|
13
|
+
|
|
14
|
+
async initialize(): Promise<void> {
|
|
15
|
+
// No-op for in-memory adapter
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async createAccount(options?: CreateAccountOptions): Promise<ManagedAccount> {
|
|
19
|
+
const keypair = new Ed25519Keypair();
|
|
20
|
+
const address = keypair.getPublicKey().toSuiAddress();
|
|
21
|
+
const label = options?.label ?? this.getDefaultLabel();
|
|
22
|
+
|
|
23
|
+
const managedAccount = buildManagedAccount(keypair, address, label);
|
|
24
|
+
this.addAccount(managedAccount);
|
|
25
|
+
return managedAccount;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async importAccount(options: ImportAccountOptions): Promise<ManagedAccount> {
|
|
29
|
+
const signer = options.signer;
|
|
30
|
+
if (!signer) {
|
|
31
|
+
throw new Error('In-memory adapter requires a signer to import');
|
|
32
|
+
}
|
|
33
|
+
const address = signer.toSuiAddress();
|
|
34
|
+
|
|
35
|
+
const existing = this.getAccount(address);
|
|
36
|
+
if (existing) return existing;
|
|
37
|
+
|
|
38
|
+
const label = options.label ?? this.getDefaultLabel();
|
|
39
|
+
const managedAccount = buildManagedAccount(signer, address, label);
|
|
40
|
+
this.addAccount(managedAccount);
|
|
41
|
+
return managedAccount;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async renameAccount(address: string, label: string): Promise<boolean> {
|
|
45
|
+
return this._performRename(address, label);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async removeAccount(address: string): Promise<boolean> {
|
|
49
|
+
return this.removeAccountByAddress(address);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { PasskeyKeypair } from '@mysten/sui/keypairs/passkey';
|
|
5
|
+
import type { PasskeyProvider } from '@mysten/sui/keypairs/passkey';
|
|
6
|
+
|
|
7
|
+
import type { CreateAccountOptions } from '../types.js';
|
|
8
|
+
import { BaseSignerAdapter } from './base-adapter.js';
|
|
9
|
+
import { buildManagedAccount } from './build-managed-account.js';
|
|
10
|
+
import { IDBStore } from './idb-store.js';
|
|
11
|
+
|
|
12
|
+
/** Metadata stored in IndexedDB for each passkey account. */
|
|
13
|
+
interface StoredPasskeyMeta {
|
|
14
|
+
address: string;
|
|
15
|
+
label: string;
|
|
16
|
+
/** Compressed secp256r1 public key (33 bytes, stored as number array). */
|
|
17
|
+
publicKeyBytes: number[];
|
|
18
|
+
/** WebAuthn credential ID (stored as number array). Used to constrain credential selection during signing. */
|
|
19
|
+
credentialId?: number[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const DEFAULT_DB_NAME = 'dev-wallet-passkey';
|
|
23
|
+
const DEFAULT_STORE_NAME = 'accounts';
|
|
24
|
+
const META_KEY = '__passkey_accounts__';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Signer adapter backed by WebAuthn passkeys. Each signing operation triggers a
|
|
28
|
+
* browser biometric/PIN prompt. Account metadata is persisted in IndexedDB;
|
|
29
|
+
* private keys are managed by the browser/OS and never enter JavaScript.
|
|
30
|
+
*
|
|
31
|
+
* Browser only — requires `navigator.credentials` and `indexedDB`.
|
|
32
|
+
*/
|
|
33
|
+
export class PasskeySignerAdapter extends BaseSignerAdapter {
|
|
34
|
+
readonly id = 'passkey';
|
|
35
|
+
readonly name = 'Passkey Signer';
|
|
36
|
+
readonly allowAutoSign = false;
|
|
37
|
+
|
|
38
|
+
#store: IDBStore;
|
|
39
|
+
#provider: PasskeyProvider | null;
|
|
40
|
+
|
|
41
|
+
constructor(options?: { dbName?: string; storeName?: string; provider?: PasskeyProvider }) {
|
|
42
|
+
super();
|
|
43
|
+
this.#store = new IDBStore(
|
|
44
|
+
options?.dbName ?? DEFAULT_DB_NAME,
|
|
45
|
+
options?.storeName ?? DEFAULT_STORE_NAME,
|
|
46
|
+
);
|
|
47
|
+
// Allow injecting a custom provider (useful for testing)
|
|
48
|
+
this.#provider = options?.provider ?? null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#getProvider(): PasskeyProvider {
|
|
52
|
+
if (!this.#provider) {
|
|
53
|
+
throw new Error('PasskeySignerAdapter not initialized. Call initialize() first.');
|
|
54
|
+
}
|
|
55
|
+
return this.#provider;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async initialize(): Promise<void> {
|
|
59
|
+
if (!this.#provider) {
|
|
60
|
+
const { BrowserPasskeyProvider } = await import('@mysten/sui/keypairs/passkey');
|
|
61
|
+
this.#provider = new BrowserPasskeyProvider('Dev Wallet Passkey', {
|
|
62
|
+
rp: { id: globalThis.location?.hostname },
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const stored = await this.#store.get<StoredPasskeyMeta[]>(META_KEY);
|
|
67
|
+
if (!stored) return;
|
|
68
|
+
|
|
69
|
+
const provider = this.#getProvider();
|
|
70
|
+
this.setInitialAccounts(
|
|
71
|
+
stored.map((meta) => {
|
|
72
|
+
const publicKeyBytes = new Uint8Array(meta.publicKeyBytes);
|
|
73
|
+
const credentialId = meta.credentialId ? new Uint8Array(meta.credentialId) : undefined;
|
|
74
|
+
const signer = new PasskeyKeypair(publicKeyBytes, provider, credentialId);
|
|
75
|
+
return buildManagedAccount(signer, meta.address, meta.label);
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
protected override getDefaultLabel(): string {
|
|
81
|
+
return `Passkey Account ${this.getAccounts().length + 1}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async createAccount(options?: CreateAccountOptions) {
|
|
85
|
+
const signer = await PasskeyKeypair.getPasskeyInstance(this.#getProvider());
|
|
86
|
+
const address = signer.toSuiAddress();
|
|
87
|
+
const label = options?.label ?? this.getDefaultLabel();
|
|
88
|
+
|
|
89
|
+
const managedAccount = buildManagedAccount(signer, address, label);
|
|
90
|
+
this.addAccount(managedAccount);
|
|
91
|
+
await this.#saveMeta();
|
|
92
|
+
|
|
93
|
+
return managedAccount;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async renameAccount(address: string, label: string): Promise<boolean> {
|
|
97
|
+
if (!this._performRename(address, label)) return false;
|
|
98
|
+
await this.#saveMeta();
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async removeAccount(address: string): Promise<boolean> {
|
|
103
|
+
if (!this.removeAccountByAddress(address)) return false;
|
|
104
|
+
await this.#saveMeta();
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async #saveMeta(): Promise<void> {
|
|
109
|
+
const meta: StoredPasskeyMeta[] = this.getAccounts().map((a) => {
|
|
110
|
+
const credentialId = (a.signer as PasskeyKeypair).getCredentialId?.();
|
|
111
|
+
return {
|
|
112
|
+
address: a.address,
|
|
113
|
+
label: a.label,
|
|
114
|
+
publicKeyBytes: [...a.signer.getPublicKey().toRawBytes()],
|
|
115
|
+
...(credentialId && { credentialId: [...credentialId] }),
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
await this.#store.set(META_KEY, meta);
|
|
119
|
+
}
|
|
120
|
+
}
|