@unicitylabs/sphere-sdk 0.1.3 → 0.1.5
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 +110 -15
- package/dist/core/index.cjs +829 -236
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +332 -210
- package/dist/core/index.d.ts +332 -210
- package/dist/core/index.js +829 -236
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +1224 -339
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +1221 -342
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +471 -37
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +470 -36
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +1238 -345
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +142 -57
- package/dist/impl/nodejs/index.d.ts +142 -57
- package/dist/impl/nodejs/index.js +1245 -348
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +871 -235
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1395 -503
- package/dist/index.d.ts +1395 -503
- package/dist/index.js +862 -235
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1542,6 +1542,7 @@ var L1PaymentsModule = class {
|
|
|
1542
1542
|
_chainCode;
|
|
1543
1543
|
_addresses = [];
|
|
1544
1544
|
_wallet;
|
|
1545
|
+
_transport;
|
|
1545
1546
|
constructor(config) {
|
|
1546
1547
|
this._config = {
|
|
1547
1548
|
electrumUrl: config?.electrumUrl ?? "wss://fulcrum.alpha.unicity.network:50004",
|
|
@@ -1554,13 +1555,14 @@ var L1PaymentsModule = class {
|
|
|
1554
1555
|
this._identity = deps.identity;
|
|
1555
1556
|
this._chainCode = deps.chainCode;
|
|
1556
1557
|
this._addresses = deps.addresses ?? [];
|
|
1558
|
+
this._transport = deps.transport;
|
|
1557
1559
|
this._wallet = {
|
|
1558
1560
|
masterPrivateKey: deps.identity.privateKey,
|
|
1559
1561
|
chainCode: deps.chainCode,
|
|
1560
1562
|
addresses: [
|
|
1561
1563
|
{
|
|
1562
|
-
address: deps.identity.
|
|
1563
|
-
publicKey: deps.identity.
|
|
1564
|
+
address: deps.identity.l1Address,
|
|
1565
|
+
publicKey: deps.identity.chainPubkey,
|
|
1564
1566
|
privateKey: deps.identity.privateKey,
|
|
1565
1567
|
path: "m/0",
|
|
1566
1568
|
index: 0
|
|
@@ -1568,7 +1570,7 @@ var L1PaymentsModule = class {
|
|
|
1568
1570
|
]
|
|
1569
1571
|
};
|
|
1570
1572
|
for (const addr of this._addresses) {
|
|
1571
|
-
if (addr !== deps.identity.
|
|
1573
|
+
if (addr !== deps.identity.l1Address) {
|
|
1572
1574
|
this._wallet.addresses.push({
|
|
1573
1575
|
address: addr,
|
|
1574
1576
|
path: null,
|
|
@@ -1591,18 +1593,64 @@ var L1PaymentsModule = class {
|
|
|
1591
1593
|
this._addresses = [];
|
|
1592
1594
|
this._wallet = void 0;
|
|
1593
1595
|
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Check if a string looks like an L1 address (alpha1... or alphat1...)
|
|
1598
|
+
*/
|
|
1599
|
+
isL1Address(value) {
|
|
1600
|
+
return value.startsWith("alpha1") || value.startsWith("alphat1");
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* Resolve recipient to L1 address
|
|
1604
|
+
* Supports: L1 address (alpha1...), nametag (with or without @)
|
|
1605
|
+
*/
|
|
1606
|
+
async resolveL1Address(recipient) {
|
|
1607
|
+
if (recipient.startsWith("@")) {
|
|
1608
|
+
const nametag = recipient.slice(1);
|
|
1609
|
+
return this.resolveNametagToL1Address(nametag);
|
|
1610
|
+
}
|
|
1611
|
+
if (this.isL1Address(recipient)) {
|
|
1612
|
+
return recipient;
|
|
1613
|
+
}
|
|
1614
|
+
try {
|
|
1615
|
+
const l1Address = await this.resolveNametagToL1Address(recipient);
|
|
1616
|
+
return l1Address;
|
|
1617
|
+
} catch {
|
|
1618
|
+
throw new Error(
|
|
1619
|
+
`Recipient "${recipient}" is not a valid nametag or L1 address. Use @nametag for explicit nametag or a valid alpha1... address.`
|
|
1620
|
+
);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Resolve nametag to L1 address using transport provider
|
|
1625
|
+
*/
|
|
1626
|
+
async resolveNametagToL1Address(nametag) {
|
|
1627
|
+
if (!this._transport?.resolveNametagInfo) {
|
|
1628
|
+
throw new Error("Transport provider does not support nametag resolution");
|
|
1629
|
+
}
|
|
1630
|
+
const info = await this._transport.resolveNametagInfo(nametag);
|
|
1631
|
+
if (!info) {
|
|
1632
|
+
throw new Error(`Nametag not found: ${nametag}`);
|
|
1633
|
+
}
|
|
1634
|
+
if (!info.l1Address) {
|
|
1635
|
+
throw new Error(
|
|
1636
|
+
`Nametag @${nametag} does not have L1 address information. The owner needs to update their nametag registration.`
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
return info.l1Address;
|
|
1640
|
+
}
|
|
1594
1641
|
async send(request) {
|
|
1595
1642
|
this.ensureInitialized();
|
|
1596
1643
|
if (!this._wallet || !this._identity) {
|
|
1597
1644
|
return { success: false, error: "No wallet available" };
|
|
1598
1645
|
}
|
|
1599
1646
|
try {
|
|
1647
|
+
const recipientAddress = await this.resolveL1Address(request.to);
|
|
1600
1648
|
const amountAlpha = parseInt(request.amount, 10) / 1e8;
|
|
1601
1649
|
const results = await sendAlpha(
|
|
1602
1650
|
this._wallet,
|
|
1603
|
-
|
|
1651
|
+
recipientAddress,
|
|
1604
1652
|
amountAlpha,
|
|
1605
|
-
this._identity.
|
|
1653
|
+
this._identity.l1Address
|
|
1606
1654
|
);
|
|
1607
1655
|
if (results && results.length > 0) {
|
|
1608
1656
|
const txids = results.map((r) => r.txid);
|
|
@@ -1824,8 +1872,8 @@ var L1PaymentsModule = class {
|
|
|
1824
1872
|
}
|
|
1825
1873
|
_getWatchedAddresses() {
|
|
1826
1874
|
const addresses = [...this._addresses];
|
|
1827
|
-
if (this._identity?.
|
|
1828
|
-
addresses.unshift(this._identity.
|
|
1875
|
+
if (this._identity?.l1Address && !addresses.includes(this._identity.l1Address)) {
|
|
1876
|
+
addresses.unshift(this._identity.l1Address);
|
|
1829
1877
|
}
|
|
1830
1878
|
return addresses;
|
|
1831
1879
|
}
|
|
@@ -2302,48 +2350,55 @@ var NametagMinter = class {
|
|
|
2302
2350
|
// constants.ts
|
|
2303
2351
|
var STORAGE_PREFIX = "sphere_";
|
|
2304
2352
|
var DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
|
|
2305
|
-
var
|
|
2353
|
+
var STORAGE_KEYS_GLOBAL = {
|
|
2306
2354
|
/** Encrypted BIP39 mnemonic */
|
|
2307
|
-
MNEMONIC:
|
|
2355
|
+
MNEMONIC: "mnemonic",
|
|
2308
2356
|
/** Encrypted master private key */
|
|
2309
|
-
MASTER_KEY:
|
|
2357
|
+
MASTER_KEY: "master_key",
|
|
2310
2358
|
/** BIP32 chain code */
|
|
2311
|
-
CHAIN_CODE:
|
|
2359
|
+
CHAIN_CODE: "chain_code",
|
|
2312
2360
|
/** HD derivation path (full path like m/44'/0'/0'/0/0) */
|
|
2313
|
-
DERIVATION_PATH:
|
|
2361
|
+
DERIVATION_PATH: "derivation_path",
|
|
2314
2362
|
/** Base derivation path (like m/44'/0'/0' without chain/index) */
|
|
2315
|
-
BASE_PATH:
|
|
2363
|
+
BASE_PATH: "base_path",
|
|
2316
2364
|
/** Derivation mode: bip32, wif_hmac, legacy_hmac */
|
|
2317
|
-
DERIVATION_MODE:
|
|
2365
|
+
DERIVATION_MODE: "derivation_mode",
|
|
2318
2366
|
/** Wallet source: mnemonic, file, unknown */
|
|
2319
|
-
WALLET_SOURCE:
|
|
2367
|
+
WALLET_SOURCE: "wallet_source",
|
|
2320
2368
|
/** Wallet existence flag */
|
|
2321
|
-
WALLET_EXISTS:
|
|
2322
|
-
/** Registered nametag (legacy - single address) */
|
|
2323
|
-
NAMETAG: `${STORAGE_PREFIX}nametag`,
|
|
2369
|
+
WALLET_EXISTS: "wallet_exists",
|
|
2324
2370
|
/** Current active address index */
|
|
2325
|
-
CURRENT_ADDRESS_INDEX:
|
|
2326
|
-
/**
|
|
2327
|
-
ADDRESS_NAMETAGS:
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
/** Pending transfers */
|
|
2331
|
-
PENDING_TRANSFERS:
|
|
2332
|
-
/** Transfer outbox */
|
|
2333
|
-
OUTBOX:
|
|
2334
|
-
/** Conversations */
|
|
2335
|
-
CONVERSATIONS:
|
|
2336
|
-
/** Messages */
|
|
2337
|
-
MESSAGES:
|
|
2338
|
-
/** Transaction history */
|
|
2339
|
-
TRANSACTION_HISTORY:
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
/** Forked tokens (alternative histories) */
|
|
2345
|
-
FORKED_TOKENS: `${STORAGE_PREFIX}forked_tokens`
|
|
2371
|
+
CURRENT_ADDRESS_INDEX: "current_address_index",
|
|
2372
|
+
/** Index of address nametags (JSON: { "0": "alice", "1": "bob" }) - for discovery */
|
|
2373
|
+
ADDRESS_NAMETAGS: "address_nametags"
|
|
2374
|
+
};
|
|
2375
|
+
var STORAGE_KEYS_ADDRESS = {
|
|
2376
|
+
/** Pending transfers for this address */
|
|
2377
|
+
PENDING_TRANSFERS: "pending_transfers",
|
|
2378
|
+
/** Transfer outbox for this address */
|
|
2379
|
+
OUTBOX: "outbox",
|
|
2380
|
+
/** Conversations for this address */
|
|
2381
|
+
CONVERSATIONS: "conversations",
|
|
2382
|
+
/** Messages for this address */
|
|
2383
|
+
MESSAGES: "messages",
|
|
2384
|
+
/** Transaction history for this address */
|
|
2385
|
+
TRANSACTION_HISTORY: "transaction_history"
|
|
2386
|
+
};
|
|
2387
|
+
var STORAGE_KEYS = {
|
|
2388
|
+
...STORAGE_KEYS_GLOBAL,
|
|
2389
|
+
...STORAGE_KEYS_ADDRESS
|
|
2346
2390
|
};
|
|
2391
|
+
function getAddressId(directAddress) {
|
|
2392
|
+
let hash = directAddress;
|
|
2393
|
+
if (hash.startsWith("DIRECT://")) {
|
|
2394
|
+
hash = hash.slice(9);
|
|
2395
|
+
} else if (hash.startsWith("DIRECT:")) {
|
|
2396
|
+
hash = hash.slice(7);
|
|
2397
|
+
}
|
|
2398
|
+
const first = hash.slice(0, 6).toLowerCase();
|
|
2399
|
+
const last = hash.slice(-6).toLowerCase();
|
|
2400
|
+
return `DIRECT_${first}_${last}`;
|
|
2401
|
+
}
|
|
2347
2402
|
var DEFAULT_NOSTR_RELAYS = [
|
|
2348
2403
|
"wss://relay.unicity.network",
|
|
2349
2404
|
"wss://relay.damus.io",
|
|
@@ -2606,6 +2661,7 @@ function txfToToken(tokenId, txf) {
|
|
|
2606
2661
|
coinId,
|
|
2607
2662
|
symbol: isNft ? "NFT" : "UCT",
|
|
2608
2663
|
name: isNft ? "NFT" : "Token",
|
|
2664
|
+
decimals: isNft ? 0 : 8,
|
|
2609
2665
|
amount: totalAmount.toString(),
|
|
2610
2666
|
status: determineTokenStatus(txf),
|
|
2611
2667
|
createdAt: now,
|
|
@@ -2620,9 +2676,6 @@ async function buildTxfStorageData(tokens, meta, options) {
|
|
|
2620
2676
|
formatVersion: "2.0"
|
|
2621
2677
|
}
|
|
2622
2678
|
};
|
|
2623
|
-
if (options?.nametag) {
|
|
2624
|
-
storageData._nametag = options.nametag;
|
|
2625
|
-
}
|
|
2626
2679
|
if (options?.tombstones && options.tombstones.length > 0) {
|
|
2627
2680
|
storageData._tombstones = options.tombstones;
|
|
2628
2681
|
}
|
|
@@ -2813,23 +2866,354 @@ function countCommittedTransactions(token) {
|
|
|
2813
2866
|
}
|
|
2814
2867
|
}
|
|
2815
2868
|
|
|
2869
|
+
// registry/token-registry.testnet.json
|
|
2870
|
+
var token_registry_testnet_default = [
|
|
2871
|
+
{
|
|
2872
|
+
network: "unicity:testnet",
|
|
2873
|
+
assetKind: "non-fungible",
|
|
2874
|
+
name: "unicity",
|
|
2875
|
+
description: "Unicity testnet token type",
|
|
2876
|
+
id: "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509"
|
|
2877
|
+
},
|
|
2878
|
+
{
|
|
2879
|
+
network: "unicity:testnet",
|
|
2880
|
+
assetKind: "fungible",
|
|
2881
|
+
name: "unicity",
|
|
2882
|
+
symbol: "UCT",
|
|
2883
|
+
decimals: 18,
|
|
2884
|
+
description: "Unicity testnet native coin",
|
|
2885
|
+
icons: [
|
|
2886
|
+
{ url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity_logo_32.png" }
|
|
2887
|
+
],
|
|
2888
|
+
id: "455ad8720656b08e8dbd5bac1f3c73eeea5431565f6c1c3af742b1aa12d41d89"
|
|
2889
|
+
},
|
|
2890
|
+
{
|
|
2891
|
+
network: "unicity:testnet",
|
|
2892
|
+
assetKind: "fungible",
|
|
2893
|
+
name: "unicity-usd",
|
|
2894
|
+
symbol: "USDU",
|
|
2895
|
+
decimals: 6,
|
|
2896
|
+
description: "Unicity testnet USD stablecoin",
|
|
2897
|
+
icons: [
|
|
2898
|
+
{ url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/usdu_logo_32.png" }
|
|
2899
|
+
],
|
|
2900
|
+
id: "8f0f3d7a5e7297be0ee98c63b81bcebb2740f43f616566fc290f9823a54f52d7"
|
|
2901
|
+
},
|
|
2902
|
+
{
|
|
2903
|
+
network: "unicity:testnet",
|
|
2904
|
+
assetKind: "fungible",
|
|
2905
|
+
name: "unicity-eur",
|
|
2906
|
+
symbol: "EURU",
|
|
2907
|
+
decimals: 6,
|
|
2908
|
+
description: "Unicity testnet EUR stablecoin",
|
|
2909
|
+
icons: [
|
|
2910
|
+
{ url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/euru_logo_32.png" }
|
|
2911
|
+
],
|
|
2912
|
+
id: "5e160d5e9fdbb03b553fb9c3f6e6c30efa41fa807be39fb4f18e43776e492925"
|
|
2913
|
+
},
|
|
2914
|
+
{
|
|
2915
|
+
network: "unicity:testnet",
|
|
2916
|
+
assetKind: "fungible",
|
|
2917
|
+
name: "solana",
|
|
2918
|
+
symbol: "SOL",
|
|
2919
|
+
decimals: 9,
|
|
2920
|
+
description: "Solana testnet coin on Unicity",
|
|
2921
|
+
icons: [
|
|
2922
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/sol.svg" },
|
|
2923
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/sol.png" }
|
|
2924
|
+
],
|
|
2925
|
+
id: "dee5f8ce778562eec90e9c38a91296a023210ccc76ff4c29d527ac3eb64ade93"
|
|
2926
|
+
},
|
|
2927
|
+
{
|
|
2928
|
+
network: "unicity:testnet",
|
|
2929
|
+
assetKind: "fungible",
|
|
2930
|
+
name: "bitcoin",
|
|
2931
|
+
symbol: "BTC",
|
|
2932
|
+
decimals: 8,
|
|
2933
|
+
description: "Bitcoin testnet coin on Unicity",
|
|
2934
|
+
icons: [
|
|
2935
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/btc.svg" },
|
|
2936
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/btc.png" }
|
|
2937
|
+
],
|
|
2938
|
+
id: "86bc190fcf7b2d07c6078de93db803578760148b16d4431aa2f42a3241ff0daa"
|
|
2939
|
+
},
|
|
2940
|
+
{
|
|
2941
|
+
network: "unicity:testnet",
|
|
2942
|
+
assetKind: "fungible",
|
|
2943
|
+
name: "ethereum",
|
|
2944
|
+
symbol: "ETH",
|
|
2945
|
+
decimals: 18,
|
|
2946
|
+
description: "Ethereum testnet coin on Unicity",
|
|
2947
|
+
icons: [
|
|
2948
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/eth.svg" },
|
|
2949
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/eth.png" }
|
|
2950
|
+
],
|
|
2951
|
+
id: "3c2450f2fd867e7bb60c6a69d7ad0e53ce967078c201a3ecaa6074ed4c0deafb"
|
|
2952
|
+
},
|
|
2953
|
+
{
|
|
2954
|
+
network: "unicity:testnet",
|
|
2955
|
+
assetKind: "fungible",
|
|
2956
|
+
name: "alpha_test",
|
|
2957
|
+
symbol: "ALPHT",
|
|
2958
|
+
decimals: 8,
|
|
2959
|
+
description: "ALPHA testnet coin on Unicity",
|
|
2960
|
+
icons: [
|
|
2961
|
+
{ url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/alpha_coin.png" }
|
|
2962
|
+
],
|
|
2963
|
+
id: "cde78ded16ef65818a51f43138031c4284e519300ab0cb60c30a8f9078080e5f"
|
|
2964
|
+
},
|
|
2965
|
+
{
|
|
2966
|
+
network: "unicity:testnet",
|
|
2967
|
+
assetKind: "fungible",
|
|
2968
|
+
name: "tether",
|
|
2969
|
+
symbol: "USDT",
|
|
2970
|
+
decimals: 6,
|
|
2971
|
+
description: "Tether (Ethereum) testnet coin on Unicity",
|
|
2972
|
+
icons: [
|
|
2973
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/usdt.svg" },
|
|
2974
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/usdt.png" }
|
|
2975
|
+
],
|
|
2976
|
+
id: "40d25444648418fe7efd433e147187a3a6adf049ac62bc46038bda5b960bf690"
|
|
2977
|
+
},
|
|
2978
|
+
{
|
|
2979
|
+
network: "unicity:testnet",
|
|
2980
|
+
assetKind: "fungible",
|
|
2981
|
+
name: "usd-coin",
|
|
2982
|
+
symbol: "USDC",
|
|
2983
|
+
decimals: 6,
|
|
2984
|
+
description: "USDC (Ethereum) testnet coin on Unicity",
|
|
2985
|
+
icons: [
|
|
2986
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/usdc.svg" },
|
|
2987
|
+
{ url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/usdc.png" }
|
|
2988
|
+
],
|
|
2989
|
+
id: "2265121770fa6f41131dd9a6cc571e28679263d09a53eb2642e145b5b9a5b0a2"
|
|
2990
|
+
}
|
|
2991
|
+
];
|
|
2992
|
+
|
|
2993
|
+
// registry/TokenRegistry.ts
|
|
2994
|
+
var TokenRegistry = class _TokenRegistry {
|
|
2995
|
+
static instance = null;
|
|
2996
|
+
definitionsById;
|
|
2997
|
+
definitionsBySymbol;
|
|
2998
|
+
definitionsByName;
|
|
2999
|
+
constructor() {
|
|
3000
|
+
this.definitionsById = /* @__PURE__ */ new Map();
|
|
3001
|
+
this.definitionsBySymbol = /* @__PURE__ */ new Map();
|
|
3002
|
+
this.definitionsByName = /* @__PURE__ */ new Map();
|
|
3003
|
+
this.loadRegistry();
|
|
3004
|
+
}
|
|
3005
|
+
/**
|
|
3006
|
+
* Get singleton instance of TokenRegistry
|
|
3007
|
+
*/
|
|
3008
|
+
static getInstance() {
|
|
3009
|
+
if (!_TokenRegistry.instance) {
|
|
3010
|
+
_TokenRegistry.instance = new _TokenRegistry();
|
|
3011
|
+
}
|
|
3012
|
+
return _TokenRegistry.instance;
|
|
3013
|
+
}
|
|
3014
|
+
/**
|
|
3015
|
+
* Reset the singleton instance (useful for testing)
|
|
3016
|
+
*/
|
|
3017
|
+
static resetInstance() {
|
|
3018
|
+
_TokenRegistry.instance = null;
|
|
3019
|
+
}
|
|
3020
|
+
/**
|
|
3021
|
+
* Load registry data from bundled JSON
|
|
3022
|
+
*/
|
|
3023
|
+
loadRegistry() {
|
|
3024
|
+
const definitions = token_registry_testnet_default;
|
|
3025
|
+
for (const def of definitions) {
|
|
3026
|
+
const idLower = def.id.toLowerCase();
|
|
3027
|
+
this.definitionsById.set(idLower, def);
|
|
3028
|
+
if (def.symbol) {
|
|
3029
|
+
this.definitionsBySymbol.set(def.symbol.toUpperCase(), def);
|
|
3030
|
+
}
|
|
3031
|
+
this.definitionsByName.set(def.name.toLowerCase(), def);
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
// ===========================================================================
|
|
3035
|
+
// Lookup Methods
|
|
3036
|
+
// ===========================================================================
|
|
3037
|
+
/**
|
|
3038
|
+
* Get token definition by hex coin ID
|
|
3039
|
+
* @param coinId - 64-character hex string
|
|
3040
|
+
* @returns Token definition or undefined if not found
|
|
3041
|
+
*/
|
|
3042
|
+
getDefinition(coinId) {
|
|
3043
|
+
if (!coinId) return void 0;
|
|
3044
|
+
return this.definitionsById.get(coinId.toLowerCase());
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* Get token definition by symbol (e.g., "UCT", "BTC")
|
|
3048
|
+
* @param symbol - Token symbol (case-insensitive)
|
|
3049
|
+
* @returns Token definition or undefined if not found
|
|
3050
|
+
*/
|
|
3051
|
+
getDefinitionBySymbol(symbol) {
|
|
3052
|
+
if (!symbol) return void 0;
|
|
3053
|
+
return this.definitionsBySymbol.get(symbol.toUpperCase());
|
|
3054
|
+
}
|
|
3055
|
+
/**
|
|
3056
|
+
* Get token definition by name (e.g., "bitcoin", "ethereum")
|
|
3057
|
+
* @param name - Token name (case-insensitive)
|
|
3058
|
+
* @returns Token definition or undefined if not found
|
|
3059
|
+
*/
|
|
3060
|
+
getDefinitionByName(name) {
|
|
3061
|
+
if (!name) return void 0;
|
|
3062
|
+
return this.definitionsByName.get(name.toLowerCase());
|
|
3063
|
+
}
|
|
3064
|
+
/**
|
|
3065
|
+
* Get token symbol for a coin ID
|
|
3066
|
+
* @param coinId - 64-character hex string
|
|
3067
|
+
* @returns Symbol (e.g., "UCT") or truncated ID if not found
|
|
3068
|
+
*/
|
|
3069
|
+
getSymbol(coinId) {
|
|
3070
|
+
const def = this.getDefinition(coinId);
|
|
3071
|
+
if (def?.symbol) {
|
|
3072
|
+
return def.symbol;
|
|
3073
|
+
}
|
|
3074
|
+
return coinId.slice(0, 6).toUpperCase();
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Get token name for a coin ID
|
|
3078
|
+
* @param coinId - 64-character hex string
|
|
3079
|
+
* @returns Name (e.g., "Bitcoin") or coin ID if not found
|
|
3080
|
+
*/
|
|
3081
|
+
getName(coinId) {
|
|
3082
|
+
const def = this.getDefinition(coinId);
|
|
3083
|
+
if (def?.name) {
|
|
3084
|
+
return def.name.charAt(0).toUpperCase() + def.name.slice(1);
|
|
3085
|
+
}
|
|
3086
|
+
return coinId;
|
|
3087
|
+
}
|
|
3088
|
+
/**
|
|
3089
|
+
* Get decimal places for a coin ID
|
|
3090
|
+
* @param coinId - 64-character hex string
|
|
3091
|
+
* @returns Decimals or 0 if not found
|
|
3092
|
+
*/
|
|
3093
|
+
getDecimals(coinId) {
|
|
3094
|
+
const def = this.getDefinition(coinId);
|
|
3095
|
+
return def?.decimals ?? 0;
|
|
3096
|
+
}
|
|
3097
|
+
/**
|
|
3098
|
+
* Get icon URL for a coin ID
|
|
3099
|
+
* @param coinId - 64-character hex string
|
|
3100
|
+
* @param preferPng - Prefer PNG format over SVG
|
|
3101
|
+
* @returns Icon URL or null if not found
|
|
3102
|
+
*/
|
|
3103
|
+
getIconUrl(coinId, preferPng = true) {
|
|
3104
|
+
const def = this.getDefinition(coinId);
|
|
3105
|
+
if (!def?.icons || def.icons.length === 0) {
|
|
3106
|
+
return null;
|
|
3107
|
+
}
|
|
3108
|
+
if (preferPng) {
|
|
3109
|
+
const pngIcon = def.icons.find((i) => i.url.toLowerCase().includes(".png"));
|
|
3110
|
+
if (pngIcon) return pngIcon.url;
|
|
3111
|
+
}
|
|
3112
|
+
return def.icons[0].url;
|
|
3113
|
+
}
|
|
3114
|
+
/**
|
|
3115
|
+
* Check if a coin ID is known in the registry
|
|
3116
|
+
* @param coinId - 64-character hex string
|
|
3117
|
+
* @returns true if the coin is in the registry
|
|
3118
|
+
*/
|
|
3119
|
+
isKnown(coinId) {
|
|
3120
|
+
return this.definitionsById.has(coinId.toLowerCase());
|
|
3121
|
+
}
|
|
3122
|
+
/**
|
|
3123
|
+
* Get all token definitions
|
|
3124
|
+
* @returns Array of all token definitions
|
|
3125
|
+
*/
|
|
3126
|
+
getAllDefinitions() {
|
|
3127
|
+
return Array.from(this.definitionsById.values());
|
|
3128
|
+
}
|
|
3129
|
+
/**
|
|
3130
|
+
* Get all fungible token definitions
|
|
3131
|
+
* @returns Array of fungible token definitions
|
|
3132
|
+
*/
|
|
3133
|
+
getFungibleTokens() {
|
|
3134
|
+
return this.getAllDefinitions().filter((def) => def.assetKind === "fungible");
|
|
3135
|
+
}
|
|
3136
|
+
/**
|
|
3137
|
+
* Get all non-fungible token definitions
|
|
3138
|
+
* @returns Array of non-fungible token definitions
|
|
3139
|
+
*/
|
|
3140
|
+
getNonFungibleTokens() {
|
|
3141
|
+
return this.getAllDefinitions().filter((def) => def.assetKind === "non-fungible");
|
|
3142
|
+
}
|
|
3143
|
+
/**
|
|
3144
|
+
* Get coin ID by symbol
|
|
3145
|
+
* @param symbol - Token symbol (e.g., "UCT")
|
|
3146
|
+
* @returns Coin ID hex string or undefined if not found
|
|
3147
|
+
*/
|
|
3148
|
+
getCoinIdBySymbol(symbol) {
|
|
3149
|
+
const def = this.getDefinitionBySymbol(symbol);
|
|
3150
|
+
return def?.id;
|
|
3151
|
+
}
|
|
3152
|
+
/**
|
|
3153
|
+
* Get coin ID by name
|
|
3154
|
+
* @param name - Token name (e.g., "bitcoin")
|
|
3155
|
+
* @returns Coin ID hex string or undefined if not found
|
|
3156
|
+
*/
|
|
3157
|
+
getCoinIdByName(name) {
|
|
3158
|
+
const def = this.getDefinitionByName(name);
|
|
3159
|
+
return def?.id;
|
|
3160
|
+
}
|
|
3161
|
+
};
|
|
3162
|
+
function getTokenDefinition(coinId) {
|
|
3163
|
+
return TokenRegistry.getInstance().getDefinition(coinId);
|
|
3164
|
+
}
|
|
3165
|
+
function getTokenSymbol(coinId) {
|
|
3166
|
+
return TokenRegistry.getInstance().getSymbol(coinId);
|
|
3167
|
+
}
|
|
3168
|
+
function getTokenName(coinId) {
|
|
3169
|
+
return TokenRegistry.getInstance().getName(coinId);
|
|
3170
|
+
}
|
|
3171
|
+
function getTokenDecimals(coinId) {
|
|
3172
|
+
return TokenRegistry.getInstance().getDecimals(coinId);
|
|
3173
|
+
}
|
|
3174
|
+
function getTokenIconUrl(coinId, preferPng = true) {
|
|
3175
|
+
return TokenRegistry.getInstance().getIconUrl(coinId, preferPng);
|
|
3176
|
+
}
|
|
3177
|
+
function isKnownToken(coinId) {
|
|
3178
|
+
return TokenRegistry.getInstance().isKnown(coinId);
|
|
3179
|
+
}
|
|
3180
|
+
function getCoinIdBySymbol(symbol) {
|
|
3181
|
+
return TokenRegistry.getInstance().getCoinIdBySymbol(symbol);
|
|
3182
|
+
}
|
|
3183
|
+
function getCoinIdByName(name) {
|
|
3184
|
+
return TokenRegistry.getInstance().getCoinIdByName(name);
|
|
3185
|
+
}
|
|
3186
|
+
|
|
2816
3187
|
// modules/payments/PaymentsModule.ts
|
|
2817
3188
|
import { Token as SdkToken2 } from "@unicitylabs/state-transition-sdk/lib/token/Token";
|
|
2818
|
-
import { TokenId as TokenId3 } from "@unicitylabs/state-transition-sdk/lib/token/TokenId";
|
|
2819
3189
|
import { CoinId as CoinId3 } from "@unicitylabs/state-transition-sdk/lib/token/fungible/CoinId";
|
|
2820
3190
|
import { TransferCommitment as TransferCommitment2 } from "@unicitylabs/state-transition-sdk/lib/transaction/TransferCommitment";
|
|
2821
3191
|
import { TransferTransaction } from "@unicitylabs/state-transition-sdk/lib/transaction/TransferTransaction";
|
|
2822
3192
|
import { SigningService } from "@unicitylabs/state-transition-sdk/lib/sign/SigningService";
|
|
2823
|
-
import { ProxyAddress } from "@unicitylabs/state-transition-sdk/lib/address/ProxyAddress";
|
|
2824
3193
|
import { AddressScheme } from "@unicitylabs/state-transition-sdk/lib/address/AddressScheme";
|
|
2825
3194
|
import { UnmaskedPredicate as UnmaskedPredicate3 } from "@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate";
|
|
2826
3195
|
import { TokenState as TokenState3 } from "@unicitylabs/state-transition-sdk/lib/token/TokenState";
|
|
2827
3196
|
import { HashAlgorithm as HashAlgorithm3 } from "@unicitylabs/state-transition-sdk/lib/hash/HashAlgorithm";
|
|
3197
|
+
function enrichWithRegistry(info) {
|
|
3198
|
+
const registry = TokenRegistry.getInstance();
|
|
3199
|
+
const def = registry.getDefinition(info.coinId);
|
|
3200
|
+
if (def) {
|
|
3201
|
+
return {
|
|
3202
|
+
...info,
|
|
3203
|
+
symbol: def.symbol || info.symbol,
|
|
3204
|
+
name: def.name.charAt(0).toUpperCase() + def.name.slice(1),
|
|
3205
|
+
decimals: def.decimals ?? 0,
|
|
3206
|
+
iconUrl: registry.getIconUrl(info.coinId) ?? void 0
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
return info;
|
|
3210
|
+
}
|
|
2828
3211
|
async function parseTokenInfo(tokenData) {
|
|
2829
3212
|
const defaultInfo = {
|
|
2830
3213
|
coinId: "ALPHA",
|
|
2831
3214
|
symbol: "ALPHA",
|
|
2832
3215
|
name: "Alpha Token",
|
|
3216
|
+
decimals: 0,
|
|
2833
3217
|
amount: "0"
|
|
2834
3218
|
};
|
|
2835
3219
|
try {
|
|
@@ -2850,23 +3234,25 @@ async function parseTokenInfo(tokenData) {
|
|
|
2850
3234
|
}
|
|
2851
3235
|
if (coinIdObj instanceof CoinId3) {
|
|
2852
3236
|
const coinIdHex = coinIdObj.toJSON();
|
|
2853
|
-
return {
|
|
3237
|
+
return enrichWithRegistry({
|
|
2854
3238
|
coinId: coinIdHex,
|
|
2855
3239
|
symbol: coinIdHex.slice(0, 8),
|
|
2856
3240
|
name: `Token ${coinIdHex.slice(0, 8)}`,
|
|
3241
|
+
decimals: 0,
|
|
2857
3242
|
amount: String(amount ?? "0"),
|
|
2858
3243
|
tokenId: defaultInfo.tokenId
|
|
2859
|
-
};
|
|
3244
|
+
});
|
|
2860
3245
|
} else if (coinIdObj && typeof coinIdObj === "object" && "bytes" in coinIdObj) {
|
|
2861
3246
|
const bytes = coinIdObj.bytes;
|
|
2862
3247
|
const coinIdHex = Buffer.isBuffer(bytes) ? bytes.toString("hex") : Array.isArray(bytes) ? Buffer.from(bytes).toString("hex") : String(bytes);
|
|
2863
|
-
return {
|
|
3248
|
+
return enrichWithRegistry({
|
|
2864
3249
|
coinId: coinIdHex,
|
|
2865
3250
|
symbol: coinIdHex.slice(0, 8),
|
|
2866
3251
|
name: `Token ${coinIdHex.slice(0, 8)}`,
|
|
3252
|
+
decimals: 0,
|
|
2867
3253
|
amount: String(amount ?? "0"),
|
|
2868
3254
|
tokenId: defaultInfo.tokenId
|
|
2869
|
-
};
|
|
3255
|
+
});
|
|
2870
3256
|
}
|
|
2871
3257
|
}
|
|
2872
3258
|
}
|
|
@@ -2881,13 +3267,14 @@ async function parseTokenInfo(tokenData) {
|
|
|
2881
3267
|
if (Array.isArray(firstEntry) && firstEntry.length === 2) {
|
|
2882
3268
|
const [coinIdHex, amount] = firstEntry;
|
|
2883
3269
|
const coinIdStr = typeof coinIdHex === "string" ? coinIdHex : String(coinIdHex);
|
|
2884
|
-
return {
|
|
3270
|
+
return enrichWithRegistry({
|
|
2885
3271
|
coinId: coinIdStr,
|
|
2886
3272
|
symbol: coinIdStr.slice(0, 8),
|
|
2887
3273
|
name: `Token ${coinIdStr.slice(0, 8)}`,
|
|
3274
|
+
decimals: 0,
|
|
2888
3275
|
amount: String(amount),
|
|
2889
3276
|
tokenId: defaultInfo.tokenId
|
|
2890
|
-
};
|
|
3277
|
+
});
|
|
2891
3278
|
}
|
|
2892
3279
|
}
|
|
2893
3280
|
}
|
|
@@ -2902,25 +3289,27 @@ async function parseTokenInfo(tokenData) {
|
|
|
2902
3289
|
const firstEntry = coinData[0];
|
|
2903
3290
|
if (Array.isArray(firstEntry) && firstEntry.length === 2) {
|
|
2904
3291
|
const [coinIdHex, amount] = firstEntry;
|
|
2905
|
-
return {
|
|
3292
|
+
return enrichWithRegistry({
|
|
2906
3293
|
coinId: String(coinIdHex),
|
|
2907
3294
|
symbol: String(coinIdHex).slice(0, 8),
|
|
2908
3295
|
name: `Token ${String(coinIdHex).slice(0, 8)}`,
|
|
3296
|
+
decimals: 0,
|
|
2909
3297
|
amount: String(amount),
|
|
2910
3298
|
tokenId: genesis.tokenId
|
|
2911
|
-
};
|
|
3299
|
+
});
|
|
2912
3300
|
}
|
|
2913
3301
|
} else if (typeof coinData === "object") {
|
|
2914
3302
|
const coinEntries = Object.entries(coinData);
|
|
2915
3303
|
if (coinEntries.length > 0) {
|
|
2916
3304
|
const [coinId, amount] = coinEntries[0];
|
|
2917
|
-
return {
|
|
3305
|
+
return enrichWithRegistry({
|
|
2918
3306
|
coinId,
|
|
2919
3307
|
symbol: coinId.slice(0, 8),
|
|
2920
3308
|
name: `Token ${coinId.slice(0, 8)}`,
|
|
3309
|
+
decimals: 0,
|
|
2921
3310
|
amount: String(amount),
|
|
2922
3311
|
tokenId: genesis.tokenId
|
|
2923
|
-
};
|
|
3312
|
+
});
|
|
2924
3313
|
}
|
|
2925
3314
|
}
|
|
2926
3315
|
}
|
|
@@ -2934,25 +3323,27 @@ async function parseTokenInfo(tokenData) {
|
|
|
2934
3323
|
const firstEntry = coinData[0];
|
|
2935
3324
|
if (Array.isArray(firstEntry) && firstEntry.length === 2) {
|
|
2936
3325
|
const [coinIdHex, amount] = firstEntry;
|
|
2937
|
-
return {
|
|
3326
|
+
return enrichWithRegistry({
|
|
2938
3327
|
coinId: String(coinIdHex),
|
|
2939
3328
|
symbol: String(coinIdHex).slice(0, 8),
|
|
2940
3329
|
name: `Token ${String(coinIdHex).slice(0, 8)}`,
|
|
3330
|
+
decimals: 0,
|
|
2941
3331
|
amount: String(amount),
|
|
2942
3332
|
tokenId: defaultInfo.tokenId
|
|
2943
|
-
};
|
|
3333
|
+
});
|
|
2944
3334
|
}
|
|
2945
3335
|
} else if (typeof coinData === "object") {
|
|
2946
3336
|
const coinEntries = Object.entries(coinData);
|
|
2947
3337
|
if (coinEntries.length > 0) {
|
|
2948
3338
|
const [coinId, amount] = coinEntries[0];
|
|
2949
|
-
return {
|
|
3339
|
+
return enrichWithRegistry({
|
|
2950
3340
|
coinId,
|
|
2951
3341
|
symbol: coinId.slice(0, 8),
|
|
2952
3342
|
name: `Token ${coinId.slice(0, 8)}`,
|
|
3343
|
+
decimals: 0,
|
|
2953
3344
|
amount: String(amount),
|
|
2954
3345
|
tokenId: defaultInfo.tokenId
|
|
2955
|
-
};
|
|
3346
|
+
});
|
|
2956
3347
|
}
|
|
2957
3348
|
}
|
|
2958
3349
|
}
|
|
@@ -3111,7 +3502,8 @@ var PaymentsModule = class {
|
|
|
3111
3502
|
this.l1.initialize({
|
|
3112
3503
|
identity: deps.identity,
|
|
3113
3504
|
chainCode: deps.chainCode,
|
|
3114
|
-
addresses: deps.l1Addresses
|
|
3505
|
+
addresses: deps.l1Addresses,
|
|
3506
|
+
transport: deps.transport
|
|
3115
3507
|
});
|
|
3116
3508
|
}
|
|
3117
3509
|
this.unsubscribeTransfers = deps.transport.onTokenTransfer((transfer) => {
|
|
@@ -3133,37 +3525,24 @@ var PaymentsModule = class {
|
|
|
3133
3525
|
*/
|
|
3134
3526
|
async load() {
|
|
3135
3527
|
this.ensureInitialized();
|
|
3136
|
-
const
|
|
3137
|
-
|
|
3528
|
+
const providers = this.getTokenStorageProviders();
|
|
3529
|
+
for (const [id, provider] of providers) {
|
|
3138
3530
|
try {
|
|
3139
|
-
const
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
}
|
|
3145
|
-
if (Array.isArray(parsed.tombstones)) {
|
|
3146
|
-
this.tombstones = parsed.tombstones.filter(
|
|
3147
|
-
(t) => typeof t === "object" && t !== null && typeof t.tokenId === "string" && typeof t.stateHash === "string"
|
|
3148
|
-
);
|
|
3149
|
-
}
|
|
3150
|
-
if (parsed.archivedTokens && typeof parsed.archivedTokens === "object") {
|
|
3151
|
-
this.archivedTokens = new Map(Object.entries(parsed.archivedTokens));
|
|
3152
|
-
}
|
|
3153
|
-
if (parsed.forkedTokens && typeof parsed.forkedTokens === "object") {
|
|
3154
|
-
this.forkedTokens = new Map(Object.entries(parsed.forkedTokens));
|
|
3155
|
-
}
|
|
3156
|
-
if (parsed.nametag) {
|
|
3157
|
-
this.nametag = parsed.nametag;
|
|
3531
|
+
const result = await provider.load();
|
|
3532
|
+
if (result.success && result.data) {
|
|
3533
|
+
this.loadFromStorageData(result.data);
|
|
3534
|
+
this.log(`Loaded from provider ${id}: ${this.tokens.size} tokens`);
|
|
3535
|
+
break;
|
|
3158
3536
|
}
|
|
3159
|
-
this.log(`Loaded ${this.tokens.size} tokens, ${this.tombstones.length} tombstones, ${this.archivedTokens.size} archived`);
|
|
3160
3537
|
} catch (err) {
|
|
3161
|
-
console.error(
|
|
3538
|
+
console.error(`[Payments] Failed to load from provider ${id}:`, err);
|
|
3162
3539
|
}
|
|
3163
3540
|
}
|
|
3164
|
-
|
|
3541
|
+
if (this.tokens.size === 0) {
|
|
3542
|
+
await this.loadTokensFromFileStorage();
|
|
3543
|
+
}
|
|
3165
3544
|
await this.loadNametagFromFileStorage();
|
|
3166
|
-
const historyData = await this.deps.storage.get(
|
|
3545
|
+
const historyData = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY);
|
|
3167
3546
|
if (historyData) {
|
|
3168
3547
|
try {
|
|
3169
3548
|
this.transactionHistory = JSON.parse(historyData);
|
|
@@ -3171,7 +3550,7 @@ var PaymentsModule = class {
|
|
|
3171
3550
|
this.transactionHistory = [];
|
|
3172
3551
|
}
|
|
3173
3552
|
}
|
|
3174
|
-
const pending2 = await this.deps.storage.get(
|
|
3553
|
+
const pending2 = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
|
|
3175
3554
|
if (pending2) {
|
|
3176
3555
|
const transfers = JSON.parse(pending2);
|
|
3177
3556
|
for (const transfer of transfers) {
|
|
@@ -3269,6 +3648,8 @@ var PaymentsModule = class {
|
|
|
3269
3648
|
coinId: request.coinId,
|
|
3270
3649
|
symbol: this.getCoinSymbol(request.coinId),
|
|
3271
3650
|
name: this.getCoinName(request.coinId),
|
|
3651
|
+
decimals: this.getCoinDecimals(request.coinId),
|
|
3652
|
+
iconUrl: this.getCoinIconUrl(request.coinId),
|
|
3272
3653
|
amount: splitPlan.remainderAmount.toString(),
|
|
3273
3654
|
status: "confirmed",
|
|
3274
3655
|
createdAt: Date.now(),
|
|
@@ -3337,20 +3718,25 @@ var PaymentsModule = class {
|
|
|
3337
3718
|
* Get coin symbol from coinId
|
|
3338
3719
|
*/
|
|
3339
3720
|
getCoinSymbol(coinId) {
|
|
3340
|
-
|
|
3341
|
-
"UCT": "UCT"
|
|
3342
|
-
// Add more as needed
|
|
3343
|
-
};
|
|
3344
|
-
return symbols[coinId] || coinId.slice(0, 6).toUpperCase();
|
|
3721
|
+
return TokenRegistry.getInstance().getSymbol(coinId);
|
|
3345
3722
|
}
|
|
3346
3723
|
/**
|
|
3347
3724
|
* Get coin name from coinId
|
|
3348
3725
|
*/
|
|
3349
3726
|
getCoinName(coinId) {
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3727
|
+
return TokenRegistry.getInstance().getName(coinId);
|
|
3728
|
+
}
|
|
3729
|
+
/**
|
|
3730
|
+
* Get coin decimals from coinId
|
|
3731
|
+
*/
|
|
3732
|
+
getCoinDecimals(coinId) {
|
|
3733
|
+
return TokenRegistry.getInstance().getDecimals(coinId);
|
|
3734
|
+
}
|
|
3735
|
+
/**
|
|
3736
|
+
* Get coin icon URL from coinId
|
|
3737
|
+
*/
|
|
3738
|
+
getCoinIconUrl(coinId) {
|
|
3739
|
+
return TokenRegistry.getInstance().getIconUrl(coinId) ?? void 0;
|
|
3354
3740
|
}
|
|
3355
3741
|
// ===========================================================================
|
|
3356
3742
|
// Public API - Payment Requests
|
|
@@ -3508,7 +3894,7 @@ var PaymentsModule = class {
|
|
|
3508
3894
|
}
|
|
3509
3895
|
const request = {
|
|
3510
3896
|
id: transportRequest.id,
|
|
3511
|
-
senderPubkey: transportRequest.
|
|
3897
|
+
senderPubkey: transportRequest.senderTransportPubkey,
|
|
3512
3898
|
amount: transportRequest.request.amount,
|
|
3513
3899
|
coinId: transportRequest.request.coinId,
|
|
3514
3900
|
symbol: transportRequest.request.coinId,
|
|
@@ -3620,7 +4006,7 @@ var PaymentsModule = class {
|
|
|
3620
4006
|
}
|
|
3621
4007
|
const response = {
|
|
3622
4008
|
id: transportResponse.id,
|
|
3623
|
-
responderPubkey: transportResponse.
|
|
4009
|
+
responderPubkey: transportResponse.responderTransportPubkey,
|
|
3624
4010
|
requestId: transportResponse.response.requestId,
|
|
3625
4011
|
responseType: transportResponse.response.responseType,
|
|
3626
4012
|
message: transportResponse.response.message,
|
|
@@ -3825,6 +4211,8 @@ var PaymentsModule = class {
|
|
|
3825
4211
|
coinId: tokenInfo.coinId,
|
|
3826
4212
|
symbol: tokenInfo.symbol,
|
|
3827
4213
|
name: tokenInfo.name,
|
|
4214
|
+
decimals: tokenInfo.decimals,
|
|
4215
|
+
iconUrl: tokenInfo.iconUrl,
|
|
3828
4216
|
amount: tokenInfo.amount,
|
|
3829
4217
|
status: "confirmed",
|
|
3830
4218
|
createdAt: data.receivedAt || Date.now(),
|
|
@@ -4080,7 +4468,7 @@ var PaymentsModule = class {
|
|
|
4080
4468
|
};
|
|
4081
4469
|
this.transactionHistory.push(historyEntry);
|
|
4082
4470
|
await this.deps.storage.set(
|
|
4083
|
-
|
|
4471
|
+
STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY,
|
|
4084
4472
|
JSON.stringify(this.transactionHistory)
|
|
4085
4473
|
);
|
|
4086
4474
|
}
|
|
@@ -4374,6 +4762,23 @@ var PaymentsModule = class {
|
|
|
4374
4762
|
// ===========================================================================
|
|
4375
4763
|
// Private: Transfer Operations
|
|
4376
4764
|
// ===========================================================================
|
|
4765
|
+
/**
|
|
4766
|
+
* Detect if a string is an L3 address (not a nametag)
|
|
4767
|
+
* Returns true for: hex pubkeys (64+ chars), PROXY:, DIRECT: prefixed addresses
|
|
4768
|
+
*/
|
|
4769
|
+
isL3Address(value) {
|
|
4770
|
+
if (value.startsWith("PROXY:") || value.startsWith("DIRECT:")) {
|
|
4771
|
+
return true;
|
|
4772
|
+
}
|
|
4773
|
+
if (value.length >= 64 && /^[0-9a-fA-F]+$/.test(value)) {
|
|
4774
|
+
return true;
|
|
4775
|
+
}
|
|
4776
|
+
return false;
|
|
4777
|
+
}
|
|
4778
|
+
/**
|
|
4779
|
+
* Resolve recipient to Nostr pubkey for messaging
|
|
4780
|
+
* Supports: nametag (with or without @), hex pubkey
|
|
4781
|
+
*/
|
|
4377
4782
|
async resolveRecipient(recipient) {
|
|
4378
4783
|
if (recipient.startsWith("@")) {
|
|
4379
4784
|
const nametag = recipient.slice(1);
|
|
@@ -4383,7 +4788,19 @@ var PaymentsModule = class {
|
|
|
4383
4788
|
}
|
|
4384
4789
|
return pubkey;
|
|
4385
4790
|
}
|
|
4386
|
-
|
|
4791
|
+
if (this.isL3Address(recipient)) {
|
|
4792
|
+
return recipient;
|
|
4793
|
+
}
|
|
4794
|
+
if (this.deps?.transport.resolveNametag) {
|
|
4795
|
+
const pubkey = await this.deps.transport.resolveNametag(recipient);
|
|
4796
|
+
if (pubkey) {
|
|
4797
|
+
this.log(`Resolved "${recipient}" as nametag to pubkey`);
|
|
4798
|
+
return pubkey;
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4801
|
+
throw new Error(
|
|
4802
|
+
`Recipient "${recipient}" is not a valid nametag or address. Use @nametag for explicit nametag or a valid hex pubkey/PROXY:/DIRECT: address.`
|
|
4803
|
+
);
|
|
4387
4804
|
}
|
|
4388
4805
|
/**
|
|
4389
4806
|
* Create SDK TransferCommitment for a token transfer
|
|
@@ -4415,19 +4832,74 @@ var PaymentsModule = class {
|
|
|
4415
4832
|
return SigningService.createFromSecret(privateKeyBytes);
|
|
4416
4833
|
}
|
|
4417
4834
|
/**
|
|
4418
|
-
*
|
|
4835
|
+
* Create DirectAddress from a public key using UnmaskedPredicateReference
|
|
4836
|
+
*/
|
|
4837
|
+
async createDirectAddressFromPubkey(pubkeyHex) {
|
|
4838
|
+
const { UnmaskedPredicateReference: UnmaskedPredicateReference3 } = await import("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicateReference");
|
|
4839
|
+
const { TokenType: TokenType3 } = await import("@unicitylabs/state-transition-sdk/lib/token/TokenType");
|
|
4840
|
+
const UNICITY_TOKEN_TYPE_HEX3 = "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509";
|
|
4841
|
+
const tokenType = new TokenType3(Buffer.from(UNICITY_TOKEN_TYPE_HEX3, "hex"));
|
|
4842
|
+
const pubkeyBytes = new Uint8Array(
|
|
4843
|
+
pubkeyHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
|
|
4844
|
+
);
|
|
4845
|
+
const addressRef = await UnmaskedPredicateReference3.create(
|
|
4846
|
+
tokenType,
|
|
4847
|
+
"secp256k1",
|
|
4848
|
+
pubkeyBytes,
|
|
4849
|
+
HashAlgorithm3.SHA256
|
|
4850
|
+
);
|
|
4851
|
+
return addressRef.toAddress();
|
|
4852
|
+
}
|
|
4853
|
+
/**
|
|
4854
|
+
* Resolve nametag to 33-byte compressed public key using resolveNametagInfo
|
|
4855
|
+
* Returns null if nametag not found or publicKey not available
|
|
4856
|
+
*/
|
|
4857
|
+
async resolveNametagToPublicKey(nametag) {
|
|
4858
|
+
if (!this.deps?.transport.resolveNametagInfo) {
|
|
4859
|
+
this.log("resolveNametagInfo not available on transport");
|
|
4860
|
+
return null;
|
|
4861
|
+
}
|
|
4862
|
+
const info = await this.deps.transport.resolveNametagInfo(nametag);
|
|
4863
|
+
if (!info) {
|
|
4864
|
+
this.log(`Nametag "${nametag}" not found`);
|
|
4865
|
+
return null;
|
|
4866
|
+
}
|
|
4867
|
+
if (!info.chainPubkey) {
|
|
4868
|
+
this.log(`Nametag "${nametag}" has no 33-byte chainPubkey (legacy event)`);
|
|
4869
|
+
return null;
|
|
4870
|
+
}
|
|
4871
|
+
return info.chainPubkey;
|
|
4872
|
+
}
|
|
4873
|
+
/**
|
|
4874
|
+
* Resolve recipient to IAddress for L3 transfers
|
|
4875
|
+
* Supports: nametag (with or without @), PROXY:, DIRECT:, hex pubkey
|
|
4419
4876
|
*/
|
|
4420
4877
|
async resolveRecipientAddress(recipient) {
|
|
4878
|
+
const { AddressFactory } = await import("@unicitylabs/state-transition-sdk/lib/address/AddressFactory");
|
|
4421
4879
|
if (recipient.startsWith("@")) {
|
|
4422
4880
|
const nametag = recipient.slice(1);
|
|
4423
|
-
const
|
|
4424
|
-
|
|
4881
|
+
const publicKey2 = await this.resolveNametagToPublicKey(nametag);
|
|
4882
|
+
if (publicKey2) {
|
|
4883
|
+
this.log(`Resolved @${nametag} to 33-byte publicKey for DirectAddress`);
|
|
4884
|
+
return this.createDirectAddressFromPubkey(publicKey2);
|
|
4885
|
+
}
|
|
4886
|
+
throw new Error(`Nametag "${nametag}" not found or missing publicKey`);
|
|
4425
4887
|
}
|
|
4426
|
-
|
|
4427
|
-
|
|
4888
|
+
if (recipient.startsWith("PROXY:") || recipient.startsWith("DIRECT:")) {
|
|
4889
|
+
return AddressFactory.createAddress(recipient);
|
|
4890
|
+
}
|
|
4891
|
+
if (recipient.length === 66 && /^[0-9a-fA-F]+$/.test(recipient)) {
|
|
4892
|
+
this.log(`Creating DirectAddress from 33-byte compressed pubkey`);
|
|
4893
|
+
return this.createDirectAddressFromPubkey(recipient);
|
|
4894
|
+
}
|
|
4895
|
+
const publicKey = await this.resolveNametagToPublicKey(recipient);
|
|
4896
|
+
if (publicKey) {
|
|
4897
|
+
this.log(`Resolved "${recipient}" as nametag to 33-byte publicKey for DirectAddress`);
|
|
4898
|
+
return this.createDirectAddressFromPubkey(publicKey);
|
|
4899
|
+
}
|
|
4900
|
+
throw new Error(
|
|
4901
|
+
`Recipient "${recipient}" is not a valid nametag or L3 address. Use @nametag for explicit nametag or a valid 33-byte hex pubkey/PROXY:/DIRECT: address.`
|
|
4428
4902
|
);
|
|
4429
|
-
const tokenId = new TokenId3(pubkeyBytes.slice(0, 32));
|
|
4430
|
-
return ProxyAddress.fromTokenId(tokenId);
|
|
4431
4903
|
}
|
|
4432
4904
|
async handleIncomingTransfer(transfer) {
|
|
4433
4905
|
try {
|
|
@@ -4485,7 +4957,39 @@ var PaymentsModule = class {
|
|
|
4485
4957
|
}
|
|
4486
4958
|
}
|
|
4487
4959
|
} else {
|
|
4488
|
-
|
|
4960
|
+
this.log("Finalizing DIRECT address transfer for state tracking...");
|
|
4961
|
+
try {
|
|
4962
|
+
const signingService = await this.createSigningService();
|
|
4963
|
+
const transferSalt = transferTx.data.salt;
|
|
4964
|
+
const recipientPredicate = await UnmaskedPredicate3.create(
|
|
4965
|
+
sourceToken.id,
|
|
4966
|
+
sourceToken.type,
|
|
4967
|
+
signingService,
|
|
4968
|
+
HashAlgorithm3.SHA256,
|
|
4969
|
+
transferSalt
|
|
4970
|
+
);
|
|
4971
|
+
const recipientState = new TokenState3(recipientPredicate, null);
|
|
4972
|
+
const stClient = this.deps.oracle.getStateTransitionClient?.();
|
|
4973
|
+
const trustBase = this.deps.oracle.getTrustBase?.();
|
|
4974
|
+
if (!stClient || !trustBase) {
|
|
4975
|
+
this.log("Cannot finalize DIRECT transfer - missing client, using source token");
|
|
4976
|
+
tokenData = sourceTokenInput;
|
|
4977
|
+
} else {
|
|
4978
|
+
finalizedSdkToken = await stClient.finalizeTransaction(
|
|
4979
|
+
trustBase,
|
|
4980
|
+
sourceToken,
|
|
4981
|
+
recipientState,
|
|
4982
|
+
transferTx,
|
|
4983
|
+
[]
|
|
4984
|
+
// No nametag tokens needed for DIRECT
|
|
4985
|
+
);
|
|
4986
|
+
tokenData = finalizedSdkToken.toJSON();
|
|
4987
|
+
this.log("DIRECT transfer finalized successfully");
|
|
4988
|
+
}
|
|
4989
|
+
} catch (finalizeError) {
|
|
4990
|
+
this.log("DIRECT finalization failed, using source token:", finalizeError);
|
|
4991
|
+
tokenData = sourceTokenInput;
|
|
4992
|
+
}
|
|
4489
4993
|
}
|
|
4490
4994
|
} else if (payload.token) {
|
|
4491
4995
|
tokenData = payload.token;
|
|
@@ -4504,6 +5008,8 @@ var PaymentsModule = class {
|
|
|
4504
5008
|
coinId: tokenInfo.coinId,
|
|
4505
5009
|
symbol: tokenInfo.symbol,
|
|
4506
5010
|
name: tokenInfo.name,
|
|
5011
|
+
decimals: tokenInfo.decimals,
|
|
5012
|
+
iconUrl: tokenInfo.iconUrl,
|
|
4507
5013
|
amount: tokenInfo.amount,
|
|
4508
5014
|
status: "confirmed",
|
|
4509
5015
|
createdAt: Date.now(),
|
|
@@ -4519,7 +5025,7 @@ var PaymentsModule = class {
|
|
|
4519
5025
|
await this.addToken(token);
|
|
4520
5026
|
const incomingTransfer = {
|
|
4521
5027
|
id: transfer.id,
|
|
4522
|
-
senderPubkey: transfer.
|
|
5028
|
+
senderPubkey: transfer.senderTransportPubkey,
|
|
4523
5029
|
tokens: [token],
|
|
4524
5030
|
memo: payload.memo,
|
|
4525
5031
|
receivedAt: transfer.timestamp
|
|
@@ -4557,28 +5063,32 @@ var PaymentsModule = class {
|
|
|
4557
5063
|
// Private: Storage
|
|
4558
5064
|
// ===========================================================================
|
|
4559
5065
|
async save() {
|
|
4560
|
-
const
|
|
4561
|
-
|
|
4562
|
-
tokens
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
5066
|
+
const providers = this.getTokenStorageProviders();
|
|
5067
|
+
if (providers.size === 0) {
|
|
5068
|
+
this.log("No token storage providers - tokens not persisted");
|
|
5069
|
+
return;
|
|
5070
|
+
}
|
|
5071
|
+
const data = await this.createStorageData();
|
|
5072
|
+
for (const [id, provider] of providers) {
|
|
5073
|
+
try {
|
|
5074
|
+
await provider.save(data);
|
|
5075
|
+
} catch (err) {
|
|
5076
|
+
console.error(`[Payments] Failed to save to provider ${id}:`, err);
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
4569
5079
|
}
|
|
4570
5080
|
async saveToOutbox(transfer, recipient) {
|
|
4571
5081
|
const outbox = await this.loadOutbox();
|
|
4572
5082
|
outbox.push({ transfer, recipient, createdAt: Date.now() });
|
|
4573
|
-
await this.deps.storage.set(
|
|
5083
|
+
await this.deps.storage.set(STORAGE_KEYS_ADDRESS.OUTBOX, JSON.stringify(outbox));
|
|
4574
5084
|
}
|
|
4575
5085
|
async removeFromOutbox(transferId) {
|
|
4576
5086
|
const outbox = await this.loadOutbox();
|
|
4577
5087
|
const filtered = outbox.filter((e) => e.transfer.id !== transferId);
|
|
4578
|
-
await this.deps.storage.set(
|
|
5088
|
+
await this.deps.storage.set(STORAGE_KEYS_ADDRESS.OUTBOX, JSON.stringify(filtered));
|
|
4579
5089
|
}
|
|
4580
5090
|
async loadOutbox() {
|
|
4581
|
-
const data = await this.deps.storage.get(
|
|
5091
|
+
const data = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.OUTBOX);
|
|
4582
5092
|
return data ? JSON.parse(data) : [];
|
|
4583
5093
|
}
|
|
4584
5094
|
async createStorageData() {
|
|
@@ -4587,11 +5097,10 @@ var PaymentsModule = class {
|
|
|
4587
5097
|
tokens,
|
|
4588
5098
|
{
|
|
4589
5099
|
version: 1,
|
|
4590
|
-
address: this.deps.identity.
|
|
5100
|
+
address: this.deps.identity.l1Address,
|
|
4591
5101
|
ipnsName: this.deps.identity.ipnsName ?? ""
|
|
4592
5102
|
},
|
|
4593
5103
|
{
|
|
4594
|
-
nametag: this.nametag || void 0,
|
|
4595
5104
|
tombstones: this.tombstones,
|
|
4596
5105
|
archivedTokens: this.archivedTokens,
|
|
4597
5106
|
forkedTokens: this.forkedTokens
|
|
@@ -4691,7 +5200,7 @@ var CommunicationsModule = class {
|
|
|
4691
5200
|
const eventId = await this.deps.transport.sendMessage(recipientPubkey, content);
|
|
4692
5201
|
const message = {
|
|
4693
5202
|
id: eventId,
|
|
4694
|
-
senderPubkey: this.deps.identity.
|
|
5203
|
+
senderPubkey: this.deps.identity.chainPubkey,
|
|
4695
5204
|
senderNametag: this.deps.identity.nametag,
|
|
4696
5205
|
recipientPubkey,
|
|
4697
5206
|
content,
|
|
@@ -4718,7 +5227,7 @@ var CommunicationsModule = class {
|
|
|
4718
5227
|
getConversations() {
|
|
4719
5228
|
const conversations = /* @__PURE__ */ new Map();
|
|
4720
5229
|
for (const message of this.messages.values()) {
|
|
4721
|
-
const peer = message.senderPubkey === this.deps?.identity.
|
|
5230
|
+
const peer = message.senderPubkey === this.deps?.identity.chainPubkey ? message.recipientPubkey : message.senderPubkey;
|
|
4722
5231
|
if (!conversations.has(peer)) {
|
|
4723
5232
|
conversations.set(peer, []);
|
|
4724
5233
|
}
|
|
@@ -4748,7 +5257,7 @@ var CommunicationsModule = class {
|
|
|
4748
5257
|
*/
|
|
4749
5258
|
getUnreadCount(peerPubkey) {
|
|
4750
5259
|
let messages = Array.from(this.messages.values()).filter(
|
|
4751
|
-
(m) => !m.isRead && m.senderPubkey !== this.deps?.identity.
|
|
5260
|
+
(m) => !m.isRead && m.senderPubkey !== this.deps?.identity.chainPubkey
|
|
4752
5261
|
);
|
|
4753
5262
|
if (peerPubkey) {
|
|
4754
5263
|
messages = messages.filter((m) => m.senderPubkey === peerPubkey);
|
|
@@ -4773,7 +5282,7 @@ var CommunicationsModule = class {
|
|
|
4773
5282
|
const eventId = await this.deps.transport.publishBroadcast?.(content, tags);
|
|
4774
5283
|
const message = {
|
|
4775
5284
|
id: eventId ?? crypto.randomUUID(),
|
|
4776
|
-
authorPubkey: this.deps.identity.
|
|
5285
|
+
authorPubkey: this.deps.identity.chainPubkey,
|
|
4777
5286
|
authorNametag: this.deps.identity.nametag,
|
|
4778
5287
|
content,
|
|
4779
5288
|
timestamp: Date.now(),
|
|
@@ -4824,11 +5333,12 @@ var CommunicationsModule = class {
|
|
|
4824
5333
|
// Private: Message Handling
|
|
4825
5334
|
// ===========================================================================
|
|
4826
5335
|
handleIncomingMessage(msg) {
|
|
4827
|
-
if (msg.
|
|
5336
|
+
if (msg.senderTransportPubkey === this.deps?.identity.chainPubkey) return;
|
|
4828
5337
|
const message = {
|
|
4829
5338
|
id: msg.id,
|
|
4830
|
-
senderPubkey: msg.
|
|
4831
|
-
|
|
5339
|
+
senderPubkey: msg.senderTransportPubkey,
|
|
5340
|
+
senderNametag: msg.senderNametag,
|
|
5341
|
+
recipientPubkey: this.deps.identity.chainPubkey,
|
|
4832
5342
|
content: msg.content,
|
|
4833
5343
|
timestamp: msg.timestamp,
|
|
4834
5344
|
isRead: false
|
|
@@ -4850,7 +5360,7 @@ var CommunicationsModule = class {
|
|
|
4850
5360
|
handleIncomingBroadcast(incoming) {
|
|
4851
5361
|
const message = {
|
|
4852
5362
|
id: incoming.id,
|
|
4853
|
-
authorPubkey: incoming.
|
|
5363
|
+
authorPubkey: incoming.authorTransportPubkey,
|
|
4854
5364
|
content: incoming.content,
|
|
4855
5365
|
timestamp: incoming.timestamp,
|
|
4856
5366
|
tags: incoming.tags
|
|
@@ -5592,6 +6102,7 @@ import { SigningService as SigningService2 } from "@unicitylabs/state-transition
|
|
|
5592
6102
|
import { TokenType as TokenType2 } from "@unicitylabs/state-transition-sdk/lib/token/TokenType";
|
|
5593
6103
|
import { HashAlgorithm as HashAlgorithm4 } from "@unicitylabs/state-transition-sdk/lib/hash/HashAlgorithm";
|
|
5594
6104
|
import { UnmaskedPredicateReference as UnmaskedPredicateReference2 } from "@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicateReference";
|
|
6105
|
+
import { hashNametag } from "@unicitylabs/nostr-js-sdk";
|
|
5595
6106
|
var UNICITY_TOKEN_TYPE_HEX2 = "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509";
|
|
5596
6107
|
async function deriveL3PredicateAddress(privateKey) {
|
|
5597
6108
|
const secret = Buffer.from(privateKey, "hex");
|
|
@@ -5618,6 +6129,7 @@ var Sphere = class _Sphere {
|
|
|
5618
6129
|
_derivationMode = "bip32";
|
|
5619
6130
|
_basePath = DEFAULT_BASE_PATH;
|
|
5620
6131
|
_currentAddressIndex = 0;
|
|
6132
|
+
/** Map of addressId -> (nametagIndex -> nametag). Supports multiple nametags per address (e.g., from Nostr recovery) */
|
|
5621
6133
|
_addressNametags = /* @__PURE__ */ new Map();
|
|
5622
6134
|
// Providers
|
|
5623
6135
|
_storage;
|
|
@@ -5653,9 +6165,9 @@ var Sphere = class _Sphere {
|
|
|
5653
6165
|
if (!storage.isConnected()) {
|
|
5654
6166
|
await storage.connect();
|
|
5655
6167
|
}
|
|
5656
|
-
const mnemonic = await storage.get(
|
|
6168
|
+
const mnemonic = await storage.get(STORAGE_KEYS_GLOBAL.MNEMONIC);
|
|
5657
6169
|
if (mnemonic) return true;
|
|
5658
|
-
const masterKey = await storage.get(
|
|
6170
|
+
const masterKey = await storage.get(STORAGE_KEYS_GLOBAL.MASTER_KEY);
|
|
5659
6171
|
if (masterKey) return true;
|
|
5660
6172
|
return false;
|
|
5661
6173
|
} catch {
|
|
@@ -5749,6 +6261,8 @@ var Sphere = class _Sphere {
|
|
|
5749
6261
|
_Sphere.instance = sphere;
|
|
5750
6262
|
if (options.nametag) {
|
|
5751
6263
|
await sphere.registerNametag(options.nametag);
|
|
6264
|
+
} else {
|
|
6265
|
+
await sphere.recoverNametagFromNostr();
|
|
5752
6266
|
}
|
|
5753
6267
|
return sphere;
|
|
5754
6268
|
}
|
|
@@ -5811,6 +6325,9 @@ var Sphere = class _Sphere {
|
|
|
5811
6325
|
}
|
|
5812
6326
|
await sphere.initializeProviders();
|
|
5813
6327
|
await sphere.initializeModules();
|
|
6328
|
+
if (!options.nametag) {
|
|
6329
|
+
await sphere.recoverNametagFromNostr();
|
|
6330
|
+
}
|
|
5814
6331
|
await sphere.finalizeWalletCreation();
|
|
5815
6332
|
sphere._initialized = true;
|
|
5816
6333
|
_Sphere.instance = sphere;
|
|
@@ -5821,20 +6338,20 @@ var Sphere = class _Sphere {
|
|
|
5821
6338
|
}
|
|
5822
6339
|
/**
|
|
5823
6340
|
* Clear wallet data from storage
|
|
6341
|
+
* Note: Token data is cleared via TokenStorageProvider, not here
|
|
5824
6342
|
*/
|
|
5825
6343
|
static async clear(storage) {
|
|
5826
|
-
await storage.remove(
|
|
5827
|
-
await storage.remove(
|
|
5828
|
-
await storage.remove(
|
|
5829
|
-
await storage.remove(
|
|
5830
|
-
await storage.remove(
|
|
5831
|
-
await storage.remove(
|
|
5832
|
-
await storage.remove(
|
|
5833
|
-
await storage.remove(
|
|
5834
|
-
await storage.remove(
|
|
5835
|
-
await storage.remove(
|
|
5836
|
-
await storage.remove(
|
|
5837
|
-
await storage.remove(STORAGE_KEYS.OUTBOX);
|
|
6344
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.MNEMONIC);
|
|
6345
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.MASTER_KEY);
|
|
6346
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
|
|
6347
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.DERIVATION_PATH);
|
|
6348
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.BASE_PATH);
|
|
6349
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.DERIVATION_MODE);
|
|
6350
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.WALLET_SOURCE);
|
|
6351
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.WALLET_EXISTS);
|
|
6352
|
+
await storage.remove(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
|
|
6353
|
+
await storage.remove(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
|
|
6354
|
+
await storage.remove(STORAGE_KEYS_ADDRESS.OUTBOX);
|
|
5838
6355
|
if (_Sphere.instance) {
|
|
5839
6356
|
await _Sphere.instance.destroy();
|
|
5840
6357
|
}
|
|
@@ -5884,9 +6401,9 @@ var Sphere = class _Sphere {
|
|
|
5884
6401
|
get identity() {
|
|
5885
6402
|
if (!this._identity) return null;
|
|
5886
6403
|
return {
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
6404
|
+
chainPubkey: this._identity.chainPubkey,
|
|
6405
|
+
l1Address: this._identity.l1Address,
|
|
6406
|
+
directAddress: this._identity.directAddress,
|
|
5890
6407
|
ipnsName: this._identity.ipnsName,
|
|
5891
6408
|
nametag: this._identity.nametag
|
|
5892
6409
|
};
|
|
@@ -6003,7 +6520,7 @@ var Sphere = class _Sphere {
|
|
|
6003
6520
|
if (this._masterKey) {
|
|
6004
6521
|
address0 = this.deriveAddress(0).address;
|
|
6005
6522
|
} else if (this._identity) {
|
|
6006
|
-
address0 = this._identity.
|
|
6523
|
+
address0 = this._identity.l1Address;
|
|
6007
6524
|
}
|
|
6008
6525
|
} catch {
|
|
6009
6526
|
}
|
|
@@ -6050,8 +6567,8 @@ var Sphere = class _Sphere {
|
|
|
6050
6567
|
} catch {
|
|
6051
6568
|
if (i === 0 && this._identity) {
|
|
6052
6569
|
addresses.push({
|
|
6053
|
-
address: this._identity.
|
|
6054
|
-
publicKey: this._identity.
|
|
6570
|
+
address: this._identity.l1Address,
|
|
6571
|
+
publicKey: this._identity.chainPubkey,
|
|
6055
6572
|
path: this.getDefaultAddressPath(),
|
|
6056
6573
|
index: 0
|
|
6057
6574
|
});
|
|
@@ -6130,7 +6647,7 @@ var Sphere = class _Sphere {
|
|
|
6130
6647
|
} catch {
|
|
6131
6648
|
if (i === 0 && this._identity) {
|
|
6132
6649
|
addresses.push({
|
|
6133
|
-
address: this._identity.
|
|
6650
|
+
address: this._identity.l1Address,
|
|
6134
6651
|
path: this.getDefaultAddressPath(),
|
|
6135
6652
|
index: 0,
|
|
6136
6653
|
isChange: false
|
|
@@ -6434,22 +6951,47 @@ var Sphere = class _Sphere {
|
|
|
6434
6951
|
return this._currentAddressIndex;
|
|
6435
6952
|
}
|
|
6436
6953
|
/**
|
|
6437
|
-
* Get nametag for a specific address
|
|
6954
|
+
* Get primary nametag for a specific address
|
|
6955
|
+
*
|
|
6956
|
+
* @param addressId - Address identifier (DIRECT://xxx), defaults to current address
|
|
6957
|
+
* @returns Primary nametag (index 0) or undefined if not registered
|
|
6958
|
+
*/
|
|
6959
|
+
getNametagForAddress(addressId) {
|
|
6960
|
+
const id = addressId ?? this.getCurrentAddressId();
|
|
6961
|
+
if (!id) return void 0;
|
|
6962
|
+
const nametagsMap = this._addressNametags.get(id);
|
|
6963
|
+
return nametagsMap?.get(0);
|
|
6964
|
+
}
|
|
6965
|
+
/**
|
|
6966
|
+
* Get all nametags for a specific address
|
|
6438
6967
|
*
|
|
6439
|
-
* @param
|
|
6440
|
-
* @returns
|
|
6968
|
+
* @param addressId - Address identifier (DIRECT://xxx), defaults to current address
|
|
6969
|
+
* @returns Map of nametagIndex to nametag, or undefined if no nametags
|
|
6441
6970
|
*/
|
|
6442
|
-
|
|
6443
|
-
const
|
|
6444
|
-
|
|
6971
|
+
getNametagsForAddress(addressId) {
|
|
6972
|
+
const id = addressId ?? this.getCurrentAddressId();
|
|
6973
|
+
if (!id) return void 0;
|
|
6974
|
+
const nametagsMap = this._addressNametags.get(id);
|
|
6975
|
+
return nametagsMap ? new Map(nametagsMap) : void 0;
|
|
6445
6976
|
}
|
|
6446
6977
|
/**
|
|
6447
6978
|
* Get all registered address nametags
|
|
6448
6979
|
*
|
|
6449
|
-
* @returns Map of
|
|
6980
|
+
* @returns Map of addressId to (nametagIndex -> nametag)
|
|
6450
6981
|
*/
|
|
6451
6982
|
getAllAddressNametags() {
|
|
6452
|
-
|
|
6983
|
+
const result = /* @__PURE__ */ new Map();
|
|
6984
|
+
this._addressNametags.forEach((nametagsMap, addressId) => {
|
|
6985
|
+
result.set(addressId, new Map(nametagsMap));
|
|
6986
|
+
});
|
|
6987
|
+
return result;
|
|
6988
|
+
}
|
|
6989
|
+
/**
|
|
6990
|
+
* Get current address identifier (DIRECT://xxx format)
|
|
6991
|
+
*/
|
|
6992
|
+
getCurrentAddressId() {
|
|
6993
|
+
if (!this._identity?.directAddress) return void 0;
|
|
6994
|
+
return getAddressId(this._identity.directAddress);
|
|
6453
6995
|
}
|
|
6454
6996
|
/**
|
|
6455
6997
|
* Switch to a different address by index
|
|
@@ -6481,17 +7023,19 @@ var Sphere = class _Sphere {
|
|
|
6481
7023
|
const addressInfo = this.deriveAddress(index, false);
|
|
6482
7024
|
const ipnsHash = sha256(addressInfo.publicKey, "hex").slice(0, 40);
|
|
6483
7025
|
const predicateAddress = await deriveL3PredicateAddress(addressInfo.privateKey);
|
|
6484
|
-
const
|
|
7026
|
+
const addressId = getAddressId(predicateAddress);
|
|
7027
|
+
const nametagsMap = this._addressNametags.get(addressId);
|
|
7028
|
+
const nametag = nametagsMap?.get(0);
|
|
6485
7029
|
this._identity = {
|
|
6486
7030
|
privateKey: addressInfo.privateKey,
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
predicateAddress,
|
|
7031
|
+
chainPubkey: addressInfo.publicKey,
|
|
7032
|
+
l1Address: addressInfo.address,
|
|
7033
|
+
directAddress: predicateAddress,
|
|
6490
7034
|
ipnsName: "12D3KooW" + ipnsHash,
|
|
6491
7035
|
nametag
|
|
6492
7036
|
};
|
|
6493
7037
|
this._currentAddressIndex = index;
|
|
6494
|
-
await this._storage.set(
|
|
7038
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.CURRENT_ADDRESS_INDEX, index.toString());
|
|
6495
7039
|
this._storage.setIdentity(this._identity);
|
|
6496
7040
|
this._transport.setIdentity(this._identity);
|
|
6497
7041
|
for (const provider of this._tokenStorageProviders.values()) {
|
|
@@ -6499,13 +7043,13 @@ var Sphere = class _Sphere {
|
|
|
6499
7043
|
}
|
|
6500
7044
|
await this.reinitializeModulesForNewAddress();
|
|
6501
7045
|
this.emitEvent("identity:changed", {
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
7046
|
+
l1Address: this._identity.l1Address,
|
|
7047
|
+
directAddress: this._identity.directAddress,
|
|
7048
|
+
chainPubkey: this._identity.chainPubkey,
|
|
6505
7049
|
nametag: this._identity.nametag,
|
|
6506
7050
|
addressIndex: index
|
|
6507
7051
|
});
|
|
6508
|
-
console.log(`[Sphere] Switched to address ${index}:`, this._identity.
|
|
7052
|
+
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
6509
7053
|
}
|
|
6510
7054
|
/**
|
|
6511
7055
|
* Re-initialize modules after address switch
|
|
@@ -6563,7 +7107,7 @@ var Sphere = class _Sphere {
|
|
|
6563
7107
|
);
|
|
6564
7108
|
return {
|
|
6565
7109
|
...info,
|
|
6566
|
-
address:
|
|
7110
|
+
address: publicKeyToAddress(info.publicKey, "alpha")
|
|
6567
7111
|
};
|
|
6568
7112
|
}
|
|
6569
7113
|
/**
|
|
@@ -6590,11 +7134,10 @@ var Sphere = class _Sphere {
|
|
|
6590
7134
|
path
|
|
6591
7135
|
);
|
|
6592
7136
|
const publicKey = getPublicKey(derived.privateKey);
|
|
6593
|
-
const addressHash = hash160(publicKey);
|
|
6594
7137
|
return {
|
|
6595
7138
|
privateKey: derived.privateKey,
|
|
6596
7139
|
publicKey,
|
|
6597
|
-
address:
|
|
7140
|
+
address: publicKeyToAddress(publicKey, "alpha"),
|
|
6598
7141
|
path,
|
|
6599
7142
|
index
|
|
6600
7143
|
};
|
|
@@ -6682,6 +7225,17 @@ var Sphere = class _Sphere {
|
|
|
6682
7225
|
hasNametag() {
|
|
6683
7226
|
return !!this._identity?.nametag;
|
|
6684
7227
|
}
|
|
7228
|
+
/**
|
|
7229
|
+
* Get the PROXY address for the current nametag
|
|
7230
|
+
* PROXY addresses are derived from the nametag hash and require
|
|
7231
|
+
* the nametag token to claim funds sent to them
|
|
7232
|
+
* @returns PROXY address string or undefined if no nametag
|
|
7233
|
+
*/
|
|
7234
|
+
getProxyAddress() {
|
|
7235
|
+
const nametag = this._identity?.nametag;
|
|
7236
|
+
if (!nametag) return void 0;
|
|
7237
|
+
return `PROXY:${hashNametag(nametag)}`;
|
|
7238
|
+
}
|
|
6685
7239
|
/**
|
|
6686
7240
|
* Register a nametag for the current active address
|
|
6687
7241
|
* Each address can have its own independent nametag
|
|
@@ -6710,14 +7264,25 @@ var Sphere = class _Sphere {
|
|
|
6710
7264
|
throw new Error(`Nametag already registered for address ${this._currentAddressIndex}: @${this._identity.nametag}`);
|
|
6711
7265
|
}
|
|
6712
7266
|
if (this._transport.registerNametag) {
|
|
6713
|
-
const success = await this._transport.registerNametag(
|
|
7267
|
+
const success = await this._transport.registerNametag(
|
|
7268
|
+
cleanNametag,
|
|
7269
|
+
this._identity.chainPubkey,
|
|
7270
|
+
this._identity.directAddress || ""
|
|
7271
|
+
);
|
|
6714
7272
|
if (!success) {
|
|
6715
7273
|
throw new Error("Failed to register nametag. It may already be taken.");
|
|
6716
7274
|
}
|
|
6717
7275
|
}
|
|
6718
7276
|
this._identity.nametag = cleanNametag;
|
|
6719
|
-
this.
|
|
6720
|
-
|
|
7277
|
+
const addressId = this.getCurrentAddressId();
|
|
7278
|
+
if (addressId) {
|
|
7279
|
+
let nametagsMap = this._addressNametags.get(addressId);
|
|
7280
|
+
if (!nametagsMap) {
|
|
7281
|
+
nametagsMap = /* @__PURE__ */ new Map();
|
|
7282
|
+
this._addressNametags.set(addressId, nametagsMap);
|
|
7283
|
+
}
|
|
7284
|
+
nametagsMap.set(0, cleanNametag);
|
|
7285
|
+
}
|
|
6721
7286
|
await this.persistAddressNametags();
|
|
6722
7287
|
if (!this._payments.hasNametag()) {
|
|
6723
7288
|
console.log(`[Sphere] Minting nametag token for @${cleanNametag}...`);
|
|
@@ -6736,13 +7301,18 @@ var Sphere = class _Sphere {
|
|
|
6736
7301
|
}
|
|
6737
7302
|
/**
|
|
6738
7303
|
* Persist address nametags to storage
|
|
7304
|
+
* Format: { "DIRECT://abc...xyz": { "0": "alice", "1": "alice2" }, ... }
|
|
6739
7305
|
*/
|
|
6740
7306
|
async persistAddressNametags() {
|
|
6741
|
-
const
|
|
6742
|
-
this._addressNametags.forEach((
|
|
6743
|
-
|
|
7307
|
+
const result = {};
|
|
7308
|
+
this._addressNametags.forEach((nametagsMap, addressId) => {
|
|
7309
|
+
const innerObj = {};
|
|
7310
|
+
nametagsMap.forEach((nametag, index) => {
|
|
7311
|
+
innerObj[index.toString()] = nametag;
|
|
7312
|
+
});
|
|
7313
|
+
result[addressId] = innerObj;
|
|
6744
7314
|
});
|
|
6745
|
-
await this._storage.set(
|
|
7315
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS, JSON.stringify(result));
|
|
6746
7316
|
}
|
|
6747
7317
|
/**
|
|
6748
7318
|
* Mint a nametag token on-chain (like Sphere wallet and lottery)
|
|
@@ -6777,15 +7347,24 @@ var Sphere = class _Sphere {
|
|
|
6777
7347
|
}
|
|
6778
7348
|
/**
|
|
6779
7349
|
* Load address nametags from storage
|
|
7350
|
+
* Supports new format: { "DIRECT://abc...xyz": { "0": "alice" } }
|
|
7351
|
+
* And legacy format: { "0": "alice" } (migrates to new format on save)
|
|
6780
7352
|
*/
|
|
6781
7353
|
async loadAddressNametags() {
|
|
6782
7354
|
try {
|
|
6783
|
-
const saved = await this._storage.get(
|
|
7355
|
+
const saved = await this._storage.get(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
|
|
6784
7356
|
if (saved) {
|
|
6785
|
-
const
|
|
7357
|
+
const parsed = JSON.parse(saved);
|
|
6786
7358
|
this._addressNametags.clear();
|
|
6787
|
-
for (const [
|
|
6788
|
-
|
|
7359
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
7360
|
+
if (typeof value === "object" && value !== null) {
|
|
7361
|
+
const nametagsMap = /* @__PURE__ */ new Map();
|
|
7362
|
+
for (const [indexStr, nametag] of Object.entries(value)) {
|
|
7363
|
+
nametagsMap.set(parseInt(indexStr, 10), nametag);
|
|
7364
|
+
}
|
|
7365
|
+
this._addressNametags.set(key, nametagsMap);
|
|
7366
|
+
} else if (typeof value === "string") {
|
|
7367
|
+
}
|
|
6789
7368
|
}
|
|
6790
7369
|
}
|
|
6791
7370
|
} catch {
|
|
@@ -6804,7 +7383,11 @@ var Sphere = class _Sphere {
|
|
|
6804
7383
|
return;
|
|
6805
7384
|
}
|
|
6806
7385
|
try {
|
|
6807
|
-
const success = await this._transport.registerNametag(
|
|
7386
|
+
const success = await this._transport.registerNametag(
|
|
7387
|
+
nametag,
|
|
7388
|
+
this._identity.chainPubkey,
|
|
7389
|
+
this._identity.directAddress || ""
|
|
7390
|
+
);
|
|
6808
7391
|
if (success) {
|
|
6809
7392
|
console.log(`[Sphere] Nametag @${nametag} synced with Nostr`);
|
|
6810
7393
|
} else {
|
|
@@ -6814,6 +7397,47 @@ var Sphere = class _Sphere {
|
|
|
6814
7397
|
console.warn(`[Sphere] Nametag sync failed:`, error);
|
|
6815
7398
|
}
|
|
6816
7399
|
}
|
|
7400
|
+
/**
|
|
7401
|
+
* Recover nametag from Nostr after wallet import
|
|
7402
|
+
* Searches for encrypted nametag events authored by this wallet's pubkey
|
|
7403
|
+
* and decrypts them to restore the nametag association
|
|
7404
|
+
*/
|
|
7405
|
+
async recoverNametagFromNostr() {
|
|
7406
|
+
if (this._identity?.nametag) {
|
|
7407
|
+
return;
|
|
7408
|
+
}
|
|
7409
|
+
if (!this._transport.recoverNametag) {
|
|
7410
|
+
return;
|
|
7411
|
+
}
|
|
7412
|
+
try {
|
|
7413
|
+
const recoveredNametag = await this._transport.recoverNametag();
|
|
7414
|
+
if (recoveredNametag) {
|
|
7415
|
+
if (this._identity) {
|
|
7416
|
+
this._identity.nametag = recoveredNametag;
|
|
7417
|
+
}
|
|
7418
|
+
const addressId = this.getCurrentAddressId();
|
|
7419
|
+
if (addressId) {
|
|
7420
|
+
let nametagsMap = this._addressNametags.get(addressId);
|
|
7421
|
+
if (!nametagsMap) {
|
|
7422
|
+
nametagsMap = /* @__PURE__ */ new Map();
|
|
7423
|
+
this._addressNametags.set(addressId, nametagsMap);
|
|
7424
|
+
}
|
|
7425
|
+
const nextIndex = nametagsMap.size;
|
|
7426
|
+
nametagsMap.set(nextIndex, recoveredNametag);
|
|
7427
|
+
}
|
|
7428
|
+
await this.persistAddressNametags();
|
|
7429
|
+
if (this._transport.registerNametag) {
|
|
7430
|
+
await this._transport.registerNametag(
|
|
7431
|
+
recoveredNametag,
|
|
7432
|
+
this._identity.chainPubkey,
|
|
7433
|
+
this._identity.directAddress || ""
|
|
7434
|
+
);
|
|
7435
|
+
}
|
|
7436
|
+
this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
|
|
7437
|
+
}
|
|
7438
|
+
} catch {
|
|
7439
|
+
}
|
|
7440
|
+
}
|
|
6817
7441
|
/**
|
|
6818
7442
|
* Validate nametag format
|
|
6819
7443
|
*/
|
|
@@ -6844,22 +7468,22 @@ var Sphere = class _Sphere {
|
|
|
6844
7468
|
// ===========================================================================
|
|
6845
7469
|
async storeMnemonic(mnemonic, derivationPath, basePath) {
|
|
6846
7470
|
const encrypted = this.encrypt(mnemonic);
|
|
6847
|
-
await this._storage.set(
|
|
7471
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.MNEMONIC, encrypted);
|
|
6848
7472
|
this._mnemonic = mnemonic;
|
|
6849
7473
|
this._source = "mnemonic";
|
|
6850
7474
|
this._derivationMode = "bip32";
|
|
6851
7475
|
if (derivationPath) {
|
|
6852
|
-
await this._storage.set(
|
|
7476
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_PATH, derivationPath);
|
|
6853
7477
|
}
|
|
6854
7478
|
const effectiveBasePath = basePath ?? DEFAULT_BASE_PATH;
|
|
6855
7479
|
this._basePath = effectiveBasePath;
|
|
6856
|
-
await this._storage.set(
|
|
6857
|
-
await this._storage.set(
|
|
6858
|
-
await this._storage.set(
|
|
7480
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.BASE_PATH, effectiveBasePath);
|
|
7481
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_MODE, this._derivationMode);
|
|
7482
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.WALLET_SOURCE, this._source);
|
|
6859
7483
|
}
|
|
6860
7484
|
async storeMasterKey(masterKey, chainCode, derivationPath, basePath, derivationMode) {
|
|
6861
7485
|
const encrypted = this.encrypt(masterKey);
|
|
6862
|
-
await this._storage.set(
|
|
7486
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.MASTER_KEY, encrypted);
|
|
6863
7487
|
this._source = "file";
|
|
6864
7488
|
this._mnemonic = null;
|
|
6865
7489
|
if (derivationMode) {
|
|
@@ -6868,16 +7492,16 @@ var Sphere = class _Sphere {
|
|
|
6868
7492
|
this._derivationMode = chainCode ? "bip32" : "wif_hmac";
|
|
6869
7493
|
}
|
|
6870
7494
|
if (chainCode) {
|
|
6871
|
-
await this._storage.set(
|
|
7495
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.CHAIN_CODE, chainCode);
|
|
6872
7496
|
}
|
|
6873
7497
|
if (derivationPath) {
|
|
6874
|
-
await this._storage.set(
|
|
7498
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_PATH, derivationPath);
|
|
6875
7499
|
}
|
|
6876
7500
|
const effectiveBasePath = basePath ?? DEFAULT_BASE_PATH;
|
|
6877
7501
|
this._basePath = effectiveBasePath;
|
|
6878
|
-
await this._storage.set(
|
|
6879
|
-
await this._storage.set(
|
|
6880
|
-
await this._storage.set(
|
|
7502
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.BASE_PATH, effectiveBasePath);
|
|
7503
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_MODE, this._derivationMode);
|
|
7504
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.WALLET_SOURCE, this._source);
|
|
6881
7505
|
}
|
|
6882
7506
|
/**
|
|
6883
7507
|
* Mark wallet as fully created (after successful initialization)
|
|
@@ -6885,20 +7509,20 @@ var Sphere = class _Sphere {
|
|
|
6885
7509
|
* marked as existing after all initialization steps succeed.
|
|
6886
7510
|
*/
|
|
6887
7511
|
async finalizeWalletCreation() {
|
|
6888
|
-
await this._storage.set(
|
|
7512
|
+
await this._storage.set(STORAGE_KEYS_GLOBAL.WALLET_EXISTS, "true");
|
|
6889
7513
|
}
|
|
6890
7514
|
// ===========================================================================
|
|
6891
7515
|
// Private: Identity Initialization
|
|
6892
7516
|
// ===========================================================================
|
|
6893
7517
|
async loadIdentityFromStorage() {
|
|
6894
|
-
const encryptedMnemonic = await this._storage.get(
|
|
6895
|
-
const encryptedMasterKey = await this._storage.get(
|
|
6896
|
-
const chainCode = await this._storage.get(
|
|
6897
|
-
const derivationPath = await this._storage.get(
|
|
6898
|
-
const savedBasePath = await this._storage.get(
|
|
6899
|
-
const savedDerivationMode = await this._storage.get(
|
|
6900
|
-
const savedSource = await this._storage.get(
|
|
6901
|
-
const savedAddressIndex = await this._storage.get(
|
|
7518
|
+
const encryptedMnemonic = await this._storage.get(STORAGE_KEYS_GLOBAL.MNEMONIC);
|
|
7519
|
+
const encryptedMasterKey = await this._storage.get(STORAGE_KEYS_GLOBAL.MASTER_KEY);
|
|
7520
|
+
const chainCode = await this._storage.get(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
|
|
7521
|
+
const derivationPath = await this._storage.get(STORAGE_KEYS_GLOBAL.DERIVATION_PATH);
|
|
7522
|
+
const savedBasePath = await this._storage.get(STORAGE_KEYS_GLOBAL.BASE_PATH);
|
|
7523
|
+
const savedDerivationMode = await this._storage.get(STORAGE_KEYS_GLOBAL.DERIVATION_MODE);
|
|
7524
|
+
const savedSource = await this._storage.get(STORAGE_KEYS_GLOBAL.WALLET_SOURCE);
|
|
7525
|
+
const savedAddressIndex = await this._storage.get(STORAGE_KEYS_GLOBAL.CURRENT_ADDRESS_INDEX);
|
|
6902
7526
|
this._basePath = savedBasePath ?? DEFAULT_BASE_PATH;
|
|
6903
7527
|
this._derivationMode = savedDerivationMode ?? "bip32";
|
|
6904
7528
|
this._source = savedSource ?? "unknown";
|
|
@@ -6932,65 +7556,60 @@ var Sphere = class _Sphere {
|
|
|
6932
7556
|
this._storage.setIdentity(this._identity);
|
|
6933
7557
|
}
|
|
6934
7558
|
await this.loadAddressNametags();
|
|
6935
|
-
const savedNametag = await this._storage.get(STORAGE_KEYS.NAMETAG);
|
|
6936
7559
|
if (this._currentAddressIndex > 0 && this._masterKey) {
|
|
6937
7560
|
const addressInfo = this.deriveAddress(this._currentAddressIndex, false);
|
|
6938
7561
|
const ipnsHash = sha256(addressInfo.publicKey, "hex").slice(0, 40);
|
|
6939
7562
|
const predicateAddress = await deriveL3PredicateAddress(addressInfo.privateKey);
|
|
6940
|
-
const
|
|
7563
|
+
const addressId = getAddressId(predicateAddress);
|
|
7564
|
+
const nametagsMap = this._addressNametags.get(addressId);
|
|
7565
|
+
const nametag = nametagsMap?.get(0);
|
|
6941
7566
|
this._identity = {
|
|
6942
7567
|
privateKey: addressInfo.privateKey,
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
predicateAddress,
|
|
7568
|
+
chainPubkey: addressInfo.publicKey,
|
|
7569
|
+
l1Address: addressInfo.address,
|
|
7570
|
+
directAddress: predicateAddress,
|
|
6946
7571
|
ipnsName: "12D3KooW" + ipnsHash,
|
|
6947
7572
|
nametag
|
|
6948
7573
|
};
|
|
6949
7574
|
this._storage.setIdentity(this._identity);
|
|
6950
|
-
console.log(`[Sphere] Restored to address ${this._currentAddressIndex}:`, this._identity.
|
|
6951
|
-
} else {
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
console.log("[Sphere] Restored nametag:", savedNametag);
|
|
6958
|
-
} else if (this._identity) {
|
|
6959
|
-
const nametag = this._addressNametags.get(0);
|
|
6960
|
-
if (nametag) {
|
|
6961
|
-
this._identity.nametag = nametag;
|
|
6962
|
-
console.log("[Sphere] Restored nametag from map:", nametag);
|
|
6963
|
-
}
|
|
7575
|
+
console.log(`[Sphere] Restored to address ${this._currentAddressIndex}:`, this._identity.l1Address);
|
|
7576
|
+
} else if (this._identity) {
|
|
7577
|
+
const addressId = this.getCurrentAddressId();
|
|
7578
|
+
const nametagsMap = addressId ? this._addressNametags.get(addressId) : void 0;
|
|
7579
|
+
const nametag = nametagsMap?.get(0);
|
|
7580
|
+
if (nametag) {
|
|
7581
|
+
this._identity.nametag = nametag;
|
|
6964
7582
|
}
|
|
6965
7583
|
}
|
|
6966
7584
|
}
|
|
6967
7585
|
async initializeIdentityFromMnemonic(mnemonic, derivationPath) {
|
|
6968
|
-
const
|
|
7586
|
+
const basePath = derivationPath ?? DEFAULT_BASE_PATH;
|
|
7587
|
+
const fullPath = `${basePath}/0/0`;
|
|
6969
7588
|
const masterKey = identityFromMnemonicSync(mnemonic);
|
|
6970
7589
|
const derivedKey = deriveKeyAtPath(
|
|
6971
7590
|
masterKey.privateKey,
|
|
6972
7591
|
masterKey.chainCode,
|
|
6973
|
-
|
|
7592
|
+
fullPath
|
|
6974
7593
|
);
|
|
6975
7594
|
const publicKey = getPublicKey(derivedKey.privateKey);
|
|
6976
|
-
const
|
|
7595
|
+
const address = publicKeyToAddress(publicKey, "alpha");
|
|
6977
7596
|
const ipnsHash = sha256(publicKey, "hex").slice(0, 40);
|
|
6978
7597
|
const predicateAddress = await deriveL3PredicateAddress(derivedKey.privateKey);
|
|
6979
7598
|
this._identity = {
|
|
6980
7599
|
privateKey: derivedKey.privateKey,
|
|
6981
|
-
publicKey,
|
|
6982
|
-
|
|
6983
|
-
predicateAddress,
|
|
7600
|
+
chainPubkey: publicKey,
|
|
7601
|
+
l1Address: address,
|
|
7602
|
+
directAddress: predicateAddress,
|
|
6984
7603
|
ipnsName: "12D3KooW" + ipnsHash
|
|
6985
7604
|
};
|
|
6986
7605
|
this._masterKey = masterKey;
|
|
6987
|
-
console.log("[Sphere] Identity initialized from mnemonic, path:", path);
|
|
6988
7606
|
}
|
|
6989
7607
|
async initializeIdentityFromMasterKey(masterKey, chainCode, derivationPath) {
|
|
6990
|
-
const
|
|
7608
|
+
const basePath = derivationPath ?? DEFAULT_BASE_PATH;
|
|
7609
|
+
const fullPath = `${basePath}/0/0`;
|
|
6991
7610
|
let privateKey;
|
|
6992
7611
|
if (chainCode) {
|
|
6993
|
-
const derivedKey = deriveKeyAtPath(masterKey, chainCode,
|
|
7612
|
+
const derivedKey = deriveKeyAtPath(masterKey, chainCode, fullPath);
|
|
6994
7613
|
privateKey = derivedKey.privateKey;
|
|
6995
7614
|
this._masterKey = {
|
|
6996
7615
|
privateKey: masterKey,
|
|
@@ -7001,17 +7620,16 @@ var Sphere = class _Sphere {
|
|
|
7001
7620
|
this._masterKey = null;
|
|
7002
7621
|
}
|
|
7003
7622
|
const publicKey = getPublicKey(privateKey);
|
|
7004
|
-
const
|
|
7623
|
+
const address = publicKeyToAddress(publicKey, "alpha");
|
|
7005
7624
|
const ipnsHash = sha256(publicKey, "hex").slice(0, 40);
|
|
7006
7625
|
const predicateAddress = await deriveL3PredicateAddress(privateKey);
|
|
7007
7626
|
this._identity = {
|
|
7008
7627
|
privateKey,
|
|
7009
|
-
publicKey,
|
|
7010
|
-
|
|
7011
|
-
predicateAddress,
|
|
7628
|
+
chainPubkey: publicKey,
|
|
7629
|
+
l1Address: address,
|
|
7630
|
+
directAddress: predicateAddress,
|
|
7012
7631
|
ipnsName: "12D3KooW" + ipnsHash
|
|
7013
7632
|
};
|
|
7014
|
-
console.log("[Sphere] Identity initialized from master key, path:", path, "chainCode:", !!chainCode);
|
|
7015
7633
|
}
|
|
7016
7634
|
// ===========================================================================
|
|
7017
7635
|
// Private: Provider & Module Initialization
|
|
@@ -7439,6 +8057,7 @@ export {
|
|
|
7439
8057
|
TEST_ELECTRUM_URL,
|
|
7440
8058
|
TEST_NOSTR_RELAYS,
|
|
7441
8059
|
TIMEOUTS,
|
|
8060
|
+
TokenRegistry,
|
|
7442
8061
|
TokenValidator,
|
|
7443
8062
|
archivedKeyFromTokenId,
|
|
7444
8063
|
base58Decode,
|
|
@@ -7469,10 +8088,17 @@ export {
|
|
|
7469
8088
|
generateMasterKey,
|
|
7470
8089
|
generateMnemonic2 as generateMnemonic,
|
|
7471
8090
|
getAddressHrp,
|
|
8091
|
+
getCoinIdByName,
|
|
8092
|
+
getCoinIdBySymbol,
|
|
7472
8093
|
getCurrentStateHash,
|
|
7473
8094
|
getPublicKey,
|
|
7474
8095
|
getSphere,
|
|
8096
|
+
getTokenDecimals,
|
|
8097
|
+
getTokenDefinition,
|
|
8098
|
+
getTokenIconUrl,
|
|
7475
8099
|
getTokenId,
|
|
8100
|
+
getTokenName,
|
|
8101
|
+
getTokenSymbol,
|
|
7476
8102
|
hasMissingNewStateHash,
|
|
7477
8103
|
hasUncommittedTransactions,
|
|
7478
8104
|
hasValidTxfData,
|
|
@@ -7482,6 +8108,7 @@ export {
|
|
|
7482
8108
|
initSphere,
|
|
7483
8109
|
isArchivedKey,
|
|
7484
8110
|
isForkedKey,
|
|
8111
|
+
isKnownToken,
|
|
7485
8112
|
isSQLiteDatabase,
|
|
7486
8113
|
isTextWalletEncrypted,
|
|
7487
8114
|
isTokenKey,
|