@naculus/connect-appkit-core 0.8.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +99 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +94 -18
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -44,6 +44,7 @@ __export(src_exports, {
|
|
|
44
44
|
createNotification: () => createNotification,
|
|
45
45
|
createNotificationSettingsStorage: () => createNotificationSettingsStorage,
|
|
46
46
|
createSolanaSessionKeyFlow: () => createSolanaSessionKeyFlow,
|
|
47
|
+
createX402WalletSigner: () => createX402WalletSigner,
|
|
47
48
|
decodeRevertReason: () => decodeRevertReason,
|
|
48
49
|
defaultSiwxDomain: () => defaultSiwxDomain,
|
|
49
50
|
defaultSiwxUri: () => defaultSiwxUri,
|
|
@@ -56,6 +57,7 @@ __export(src_exports, {
|
|
|
56
57
|
encodeErc20TransferFrom: () => encodeErc20TransferFrom,
|
|
57
58
|
explainSpend: () => explainSpend,
|
|
58
59
|
fetchUserOperationReceipt: () => fetchUserOperationReceipt,
|
|
60
|
+
findX402Provider: () => findX402Provider,
|
|
59
61
|
formatAuthorizationAmount: () => formatAuthorizationAmount,
|
|
60
62
|
getResolver: () => getResolver,
|
|
61
63
|
getSharedSessionKeyManager: () => getSharedSessionKeyManager,
|
|
@@ -86,6 +88,7 @@ __export(src_exports, {
|
|
|
86
88
|
resolveRevertReason: () => resolveRevertReason,
|
|
87
89
|
resolveSimulationEndpoint: () => resolveSimulationEndpoint,
|
|
88
90
|
resolveUserOpChain: () => resolveUserOpChain,
|
|
91
|
+
resolveX402Wallet: () => resolveX402Wallet,
|
|
89
92
|
sameExecutionIntent: () => sameExecutionIntent,
|
|
90
93
|
saveNotificationSettings: () => saveNotificationSettings,
|
|
91
94
|
selectChainCapabilities: () => selectChainCapabilities,
|
|
@@ -1381,35 +1384,51 @@ function createDelegationPolicyFlow(deps) {
|
|
|
1381
1384
|
|
|
1382
1385
|
// src/authorization.ts
|
|
1383
1386
|
var import_connect_core17 = require("@naculus/connect-core");
|
|
1384
|
-
function assetAddress(asset) {
|
|
1385
|
-
return asset.split(/[:/]/).at(-1);
|
|
1386
|
-
}
|
|
1387
1387
|
function groupDigits(value) {
|
|
1388
|
-
|
|
1388
|
+
let out = "";
|
|
1389
|
+
for (let i = 0; i < value.length; i++)
|
|
1390
|
+
out += (i && (value.length - i) % 3 === 0 ? "," : "") + value[i];
|
|
1391
|
+
return out;
|
|
1392
|
+
}
|
|
1393
|
+
function trustedMetadata(asset, options) {
|
|
1394
|
+
const trust = !options.trustedAssets ? "unchecked" : options.trustedAssets.some(
|
|
1395
|
+
(t) => canonicalAssetId(t) === canonicalAssetId(asset)
|
|
1396
|
+
) ? "trusted" : "unverified";
|
|
1397
|
+
return [trust, trust === "unverified" ? void 0 : options.assets?.[asset]];
|
|
1398
|
+
}
|
|
1399
|
+
function canonicalAssetId(asset) {
|
|
1400
|
+
return asset.replace(
|
|
1401
|
+
/^(eip155:[^/]+\/erc20:)(.+)$/,
|
|
1402
|
+
(_, prefix, reference) => prefix + reference.toLowerCase()
|
|
1403
|
+
);
|
|
1389
1404
|
}
|
|
1390
1405
|
function formatAuthorizationAmount(amount, metadata) {
|
|
1391
1406
|
const baseUnits = amount.toString();
|
|
1392
|
-
if (!metadata
|
|
1407
|
+
if (!metadata?.symbol || !Number.isSafeInteger(metadata.decimals) || metadata.decimals < 0 || metadata.decimals > 255) {
|
|
1393
1408
|
return {
|
|
1394
1409
|
formatted: `${groupDigits(baseUnits)} base units`
|
|
1395
1410
|
};
|
|
1396
1411
|
}
|
|
1397
1412
|
const decimals = metadata.decimals;
|
|
1398
1413
|
const padded = baseUnits.padStart(decimals + 1, "0");
|
|
1399
|
-
const integer =
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
return {
|
|
1414
|
+
const integer = padded.slice(0, decimals ? -decimals : void 0);
|
|
1415
|
+
let fraction = decimals ? padded.slice(-decimals) : "";
|
|
1416
|
+
while (fraction.endsWith("0")) fraction = fraction.slice(0, -1);
|
|
1417
|
+
return {
|
|
1418
|
+
formatted: `${groupDigits(integer)}${fraction ? `.${fraction}` : ""} ${metadata.symbol}`
|
|
1419
|
+
};
|
|
1403
1420
|
}
|
|
1404
1421
|
function relativeExpiry(expiresAt, now, locale) {
|
|
1405
1422
|
const seconds = expiresAt - now;
|
|
1406
1423
|
const absolute = Math.abs(seconds);
|
|
1407
|
-
const divisor = absolute >= 31536e3 ? 31536e3 : absolute >= 2592e3 ? 2592e3 : absolute >= 86400 ? 86400 : absolute >= 3600 ? 3600 : absolute >= 60 ? 60 : 1;
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1410
|
-
Math.
|
|
1411
|
-
unit
|
|
1412
|
-
|
|
1424
|
+
const [divisor, unit] = absolute >= 31536e3 ? [31536e3, "year"] : absolute >= 2592e3 ? [2592e3, "month"] : absolute >= 86400 ? [86400, "day"] : absolute >= 3600 ? [3600, "hour"] : absolute >= 60 ? [60, "minute"] : [1, "second"];
|
|
1425
|
+
const value = Math.round(seconds / divisor);
|
|
1426
|
+
if (typeof Intl.RelativeTimeFormat !== "function") {
|
|
1427
|
+
const count = Math.abs(value);
|
|
1428
|
+
const phrase = `${count} ${unit}${count === 1 ? "" : "s"}`;
|
|
1429
|
+
return value < 0 || Object.is(value, -0) ? `${phrase} ago` : `in ${phrase}`;
|
|
1430
|
+
}
|
|
1431
|
+
return new Intl.RelativeTimeFormat(locale).format(value, unit);
|
|
1413
1432
|
}
|
|
1414
1433
|
function describeAuthorization(input, options = {}) {
|
|
1415
1434
|
const now = options.now ?? Math.floor(Date.now() / 1e3);
|
|
@@ -1420,10 +1439,11 @@ function describeAuthorization(input, options = {}) {
|
|
|
1420
1439
|
label,
|
|
1421
1440
|
principal: input.principal ?? null,
|
|
1422
1441
|
grants: input.grants.map((grant) => {
|
|
1423
|
-
const metadata =
|
|
1442
|
+
const [assetTrust, metadata] = trustedMetadata(grant.asset, options);
|
|
1424
1443
|
return {
|
|
1425
1444
|
asset: grant.asset,
|
|
1426
|
-
|
|
1445
|
+
assetTrust,
|
|
1446
|
+
assetLabel: metadata?.symbol || grant.asset.split(":").at(-1),
|
|
1427
1447
|
recipients: grant.recipients.map((full) => ({
|
|
1428
1448
|
shortened: full.length <= 14 ? full : `${full.slice(0, 6)}\u2026${full.slice(-6)}`,
|
|
1429
1449
|
full
|
|
@@ -1476,7 +1496,7 @@ function explainSpend(authorization, request, options = {}) {
|
|
|
1476
1496
|
const remainingTotal = authorization.grants[verdict.grant].maxTotal - request.spentSoFar - request.amount;
|
|
1477
1497
|
const remainingTotalFormatted = formatAuthorizationAmount(
|
|
1478
1498
|
remainingTotal,
|
|
1479
|
-
|
|
1499
|
+
trustedMetadata(authorization.grants[verdict.grant].asset, options)[1]
|
|
1480
1500
|
);
|
|
1481
1501
|
return {
|
|
1482
1502
|
allowed: true,
|
|
@@ -1558,6 +1578,57 @@ function describePayment(input, result) {
|
|
|
1558
1578
|
};
|
|
1559
1579
|
}
|
|
1560
1580
|
|
|
1581
|
+
// src/x402-wallet.ts
|
|
1582
|
+
var import_connect_core18 = require("@naculus/connect-core");
|
|
1583
|
+
var import_payments_x402 = require("@naculus/payments-x402");
|
|
1584
|
+
function findX402Provider(session, sources) {
|
|
1585
|
+
if (!session) return null;
|
|
1586
|
+
if (session.walletType === "eip6963" || session.id.startsWith("eip6963-")) {
|
|
1587
|
+
return sources.injected?.find((wallet) => wallet.id === session.walletId)?.provider ?? null;
|
|
1588
|
+
}
|
|
1589
|
+
if (session.walletType === "walletconnect") {
|
|
1590
|
+
return sources.walletConnect ?? null;
|
|
1591
|
+
}
|
|
1592
|
+
return null;
|
|
1593
|
+
}
|
|
1594
|
+
function unavailable(reason) {
|
|
1595
|
+
return { provider: null, address: null, reason };
|
|
1596
|
+
}
|
|
1597
|
+
function resolveX402Wallet(session, provider) {
|
|
1598
|
+
if (!session) return unavailable("no-session");
|
|
1599
|
+
const namespace = session.namespaces.eip155;
|
|
1600
|
+
if (!namespace) return unavailable("not-evm");
|
|
1601
|
+
const isInjected = session.walletType === "eip6963" || session.id.startsWith("eip6963-");
|
|
1602
|
+
const isWalletConnect = session.walletType === "walletconnect";
|
|
1603
|
+
if (!isInjected && !isWalletConnect || !provider?.request) {
|
|
1604
|
+
return unavailable("unsupported-wallet-type");
|
|
1605
|
+
}
|
|
1606
|
+
for (const account of namespace.accounts) {
|
|
1607
|
+
const parsed = (0, import_connect_core18.parseCaip10)(account);
|
|
1608
|
+
const address = parsed?.namespace === "eip155" ? parsed.address : account;
|
|
1609
|
+
if ((0, import_connect_core18.isEvmAddress)(address)) {
|
|
1610
|
+
return {
|
|
1611
|
+
provider,
|
|
1612
|
+
address,
|
|
1613
|
+
reason: null
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
return unavailable("not-evm");
|
|
1618
|
+
}
|
|
1619
|
+
function createX402WalletSigner(session, provider, switchChain) {
|
|
1620
|
+
const resolved = resolveX402Wallet(session, provider);
|
|
1621
|
+
if (resolved.reason) return { signer: null, reason: resolved.reason };
|
|
1622
|
+
return {
|
|
1623
|
+
signer: (0, import_payments_x402.walletX402Signer)({
|
|
1624
|
+
provider: resolved.provider,
|
|
1625
|
+
address: resolved.address,
|
|
1626
|
+
switchChain
|
|
1627
|
+
}),
|
|
1628
|
+
reason: null
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1561
1632
|
// src/mpp-session.ts
|
|
1562
1633
|
function record2(value) {
|
|
1563
1634
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
@@ -1589,11 +1660,11 @@ function readMppRecoveryChannelId(error) {
|
|
|
1589
1660
|
}
|
|
1590
1661
|
|
|
1591
1662
|
// src/solana-session-key.ts
|
|
1592
|
-
var
|
|
1663
|
+
var import_connect_core19 = require("@naculus/connect-core");
|
|
1593
1664
|
function send(rpc) {
|
|
1594
1665
|
const sendTransaction = rpc.sendTransaction;
|
|
1595
1666
|
if (!sendTransaction) {
|
|
1596
|
-
throw new
|
|
1667
|
+
throw new import_connect_core19.WalletError(
|
|
1597
1668
|
"invalid_input",
|
|
1598
1669
|
"The Solana RPC must implement sendTransaction to approve or revoke."
|
|
1599
1670
|
);
|
|
@@ -1631,7 +1702,7 @@ function createSolanaSessionKeyFlow(deps) {
|
|
|
1631
1702
|
} catch (cause) {
|
|
1632
1703
|
await manager.revoke(draft.id).catch(() => {
|
|
1633
1704
|
});
|
|
1634
|
-
throw new
|
|
1705
|
+
throw new import_connect_core19.WalletError(
|
|
1635
1706
|
"rpc_error",
|
|
1636
1707
|
`The approval could not be confirmed as sent (${cause instanceof Error ? cause.message : String(cause)}); the key is revoked here. Call revoke("${draft.id}") to send the on-chain Revoke in case it landed.`
|
|
1637
1708
|
);
|
|
@@ -1642,7 +1713,7 @@ function createSolanaSessionKeyFlow(deps) {
|
|
|
1642
1713
|
async revoke(id) {
|
|
1643
1714
|
const key = (await list()).find((k) => k.id === id);
|
|
1644
1715
|
if (!key) {
|
|
1645
|
-
throw new
|
|
1716
|
+
throw new import_connect_core19.WalletError(
|
|
1646
1717
|
"invalid_input",
|
|
1647
1718
|
`No Solana session key ${id} for this owner.`
|
|
1648
1719
|
);
|
|
@@ -1654,7 +1725,7 @@ function createSolanaSessionKeyFlow(deps) {
|
|
|
1654
1725
|
rpc
|
|
1655
1726
|
);
|
|
1656
1727
|
const signed = await owner.signTransaction(transaction);
|
|
1657
|
-
const revocation = (0,
|
|
1728
|
+
const revocation = (0, import_connect_core19.verifySignedOwnerTransaction)(signed, {
|
|
1658
1729
|
kind: "revoke",
|
|
1659
1730
|
revocation: {
|
|
1660
1731
|
owner: key.owner,
|
|
@@ -1669,7 +1740,7 @@ function createSolanaSessionKeyFlow(deps) {
|
|
|
1669
1740
|
}
|
|
1670
1741
|
|
|
1671
1742
|
// src/web3-store.ts
|
|
1672
|
-
var
|
|
1743
|
+
var import_connect_core20 = require("@naculus/connect-core");
|
|
1673
1744
|
function withTimeout(promise, ms, label = "Operation") {
|
|
1674
1745
|
let timeoutId;
|
|
1675
1746
|
const timeout = new Promise((_, reject) => {
|
|
@@ -1691,7 +1762,7 @@ async function withRetry(fn, options) {
|
|
|
1691
1762
|
lastError = error;
|
|
1692
1763
|
if (attempt < options.maxRetries) {
|
|
1693
1764
|
const delay = options.baseDelay * 2 ** attempt;
|
|
1694
|
-
|
|
1765
|
+
import_connect_core20.logger.warn(
|
|
1695
1766
|
"appkit/core",
|
|
1696
1767
|
`Retry attempt ${attempt + 1}/${options.maxRetries} after ${delay}ms`
|
|
1697
1768
|
);
|
|
@@ -1829,6 +1900,7 @@ function siwxResultToSession(result, now = /* @__PURE__ */ new Date()) {
|
|
|
1829
1900
|
createNotification,
|
|
1830
1901
|
createNotificationSettingsStorage,
|
|
1831
1902
|
createSolanaSessionKeyFlow,
|
|
1903
|
+
createX402WalletSigner,
|
|
1832
1904
|
decodeRevertReason,
|
|
1833
1905
|
defaultSiwxDomain,
|
|
1834
1906
|
defaultSiwxUri,
|
|
@@ -1841,6 +1913,7 @@ function siwxResultToSession(result, now = /* @__PURE__ */ new Date()) {
|
|
|
1841
1913
|
encodeErc20TransferFrom,
|
|
1842
1914
|
explainSpend,
|
|
1843
1915
|
fetchUserOperationReceipt,
|
|
1916
|
+
findX402Provider,
|
|
1844
1917
|
formatAuthorizationAmount,
|
|
1845
1918
|
getResolver,
|
|
1846
1919
|
getSharedSessionKeyManager,
|
|
@@ -1871,6 +1944,7 @@ function siwxResultToSession(result, now = /* @__PURE__ */ new Date()) {
|
|
|
1871
1944
|
resolveRevertReason,
|
|
1872
1945
|
resolveSimulationEndpoint,
|
|
1873
1946
|
resolveUserOpChain,
|
|
1947
|
+
resolveX402Wallet,
|
|
1874
1948
|
sameExecutionIntent,
|
|
1875
1949
|
saveNotificationSettings,
|
|
1876
1950
|
selectChainCapabilities,
|