@shieldedtech/moth-wallet 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/contract/args-parser.d.ts +29 -0
- package/dist/contract/args-parser.d.ts.map +1 -0
- package/dist/contract/args-parser.js +123 -0
- package/dist/contract/args-parser.js.map +1 -0
- package/dist/contract/artifact-loader.d.ts +26 -0
- package/dist/contract/artifact-loader.d.ts.map +1 -0
- package/dist/contract/artifact-loader.js +129 -0
- package/dist/contract/artifact-loader.js.map +1 -0
- package/dist/contract/call.d.ts +32 -0
- package/dist/contract/call.d.ts.map +1 -0
- package/dist/contract/call.js +245 -0
- package/dist/contract/call.js.map +1 -0
- package/dist/contract/deploy.d.ts +36 -0
- package/dist/contract/deploy.d.ts.map +1 -0
- package/dist/contract/deploy.js +388 -0
- package/dist/contract/deploy.js.map +1 -0
- package/dist/contract/fungible-token.d.ts +40 -0
- package/dist/contract/fungible-token.d.ts.map +1 -0
- package/dist/contract/fungible-token.js +88 -0
- package/dist/contract/fungible-token.js.map +1 -0
- package/dist/contract/initial-private-state.d.ts +18 -0
- package/dist/contract/initial-private-state.d.ts.map +1 -0
- package/dist/contract/initial-private-state.js +44 -0
- package/dist/contract/initial-private-state.js.map +1 -0
- package/dist/contract/maintenance.d.ts +72 -0
- package/dist/contract/maintenance.d.ts.map +1 -0
- package/dist/contract/maintenance.js +430 -0
- package/dist/contract/maintenance.js.map +1 -0
- package/dist/contract/state.d.ts +16 -0
- package/dist/contract/state.d.ts.map +1 -0
- package/dist/contract/state.js +18 -0
- package/dist/contract/state.js.map +1 -0
- package/dist/contract/witness-loader.d.ts +3 -0
- package/dist/contract/witness-loader.d.ts.map +1 -0
- package/dist/contract/witness-loader.js +27 -0
- package/dist/contract/witness-loader.js.map +1 -0
- package/dist/daemon/api-keys.d.ts +66 -0
- package/dist/daemon/api-keys.d.ts.map +1 -0
- package/dist/daemon/api-keys.js +222 -0
- package/dist/daemon/api-keys.js.map +1 -0
- package/dist/daemon/audit-log.d.ts +65 -0
- package/dist/daemon/audit-log.d.ts.map +1 -0
- package/dist/daemon/audit-log.js +73 -0
- package/dist/daemon/audit-log.js.map +1 -0
- package/dist/daemon/client.d.ts +63 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +214 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/confirmation-queue.d.ts +46 -0
- package/dist/daemon/confirmation-queue.d.ts.map +1 -0
- package/dist/daemon/confirmation-queue.js +92 -0
- package/dist/daemon/confirmation-queue.js.map +1 -0
- package/dist/daemon/index.d.ts +23 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +26 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/protocol.d.ts +40 -0
- package/dist/daemon/protocol.d.ts.map +1 -0
- package/dist/daemon/protocol.js +104 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/daemon/server.d.ts +158 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +297 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/wallet-handlers.d.ts +37 -0
- package/dist/daemon/wallet-handlers.d.ts.map +1 -0
- package/dist/daemon/wallet-handlers.js +533 -0
- package/dist/daemon/wallet-handlers.js.map +1 -0
- package/dist/daemon/wallet-rpc-parsers.d.ts +14 -0
- package/dist/daemon/wallet-rpc-parsers.d.ts.map +1 -0
- package/dist/daemon/wallet-rpc-parsers.js +259 -0
- package/dist/daemon/wallet-rpc-parsers.js.map +1 -0
- package/dist/daemon/wallet-rpc-types.d.ts +138 -0
- package/dist/daemon/wallet-rpc-types.d.ts.map +1 -0
- package/dist/daemon/wallet-rpc-types.js +11 -0
- package/dist/daemon/wallet-rpc-types.js.map +1 -0
- package/dist/diagnostics/fs-timing-store.d.ts +29 -0
- package/dist/diagnostics/fs-timing-store.d.ts.map +1 -0
- package/dist/diagnostics/fs-timing-store.js +81 -0
- package/dist/diagnostics/fs-timing-store.js.map +1 -0
- package/dist/diagnostics/timings.d.ts +64 -0
- package/dist/diagnostics/timings.d.ts.map +1 -0
- package/dist/diagnostics/timings.js +100 -0
- package/dist/diagnostics/timings.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/network/indexer-client.d.ts +66 -0
- package/dist/network/indexer-client.d.ts.map +1 -0
- package/dist/network/indexer-client.js +112 -0
- package/dist/network/indexer-client.js.map +1 -0
- package/dist/network/node-client.d.ts +27 -0
- package/dist/network/node-client.d.ts.map +1 -0
- package/dist/network/node-client.js +94 -0
- package/dist/network/node-client.js.map +1 -0
- package/dist/proof/client.d.ts +15 -0
- package/dist/proof/client.d.ts.map +1 -0
- package/dist/proof/client.js +77 -0
- package/dist/proof/client.js.map +1 -0
- package/dist/proof/provider.d.ts +12 -0
- package/dist/proof/provider.d.ts.map +1 -0
- package/dist/proof/provider.js +96 -0
- package/dist/proof/provider.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/midnight-provider.d.ts +11 -0
- package/dist/providers/midnight-provider.d.ts.map +1 -0
- package/dist/providers/midnight-provider.js +30 -0
- package/dist/providers/midnight-provider.js.map +1 -0
- package/dist/storage/adapter.d.ts +8 -0
- package/dist/storage/adapter.d.ts.map +1 -0
- package/dist/storage/adapter.js +2 -0
- package/dist/storage/adapter.js.map +1 -0
- package/dist/storage/fs-adapter.d.ts +14 -0
- package/dist/storage/fs-adapter.d.ts.map +1 -0
- package/dist/storage/fs-adapter.js +126 -0
- package/dist/storage/fs-adapter.js.map +1 -0
- package/dist/storage/safe-path.d.ts +13 -0
- package/dist/storage/safe-path.d.ts.map +1 -0
- package/dist/storage/safe-path.js +35 -0
- package/dist/storage/safe-path.js.map +1 -0
- package/dist/sync/activity.d.ts +53 -0
- package/dist/sync/activity.d.ts.map +1 -0
- package/dist/sync/activity.js +92 -0
- package/dist/sync/activity.js.map +1 -0
- package/dist/sync/dust-registration-estimate.d.ts +54 -0
- package/dist/sync/dust-registration-estimate.d.ts.map +1 -0
- package/dist/sync/dust-registration-estimate.js +103 -0
- package/dist/sync/dust-registration-estimate.js.map +1 -0
- package/dist/sync/node-sync-store.d.ts +10 -0
- package/dist/sync/node-sync-store.d.ts.map +1 -0
- package/dist/sync/node-sync-store.js +42 -0
- package/dist/sync/node-sync-store.js.map +1 -0
- package/dist/sync/operations.d.ts +138 -0
- package/dist/sync/operations.d.ts.map +1 -0
- package/dist/sync/operations.js +395 -0
- package/dist/sync/operations.js.map +1 -0
- package/dist/sync/preseed-parts.d.ts +18 -0
- package/dist/sync/preseed-parts.d.ts.map +1 -0
- package/dist/sync/preseed-parts.js +33 -0
- package/dist/sync/preseed-parts.js.map +1 -0
- package/dist/sync/preseed.d.ts +95 -0
- package/dist/sync/preseed.d.ts.map +1 -0
- package/dist/sync/preseed.js +365 -0
- package/dist/sync/preseed.js.map +1 -0
- package/dist/sync/progress.d.ts +45 -0
- package/dist/sync/progress.d.ts.map +1 -0
- package/dist/sync/progress.js +51 -0
- package/dist/sync/progress.js.map +1 -0
- package/dist/sync/sdk-dedup.d.ts +53 -0
- package/dist/sync/sdk-dedup.d.ts.map +1 -0
- package/dist/sync/sdk-dedup.js +134 -0
- package/dist/sync/sdk-dedup.js.map +1 -0
- package/dist/sync/sync-store.d.ts +33 -0
- package/dist/sync/sync-store.d.ts.map +1 -0
- package/dist/sync/sync-store.js +45 -0
- package/dist/sync/sync-store.js.map +1 -0
- package/dist/sync/wallet-sync.d.ts +153 -0
- package/dist/sync/wallet-sync.d.ts.map +1 -0
- package/dist/sync/wallet-sync.js +943 -0
- package/dist/sync/wallet-sync.js.map +1 -0
- package/dist/types/errors.d.ts +18 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +33 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/exit-codes.d.ts +8 -0
- package/dist/types/exit-codes.d.ts.map +1 -0
- package/dist/types/exit-codes.js +7 -0
- package/dist/types/exit-codes.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/network.d.ts +65 -0
- package/dist/types/network.d.ts.map +1 -0
- package/dist/types/network.js +108 -0
- package/dist/types/network.js.map +1 -0
- package/dist/types/tokens.d.ts +3 -0
- package/dist/types/tokens.d.ts.map +1 -0
- package/dist/types/tokens.js +11 -0
- package/dist/types/tokens.js.map +1 -0
- package/dist/types/transaction.d.ts +13 -0
- package/dist/types/transaction.d.ts.map +1 -0
- package/dist/types/transaction.js +2 -0
- package/dist/types/transaction.js.map +1 -0
- package/dist/types/wallet.d.ts +82 -0
- package/dist/types/wallet.d.ts.map +1 -0
- package/dist/types/wallet.js +2 -0
- package/dist/types/wallet.js.map +1 -0
- package/dist/wallet/address-validate.d.ts +7 -0
- package/dist/wallet/address-validate.d.ts.map +1 -0
- package/dist/wallet/address-validate.js +28 -0
- package/dist/wallet/address-validate.js.map +1 -0
- package/dist/wallet/address.d.ts +32 -0
- package/dist/wallet/address.d.ts.map +1 -0
- package/dist/wallet/address.js +107 -0
- package/dist/wallet/address.js.map +1 -0
- package/dist/wallet/app-secret.d.ts +15 -0
- package/dist/wallet/app-secret.d.ts.map +1 -0
- package/dist/wallet/app-secret.js +45 -0
- package/dist/wallet/app-secret.js.map +1 -0
- package/dist/wallet/balance-format.d.ts +12 -0
- package/dist/wallet/balance-format.d.ts.map +1 -0
- package/dist/wallet/balance-format.js +51 -0
- package/dist/wallet/balance-format.js.map +1 -0
- package/dist/wallet/batch-transfer.d.ts +36 -0
- package/dist/wallet/batch-transfer.d.ts.map +1 -0
- package/dist/wallet/batch-transfer.js +93 -0
- package/dist/wallet/batch-transfer.js.map +1 -0
- package/dist/wallet/keystore.d.ts +16 -0
- package/dist/wallet/keystore.d.ts.map +1 -0
- package/dist/wallet/keystore.js +76 -0
- package/dist/wallet/keystore.js.map +1 -0
- package/dist/wallet/manager.d.ts +77 -0
- package/dist/wallet/manager.d.ts.map +1 -0
- package/dist/wallet/manager.js +474 -0
- package/dist/wallet/manager.js.map +1 -0
- package/dist/wallet/mnemonic.d.ts +5 -0
- package/dist/wallet/mnemonic.d.ts.map +1 -0
- package/dist/wallet/mnemonic.js +28 -0
- package/dist/wallet/mnemonic.js.map +1 -0
- package/dist/wallet/sign-message.d.ts +20 -0
- package/dist/wallet/sign-message.d.ts.map +1 -0
- package/dist/wallet/sign-message.js +58 -0
- package/dist/wallet/sign-message.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Address derivation for Midnight wallets.
|
|
2
|
+
// Uses the same derivation as mn-tui and the official wallet SDK.
|
|
3
|
+
// See NOTICE for attribution to mn-tui (Apache-2.0).
|
|
4
|
+
import { HDWallet, Roles } from '@midnightntwrk/wallet-sdk/hd';
|
|
5
|
+
import { ZswapSecretKeys, DustSecretKey } from '@midnight-ntwrk/ledger-v8';
|
|
6
|
+
import { ShieldedAddress, ShieldedCoinPublicKey, ShieldedEncryptionPublicKey, DustAddress, MidnightBech32m, } from '@midnightntwrk/wallet-sdk/address-format';
|
|
7
|
+
import { createKeystore } from '@midnightntwrk/wallet-sdk/unshielded';
|
|
8
|
+
import { setNetworkId } from '@midnight-ntwrk/midnight-js/network-id';
|
|
9
|
+
const ALL_NETWORKS = ['mainnet', 'devnet', 'preview', 'preprod', 'qanet', 'stagenet', 'local', 'undeployed'];
|
|
10
|
+
export { Roles };
|
|
11
|
+
/**
|
|
12
|
+
* Derive raw HD keys from a hex seed using the wallet SDK's HDWallet.
|
|
13
|
+
*/
|
|
14
|
+
export function deriveRawKeys(seedHex) {
|
|
15
|
+
const hdWallet = HDWallet.fromSeed(Buffer.from(seedHex, 'hex'));
|
|
16
|
+
if (hdWallet.type !== 'seedOk')
|
|
17
|
+
throw new Error('Invalid seed');
|
|
18
|
+
const result = hdWallet.hdWallet
|
|
19
|
+
.selectAccount(0)
|
|
20
|
+
.selectRoles([Roles.NightExternal, Roles.NightInternal, Roles.Dust, Roles.Zswap, Roles.Metadata])
|
|
21
|
+
.deriveKeysAt(0);
|
|
22
|
+
if (result.type !== 'keysDerived')
|
|
23
|
+
throw new Error('Key derivation failed');
|
|
24
|
+
hdWallet.hdWallet.clear();
|
|
25
|
+
return result.keys;
|
|
26
|
+
}
|
|
27
|
+
function toHex(bytes) {
|
|
28
|
+
return Array.from(bytes)
|
|
29
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
30
|
+
.join('');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Derive proper Midnight addresses for a specific network.
|
|
34
|
+
*
|
|
35
|
+
* - Unshielded: createKeystore(secretKey) → Ed25519 public key → bech32m
|
|
36
|
+
* - Shielded: ZswapSecretKeys.fromSeed() → coin + encryption public keys
|
|
37
|
+
* - DUST: DustSecretKey.fromSeed() → public key → DustAddress
|
|
38
|
+
*/
|
|
39
|
+
function deriveForNetwork(keys, network) {
|
|
40
|
+
setNetworkId(network);
|
|
41
|
+
const unshielded = createKeystore(keys[Roles.NightExternal], network).getBech32Address().toString();
|
|
42
|
+
const unshieldedInternal = createKeystore(keys[Roles.NightInternal], network).getBech32Address().toString();
|
|
43
|
+
const zswapKeys = ZswapSecretKeys.fromSeed(keys[Roles.Zswap]);
|
|
44
|
+
const shielded = MidnightBech32m.encode(network, new ShieldedAddress(ShieldedCoinPublicKey.fromHexString(zswapKeys.coinPublicKey), ShieldedEncryptionPublicKey.fromHexString(zswapKeys.encryptionPublicKey))).toString();
|
|
45
|
+
const dustKey = DustSecretKey.fromSeed(keys[Roles.Dust]);
|
|
46
|
+
const dust = DustAddress.encodePublicKey(network, dustKey.publicKey);
|
|
47
|
+
const metadata = createKeystore(keys[Roles.Metadata], network).getBech32Address().toString();
|
|
48
|
+
return { unshielded, unshieldedInternal, shielded, dust, metadata };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Derive all Midnight addresses from a hex seed, for all networks.
|
|
52
|
+
*/
|
|
53
|
+
export function deriveAllAddressesFromSeed(seedHex) {
|
|
54
|
+
const keys = deriveRawKeys(seedHex);
|
|
55
|
+
const ne = {};
|
|
56
|
+
const ni = {};
|
|
57
|
+
const du = {};
|
|
58
|
+
const zs = {};
|
|
59
|
+
const md = {};
|
|
60
|
+
for (const network of ALL_NETWORKS) {
|
|
61
|
+
const addrs = deriveForNetwork(keys, network);
|
|
62
|
+
ne[network] = addrs.unshielded;
|
|
63
|
+
ni[network] = addrs.unshieldedInternal;
|
|
64
|
+
du[network] = addrs.dust;
|
|
65
|
+
zs[network] = addrs.shielded;
|
|
66
|
+
md[network] = addrs.metadata;
|
|
67
|
+
}
|
|
68
|
+
// SECURITY: Do NOT expose raw role key bytes as hex — those are private keys.
|
|
69
|
+
// Only public address encodings (bech32m) are safe to display/store/transmit.
|
|
70
|
+
return {
|
|
71
|
+
nightExternal: { hex: '', bech32m: ne },
|
|
72
|
+
nightInternal: { hex: '', bech32m: ni },
|
|
73
|
+
dust: { hex: '', bech32m: du },
|
|
74
|
+
zswap: { hex: '', bech32m: zs },
|
|
75
|
+
metadata: { hex: '', bech32m: md },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Derive the shielded (Zswap) coin + encryption PUBLIC keys from a hex seed,
|
|
80
|
+
* as canonical hex strings. These are public keys (network-independent, the
|
|
81
|
+
* same across all networks) and are safe to expose to a connected dApp — unlike
|
|
82
|
+
* the raw role key bytes. The combined, network-scoped shielded address is
|
|
83
|
+
* available separately via {@link deriveAllAddressesFromSeed} (`zswap`).
|
|
84
|
+
*/
|
|
85
|
+
export function deriveShieldedPublicKeys(seedHex) {
|
|
86
|
+
const keys = deriveRawKeys(seedHex);
|
|
87
|
+
const zswapKeys = ZswapSecretKeys.fromSeed(keys[Roles.Zswap]);
|
|
88
|
+
return {
|
|
89
|
+
coinPublicKey: zswapKeys.coinPublicKey,
|
|
90
|
+
encryptionPublicKey: zswapKeys.encryptionPublicKey,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* @deprecated Use deriveAllAddressesFromSeed with the hex seed.
|
|
95
|
+
*/
|
|
96
|
+
export function deriveAllAddresses() {
|
|
97
|
+
throw new Error('deriveAllAddresses is deprecated — use deriveAllAddressesFromSeed(seedHex)');
|
|
98
|
+
}
|
|
99
|
+
export function decodeBech32mAddress(address) {
|
|
100
|
+
const parsed = MidnightBech32m.parse(address);
|
|
101
|
+
return {
|
|
102
|
+
type: parsed.type,
|
|
103
|
+
network: typeof parsed.network === 'symbol' ? 'mainnet' : String(parsed.network),
|
|
104
|
+
data: new Uint8Array(parsed.data),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","sourceRoot":"","sources":["../../src/wallet/address.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a 32-byte hex app secret for `(seedHex, origin, domain)`. Same inputs
|
|
3
|
+
* always yield the same secret.
|
|
4
|
+
*
|
|
5
|
+
* SECURITY:
|
|
6
|
+
* - `origin` MUST be supplied by the wallet from the connection session, never
|
|
7
|
+
* from DApp params — that is what stops one site deriving another's secret.
|
|
8
|
+
* - IKM is the Metadata role key: non-spending and used elsewhere only to
|
|
9
|
+
* derive a *public* identity address, so a leaked app secret can never expose
|
|
10
|
+
* the seed, the unshielded signing key, or the Zswap/Dust spend keys. HKDF's
|
|
11
|
+
* one-way extract-then-expand over the private role key also makes the output
|
|
12
|
+
* independent of (and non-correlatable to) that public address.
|
|
13
|
+
*/
|
|
14
|
+
export declare function deriveAppSecret(seedHex: string, origin: string, domain: string): Promise<string>;
|
|
15
|
+
//# sourceMappingURL=app-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-secret.d.ts","sourceRoot":"","sources":["../../src/wallet/app-secret.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Deterministic per-(origin, domain) app secret for DApps — the wallet-side
|
|
2
|
+
// primitive behind the connector's `deriveAppSecret`. HKDF-SHA-256 over a
|
|
3
|
+
// non-spending HD role key gives a secret that is simultaneously:
|
|
4
|
+
// (1) private-key-bound — not recomputable from any public value,
|
|
5
|
+
// (2) deterministic/portable — reproducible from the seed on any device,
|
|
6
|
+
// (3) stateless — nothing to back up beyond the seed.
|
|
7
|
+
// See specs/003-derive-app-secret/spec.md.
|
|
8
|
+
//
|
|
9
|
+
// The v1 salt/info strings are NORMATIVE and vendor-neutral ("midnight:", not
|
|
10
|
+
// "moth:") on purpose: this prototype and a future @midnightntwrk/wallet-sdk
|
|
11
|
+
// version must produce BYTE-IDENTICAL secrets so adopters never re-derive. Do
|
|
12
|
+
// NOT change any of them within v1 — a change is a new version tag (v2), never
|
|
13
|
+
// an in-place edit. See specs/003-derive-app-secret/wallet-sdk-upstream.md §3.
|
|
14
|
+
import { Roles, deriveRawKeys } from './address.js';
|
|
15
|
+
/** Normative v1 domain-separation tag. Pinned — see file header. */
|
|
16
|
+
const APP_SECRET_V1 = 'midnight:dapp-app-secret:v1';
|
|
17
|
+
const APP_SECRET_SALT = new TextEncoder().encode(APP_SECRET_V1);
|
|
18
|
+
/**
|
|
19
|
+
* Derive a 32-byte hex app secret for `(seedHex, origin, domain)`. Same inputs
|
|
20
|
+
* always yield the same secret.
|
|
21
|
+
*
|
|
22
|
+
* SECURITY:
|
|
23
|
+
* - `origin` MUST be supplied by the wallet from the connection session, never
|
|
24
|
+
* from DApp params — that is what stops one site deriving another's secret.
|
|
25
|
+
* - IKM is the Metadata role key: non-spending and used elsewhere only to
|
|
26
|
+
* derive a *public* identity address, so a leaked app secret can never expose
|
|
27
|
+
* the seed, the unshielded signing key, or the Zswap/Dust spend keys. HKDF's
|
|
28
|
+
* one-way extract-then-expand over the private role key also makes the output
|
|
29
|
+
* independent of (and non-correlatable to) that public address.
|
|
30
|
+
*/
|
|
31
|
+
export async function deriveAppSecret(seedHex, origin, domain) {
|
|
32
|
+
const keys = deriveRawKeys(seedHex);
|
|
33
|
+
// Copy into a fresh ArrayBuffer-backed view: deriveRawKeys returns
|
|
34
|
+
// Uint8Array<ArrayBufferLike>, which WebCrypto's BufferSource type rejects.
|
|
35
|
+
const ikm = new Uint8Array(keys[Roles.Metadata]);
|
|
36
|
+
// origin + domain fold into `info` so different sites and different labels
|
|
37
|
+
// yield independent, non-correlatable secrets.
|
|
38
|
+
const info = new TextEncoder().encode(`${APP_SECRET_V1}|${origin}|${domain}`);
|
|
39
|
+
const key = await crypto.subtle.importKey('raw', ikm, 'HKDF', false, ['deriveBits']);
|
|
40
|
+
const bits = await crypto.subtle.deriveBits({ name: 'HKDF', hash: 'SHA-256', salt: APP_SECRET_SALT, info }, key, 256);
|
|
41
|
+
return Array.from(new Uint8Array(bits))
|
|
42
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
43
|
+
.join('');
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=app-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-secret.js","sourceRoot":"","sources":["../../src/wallet/app-secret.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,kEAAkE;AAClE,qEAAqE;AACrE,2EAA2E;AAC3E,wDAAwD;AACxD,2CAA2C;AAC3C,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAE/E,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEpD,oEAAoE;AACpE,MAAM,aAAa,GAAG,6BAA6B,CAAC;AACpD,MAAM,eAAe,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAe,EACf,MAAc,EACd,MAAc;IAEd,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,mEAAmE;IACnE,4EAA4E;IAC5E,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjD,2EAA2E;IAC3E,+CAA+C;IAC/C,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,aAAa,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;IAE9E,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CACzC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,EAC9D,GAAG,EACH,GAAG,CACJ,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;SACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** STAR per NIGHT: 1 NIGHT = 10^6 STAR. */
|
|
2
|
+
export declare const NIGHT_DENOMINATION: bigint;
|
|
3
|
+
/** SPECK per DUST: 1 DUST = 10^15 SPECK. */
|
|
4
|
+
export declare const DUST_DENOMINATION: bigint;
|
|
5
|
+
/**
|
|
6
|
+
* Generic balance formatter. Divides by the supplied denomination and
|
|
7
|
+
* applies decimal-place + scale-suffix (K/M/B/T) formatting.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatBalance(balance: bigint, denomination?: bigint): string;
|
|
10
|
+
/** SPECK → DUST display. 1 DUST = 10^15 SPECK. */
|
|
11
|
+
export declare function formatDustBalance(speckBalance: bigint): string;
|
|
12
|
+
//# sourceMappingURL=balance-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balance-format.d.ts","sourceRoot":"","sources":["../../src/wallet/balance-format.ts"],"names":[],"mappings":"AAUA,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,EAAE,MAAwB,CAAC;AAE1D,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,EAAE,MAAyB,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAE,MAA2B,GAAG,MAAM,CAkBhG;AAaD,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE9D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Pure formatting helpers for wallet balances. Shared between the TUI
|
|
2
|
+
// (for dashboard rendering) and the daemon handlers (for L3 modal
|
|
3
|
+
// summaries).
|
|
4
|
+
//
|
|
5
|
+
// Midnight denominations:
|
|
6
|
+
// 1 NIGHT = 10^6 STAR (the smallest NIGHT unit)
|
|
7
|
+
// 1 DUST = 10^15 SPECK (the smallest DUST unit; DUST is non-transferable)
|
|
8
|
+
// All other (contract-issued) tokens have no protocol-level decimals and
|
|
9
|
+
// are displayed as raw integers.
|
|
10
|
+
/** STAR per NIGHT: 1 NIGHT = 10^6 STAR. */
|
|
11
|
+
export const NIGHT_DENOMINATION = BigInt(10 ** 6);
|
|
12
|
+
/** SPECK per DUST: 1 DUST = 10^15 SPECK. */
|
|
13
|
+
export const DUST_DENOMINATION = BigInt(10 ** 15);
|
|
14
|
+
/**
|
|
15
|
+
* Generic balance formatter. Divides by the supplied denomination and
|
|
16
|
+
* applies decimal-place + scale-suffix (K/M/B/T) formatting.
|
|
17
|
+
*/
|
|
18
|
+
export function formatBalance(balance, denomination = NIGHT_DENOMINATION) {
|
|
19
|
+
const value = balance / denomination;
|
|
20
|
+
const fractionalPart = balance % denomination;
|
|
21
|
+
const trillion = 1000000000000n;
|
|
22
|
+
const billion = 1000000000n;
|
|
23
|
+
const million = 1000000n;
|
|
24
|
+
if (value >= trillion)
|
|
25
|
+
return formatScaled(value, fractionalPart, trillion, 'T');
|
|
26
|
+
if (value >= billion)
|
|
27
|
+
return formatScaled(value, fractionalPart, billion, 'B');
|
|
28
|
+
if (value >= million)
|
|
29
|
+
return formatScaled(value, fractionalPart, million, 'M');
|
|
30
|
+
const wholeStr = value.toLocaleString('en-US');
|
|
31
|
+
if (fractionalPart > 0n) {
|
|
32
|
+
const fractionalStr = fractionalPart.toString().padStart(6, '0').replace(/0+$/, '');
|
|
33
|
+
return `${wholeStr}.${fractionalStr}`;
|
|
34
|
+
}
|
|
35
|
+
return wholeStr;
|
|
36
|
+
}
|
|
37
|
+
function formatScaled(value, fractionalPart, scale, suffix) {
|
|
38
|
+
const whole = value / scale;
|
|
39
|
+
const remainder = value % scale;
|
|
40
|
+
const decimalPart = Number((remainder * 100n) / scale);
|
|
41
|
+
if (decimalPart === 0 && fractionalPart === 0n) {
|
|
42
|
+
return `${whole.toLocaleString('en-US')}${suffix}`;
|
|
43
|
+
}
|
|
44
|
+
const decimalStr = (decimalPart / 100).toFixed(2).substring(1).replace(/\.?0+$/, '');
|
|
45
|
+
return `${whole.toLocaleString('en-US')}${decimalStr}${suffix}`;
|
|
46
|
+
}
|
|
47
|
+
/** SPECK → DUST display. 1 DUST = 10^15 SPECK. */
|
|
48
|
+
export function formatDustBalance(speckBalance) {
|
|
49
|
+
return formatBalance(speckBalance, DUST_DENOMINATION);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=balance-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balance-format.js","sourceRoot":"","sources":["../../src/wallet/balance-format.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,kEAAkE;AAClE,cAAc;AACd,EAAE;AACF,0BAA0B;AAC1B,mDAAmD;AACnD,6EAA6E;AAC7E,yEAAyE;AACzE,iCAAiC;AAEjC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAW,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAE1D,4CAA4C;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAW,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AAE1D;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,eAAuB,kBAAkB;IACtF,MAAM,KAAK,GAAG,OAAO,GAAG,YAAY,CAAC;IACrC,MAAM,cAAc,GAAG,OAAO,GAAG,YAAY,CAAC;IAE9C,MAAM,QAAQ,GAAG,cAAkB,CAAC;IACpC,MAAM,OAAO,GAAG,WAAc,CAAC;IAC/B,MAAM,OAAO,GAAG,QAAU,CAAC;IAE3B,IAAI,KAAK,IAAI,QAAQ;QAAE,OAAO,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IACjF,IAAI,KAAK,IAAI,OAAO;QAAE,OAAO,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC/E,IAAI,KAAK,IAAI,OAAO;QAAE,OAAO,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAE/E,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,cAAc,GAAG,EAAE,EAAE,CAAC;QACxB,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpF,OAAO,GAAG,QAAQ,IAAI,aAAa,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,cAAsB,EAAE,KAAa,EAAE,MAAc;IACxF,MAAM,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5B,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;IAChC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IACvD,IAAI,WAAW,KAAK,CAAC,IAAI,cAAc,KAAK,EAAE,EAAE,CAAC;QAC/C,OAAO,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrF,OAAO,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,UAAU,GAAG,MAAM,EAAE,CAAC;AAClE,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,OAAO,aAAa,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type TxStage, type WalletKeys } from '../sync/operations.js';
|
|
2
|
+
export interface BatchTransferEntry {
|
|
3
|
+
to: string;
|
|
4
|
+
amount: string;
|
|
5
|
+
shielded?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface BatchTransferResult {
|
|
8
|
+
index: number;
|
|
9
|
+
to: string;
|
|
10
|
+
amount: string;
|
|
11
|
+
status: 'success' | 'error';
|
|
12
|
+
txHash?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface BatchTransferSummary {
|
|
16
|
+
total: number;
|
|
17
|
+
succeeded: number;
|
|
18
|
+
failed: number;
|
|
19
|
+
results: BatchTransferResult[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load batch transfer list from a JSON file.
|
|
23
|
+
* Expected format: array of { to, amount, shielded? }
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadBatchFile(path: string): BatchTransferEntry[];
|
|
26
|
+
/**
|
|
27
|
+
* Execute batch transfers sequentially.
|
|
28
|
+
* Returns summary with per-item results and three-tier exit code:
|
|
29
|
+
* 0 = all succeeded, 1 = some failed, 2 = all failed
|
|
30
|
+
*/
|
|
31
|
+
export declare function executeBatchTransfer(facade: any, walletKeys: WalletKeys, networkId: string, entries: BatchTransferEntry[], onProgress?: (index: number, stage: TxStage) => void): Promise<BatchTransferSummary>;
|
|
32
|
+
/**
|
|
33
|
+
* Three-tier exit code from batch results.
|
|
34
|
+
*/
|
|
35
|
+
export declare function batchExitCode(summary: BatchTransferSummary): 0 | 1 | 2;
|
|
36
|
+
//# sourceMappingURL=batch-transfer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-transfer.d.ts","sourceRoot":"","sources":["../../src/wallet/batch-transfer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwC,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAG5G,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAgBhE;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,GACnD,OAAO,CAAC,oBAAoB,CAAC,CAqD/B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAItE"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Batch transfer — load transfer list from JSON, execute sequentially, collect results.
|
|
2
|
+
// Supports file input or direct array input.
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { sendTokensWithKeys } from '../sync/operations.js';
|
|
5
|
+
import { NIGHT_TOKEN_ID } from '../sync/wallet-sync.js';
|
|
6
|
+
/**
|
|
7
|
+
* Load batch transfer list from a JSON file.
|
|
8
|
+
* Expected format: array of { to, amount, shielded? }
|
|
9
|
+
*/
|
|
10
|
+
export function loadBatchFile(path) {
|
|
11
|
+
const raw = readFileSync(path, 'utf-8');
|
|
12
|
+
const parsed = JSON.parse(raw);
|
|
13
|
+
if (!Array.isArray(parsed)) {
|
|
14
|
+
throw new Error('Batch file must contain a JSON array of transfer entries');
|
|
15
|
+
}
|
|
16
|
+
for (let i = 0; i < parsed.length; i++) {
|
|
17
|
+
const entry = parsed[i];
|
|
18
|
+
if (!entry.to || typeof entry.to !== 'string') {
|
|
19
|
+
throw new Error(`Entry ${i}: missing or invalid "to" address`);
|
|
20
|
+
}
|
|
21
|
+
if (!entry.amount || typeof entry.amount !== 'string') {
|
|
22
|
+
throw new Error(`Entry ${i}: missing or invalid "amount" (must be string)`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute batch transfers sequentially.
|
|
29
|
+
* Returns summary with per-item results and three-tier exit code:
|
|
30
|
+
* 0 = all succeeded, 1 = some failed, 2 = all failed
|
|
31
|
+
*/
|
|
32
|
+
export async function executeBatchTransfer(facade, walletKeys, networkId, entries, onProgress) {
|
|
33
|
+
const results = [];
|
|
34
|
+
for (let i = 0; i < entries.length; i++) {
|
|
35
|
+
const entry = entries[i];
|
|
36
|
+
const parsed = parseFloat(entry.amount);
|
|
37
|
+
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
38
|
+
results.push({
|
|
39
|
+
index: i,
|
|
40
|
+
to: entry.to,
|
|
41
|
+
amount: entry.amount,
|
|
42
|
+
status: 'error',
|
|
43
|
+
error: `Invalid amount: ${entry.amount}`,
|
|
44
|
+
});
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const req = {
|
|
48
|
+
type: entry.shielded ? 'shielded' : 'unshielded',
|
|
49
|
+
tokenId: NIGHT_TOKEN_ID,
|
|
50
|
+
amount: BigInt(Math.round(parsed * 1_000_000)),
|
|
51
|
+
to: entry.to,
|
|
52
|
+
};
|
|
53
|
+
try {
|
|
54
|
+
const txHash = await sendTokensWithKeys(facade, walletKeys, networkId, [req], (stage) => {
|
|
55
|
+
onProgress?.(i, stage);
|
|
56
|
+
});
|
|
57
|
+
results.push({
|
|
58
|
+
index: i,
|
|
59
|
+
to: entry.to,
|
|
60
|
+
amount: entry.amount,
|
|
61
|
+
status: 'success',
|
|
62
|
+
txHash,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
results.push({
|
|
67
|
+
index: i,
|
|
68
|
+
to: entry.to,
|
|
69
|
+
amount: entry.amount,
|
|
70
|
+
status: 'error',
|
|
71
|
+
error: err instanceof Error ? err.message : String(err),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const succeeded = results.filter(r => r.status === 'success').length;
|
|
76
|
+
return {
|
|
77
|
+
total: entries.length,
|
|
78
|
+
succeeded,
|
|
79
|
+
failed: entries.length - succeeded,
|
|
80
|
+
results,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Three-tier exit code from batch results.
|
|
85
|
+
*/
|
|
86
|
+
export function batchExitCode(summary) {
|
|
87
|
+
if (summary.failed === 0)
|
|
88
|
+
return 0;
|
|
89
|
+
if (summary.succeeded === 0)
|
|
90
|
+
return 1;
|
|
91
|
+
return 2;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=batch-transfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-transfer.js","sourceRoot":"","sources":["../../src/wallet/batch-transfer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface EncryptedKeystore {
|
|
2
|
+
readonly version: number;
|
|
3
|
+
readonly algorithm: string;
|
|
4
|
+
readonly salt: Uint8Array;
|
|
5
|
+
readonly nonce: Uint8Array;
|
|
6
|
+
readonly ciphertext: Uint8Array;
|
|
7
|
+
readonly tag: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
declare const KEYSTORE_VERSION = 2;
|
|
10
|
+
export declare function encryptKeystore(mnemonic: string, passphrase: string): Promise<EncryptedKeystore>;
|
|
11
|
+
/** Current keystore version — new keystores are always created at this version */
|
|
12
|
+
export { KEYSTORE_VERSION };
|
|
13
|
+
/** Check if a keystore needs re-encryption with stronger KDF parameters */
|
|
14
|
+
export declare function keystoreNeedsUpgrade(keystore: EncryptedKeystore): boolean;
|
|
15
|
+
export declare function decryptKeystore(keystore: EncryptedKeystore, passphrase: string): Promise<string>;
|
|
16
|
+
//# sourceMappingURL=keystore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../../src/wallet/keystore.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;CAC1B;AAED,QAAA,MAAM,gBAAgB,IAAI,CAAC;AA+B3B,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAwB5B;AAED,kFAAkF;AAClF,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAEzE;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { chacha20poly1305 } from '@noble/ciphers/chacha.js';
|
|
2
|
+
import { randomBytes } from '@noble/ciphers/utils.js';
|
|
3
|
+
import { scrypt } from '@noble/hashes/scrypt.js';
|
|
4
|
+
const KEYSTORE_VERSION = 2;
|
|
5
|
+
const ALGORITHM = 'chacha20-poly1305';
|
|
6
|
+
const SALT_LENGTH = 32;
|
|
7
|
+
const NONCE_LENGTH = 12;
|
|
8
|
+
const KEY_LENGTH = 32;
|
|
9
|
+
// scrypt parameters per keystore version.
|
|
10
|
+
// V1: N=2^15 (~8 MiB, ~50ms) — too weak for offline key storage.
|
|
11
|
+
// V2: N=2^18 (~256 MiB, ~300ms) — meets NIST SP 800-132 interactive threshold.
|
|
12
|
+
const SCRYPT_PARAMS = {
|
|
13
|
+
1: { N: 2 ** 15, r: 8, p: 1 },
|
|
14
|
+
2: { N: 2 ** 18, r: 8, p: 1 },
|
|
15
|
+
};
|
|
16
|
+
const encoder = new TextEncoder();
|
|
17
|
+
const decoder = new TextDecoder();
|
|
18
|
+
function deriveEncryptionKey(passphrase, salt, version = KEYSTORE_VERSION) {
|
|
19
|
+
const params = SCRYPT_PARAMS[version] ?? SCRYPT_PARAMS[KEYSTORE_VERSION];
|
|
20
|
+
return scrypt(encoder.encode(passphrase), salt, {
|
|
21
|
+
N: params.N,
|
|
22
|
+
r: params.r,
|
|
23
|
+
p: params.p,
|
|
24
|
+
dkLen: KEY_LENGTH,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export async function encryptKeystore(mnemonic, passphrase) {
|
|
28
|
+
const salt = randomBytes(SALT_LENGTH);
|
|
29
|
+
const nonce = randomBytes(NONCE_LENGTH);
|
|
30
|
+
const key = deriveEncryptionKey(passphrase, salt);
|
|
31
|
+
const cipher = chacha20poly1305(key, nonce);
|
|
32
|
+
const plaintext = encoder.encode(mnemonic);
|
|
33
|
+
const sealed = cipher.encrypt(plaintext);
|
|
34
|
+
// ChaCha20-Poly1305 appends 16-byte tag to ciphertext
|
|
35
|
+
const ciphertext = sealed.subarray(0, sealed.length - 16);
|
|
36
|
+
const tag = sealed.subarray(sealed.length - 16);
|
|
37
|
+
// Zero the key from memory
|
|
38
|
+
key.fill(0);
|
|
39
|
+
return {
|
|
40
|
+
version: KEYSTORE_VERSION,
|
|
41
|
+
algorithm: ALGORITHM,
|
|
42
|
+
salt,
|
|
43
|
+
nonce,
|
|
44
|
+
ciphertext,
|
|
45
|
+
tag,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Current keystore version — new keystores are always created at this version */
|
|
49
|
+
export { KEYSTORE_VERSION };
|
|
50
|
+
/** Check if a keystore needs re-encryption with stronger KDF parameters */
|
|
51
|
+
export function keystoreNeedsUpgrade(keystore) {
|
|
52
|
+
return keystore.version < KEYSTORE_VERSION;
|
|
53
|
+
}
|
|
54
|
+
export async function decryptKeystore(keystore, passphrase) {
|
|
55
|
+
if (!SCRYPT_PARAMS[keystore.version]) {
|
|
56
|
+
throw new Error(`Unsupported keystore version: ${keystore.version} (supported: ${Object.keys(SCRYPT_PARAMS).join(', ')})`);
|
|
57
|
+
}
|
|
58
|
+
// Derive key using the version-specific scrypt parameters
|
|
59
|
+
const key = deriveEncryptionKey(passphrase, keystore.salt, keystore.version);
|
|
60
|
+
// Reconstruct sealed message (ciphertext + tag)
|
|
61
|
+
const sealed = new Uint8Array(keystore.ciphertext.length + keystore.tag.length);
|
|
62
|
+
sealed.set(keystore.ciphertext);
|
|
63
|
+
sealed.set(keystore.tag, keystore.ciphertext.length);
|
|
64
|
+
const cipher = chacha20poly1305(key, keystore.nonce);
|
|
65
|
+
try {
|
|
66
|
+
const plaintext = cipher.decrypt(sealed);
|
|
67
|
+
return decoder.decode(plaintext);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new Error('Decryption failed: invalid passphrase or corrupted keystore');
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
key.fill(0);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=keystore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keystore.js","sourceRoot":"","sources":["../../src/wallet/keystore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { StorageAdapter } from '../storage/adapter.js';
|
|
2
|
+
import type { WalletInfo, UnlockedWallet } from '../types/wallet.js';
|
|
3
|
+
export declare class WalletManager {
|
|
4
|
+
private readonly storage;
|
|
5
|
+
constructor(storage: StorageAdapter);
|
|
6
|
+
private loadConfig;
|
|
7
|
+
private saveConfig;
|
|
8
|
+
private saveMeta;
|
|
9
|
+
private loadMeta;
|
|
10
|
+
private validateName;
|
|
11
|
+
private seedToHex;
|
|
12
|
+
private deriveAddressesFromSeed;
|
|
13
|
+
/** Public night receive address, preferring the wallet's own network. */
|
|
14
|
+
private primaryAddress;
|
|
15
|
+
generate(name: string, passphrase: string, network?: string, birthday?: number, mnemonic?: string): Promise<WalletInfo & {
|
|
16
|
+
mnemonic: string;
|
|
17
|
+
}>;
|
|
18
|
+
import(name: string, mnemonic: string, passphrase: string, network?: string): Promise<WalletInfo>;
|
|
19
|
+
importFromSeed(name: string, hexSeed: string, passphrase: string, network?: string): Promise<WalletInfo>;
|
|
20
|
+
/** Read and revive a wallet's keystore from storage (JSON round-trips
|
|
21
|
+
* Uint8Array fields as index-keyed objects). */
|
|
22
|
+
private readKeystore;
|
|
23
|
+
unlock(name: string, passphrase: string): Promise<UnlockedWallet>;
|
|
24
|
+
/**
|
|
25
|
+
* Recover the raw BIP-39 hex seed for a wallet.
|
|
26
|
+
*
|
|
27
|
+
* This is the ONE deliberate exception to Option A's derive-and-drop
|
|
28
|
+
* (D-KM-3): the common `unlock()` path derives `walletKeys` and drops the
|
|
29
|
+
* seed so `UnlockedWallet` is seed-free, and the daemon/CLI/multi-tenant
|
|
30
|
+
* host never see raw seed material. But the browser extension's offscreen
|
|
31
|
+
* document is the key-holder, and Chrome tears it down and recreates it at
|
|
32
|
+
* will — the WASM `walletKeys` cannot cross the runtime-message boundary, so
|
|
33
|
+
* the offscreen needs a *serializable* secret the background can re-supply to
|
|
34
|
+
* rebuild the key bundle after each restart. That secret is the seed.
|
|
35
|
+
*
|
|
36
|
+
* Kept off `unlock()` on purpose so the seed-free invariant holds for every
|
|
37
|
+
* caller that doesn't explicitly opt in here.
|
|
38
|
+
* See docs/spec/wallet-service/05-key-management.md D-KM-3.
|
|
39
|
+
*/
|
|
40
|
+
exportSeedHex(name: string, passphrase: string): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Recover the wallet's backup secret for a user-facing reveal: the original
|
|
43
|
+
* BIP-39 mnemonic when the wallet has one, or the raw hex seed for wallets
|
|
44
|
+
* imported from hex (no mnemonic ever existed). Passphrase-gated by the
|
|
45
|
+
* keystore decrypt itself — a wrong passphrase rejects. Same deliberate
|
|
46
|
+
* D-KM-3 opt-in rationale as exportSeedHex above.
|
|
47
|
+
*/
|
|
48
|
+
exportPhrase(name: string, passphrase: string): Promise<{
|
|
49
|
+
kind: 'mnemonic' | 'seed';
|
|
50
|
+
value: string;
|
|
51
|
+
}>;
|
|
52
|
+
remove(name: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* List wallets. Returns the name, network and public receive address (stored
|
|
55
|
+
* in the clear at create/import time). The full per-role address set and any
|
|
56
|
+
* key material still require unlock — only the primary night address is here.
|
|
57
|
+
*/
|
|
58
|
+
list(): Promise<WalletInfo[]>;
|
|
59
|
+
getActive(): Promise<string | null>;
|
|
60
|
+
setActive(name: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Set or clear a wallet's display label. Labels are presentation-only
|
|
63
|
+
* metadata: the wallet keeps its immutable `name` (the storage key), so
|
|
64
|
+
* keystores, sync caches and sessions all stay valid across renames.
|
|
65
|
+
* An empty (or whitespace-only) label reverts to showing the name.
|
|
66
|
+
*/
|
|
67
|
+
setLabel(name: string, label: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Move a wallet to another network. Only this wallet's metadata changes —
|
|
70
|
+
* other wallets keep their own networks. The public address and chain
|
|
71
|
+
* birthday are network-scoped, so the old values are discarded. A caller
|
|
72
|
+
* that already has the unlocked seed may provide the newly derived public
|
|
73
|
+
* address to keep the locked account list immediately useful.
|
|
74
|
+
*/
|
|
75
|
+
setNetwork(name: string, network: string, address?: string, birthday?: number): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/wallet/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAiD,MAAM,oBAAoB,CAAC;AAmGpH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,OAAO,EAAE,cAAc;YAIrB,UAAU;YAUV,UAAU;YAIV,QAAQ;YAIR,QAAQ;IAMtB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,uBAAuB;IAI/B,yEAAyE;IACzE,OAAO,CAAC,cAAc;IAWhB,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,SAAW,EAClB,QAAQ,CAAC,EAAE,MAAM,EAIjB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAuCvC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,SAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAgCnG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,SAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAuBhH;qDACiD;YACnC,YAAY;IAepB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA4GvE;;;;;;;;;;;;;;;OAeG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUtE;;;;;;OAMG;IACG,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAOlD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCzC;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAwB7B,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKnC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1D;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA6CpG"}
|