@naculus/connect-appkit-core 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/index.cjs +188 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +142 -6
- package/dist/index.d.ts +142 -6
- package/dist/index.js +173 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -478,6 +478,13 @@ function saveNotificationSettings(storage, settings) {
|
|
|
478
478
|
function updateNotificationSettings(current, update) {
|
|
479
479
|
return { ...current, ...update };
|
|
480
480
|
}
|
|
481
|
+
function replayNotificationSettings(persisted, updates) {
|
|
482
|
+
let settings = persisted ?? DEFAULT_NOTIFICATION_SETTINGS;
|
|
483
|
+
for (const update of updates) {
|
|
484
|
+
settings = updateNotificationSettings(settings, update(settings));
|
|
485
|
+
}
|
|
486
|
+
return settings;
|
|
487
|
+
}
|
|
481
488
|
function channelsUpdate(channels) {
|
|
482
489
|
const update = {};
|
|
483
490
|
if (channels.includes("telegram")) update.telegram = true;
|
|
@@ -1289,7 +1296,127 @@ function createDelegationPolicyFlow(deps) {
|
|
|
1289
1296
|
};
|
|
1290
1297
|
}
|
|
1291
1298
|
|
|
1299
|
+
// src/authorization.ts
|
|
1300
|
+
import {
|
|
1301
|
+
evaluateSpend
|
|
1302
|
+
} from "@naculus/connect-core";
|
|
1303
|
+
function assetAddress(asset) {
|
|
1304
|
+
return asset.split(/[:/]/).at(-1);
|
|
1305
|
+
}
|
|
1306
|
+
function groupDigits(value) {
|
|
1307
|
+
return value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1308
|
+
}
|
|
1309
|
+
function formatAuthorizationAmount(amount, metadata) {
|
|
1310
|
+
const baseUnits = amount.toString();
|
|
1311
|
+
if (!metadata || !metadata.symbol || !Number.isSafeInteger(metadata.decimals) || metadata.decimals < 0) {
|
|
1312
|
+
return {
|
|
1313
|
+
formatted: `${groupDigits(baseUnits)} base units`
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
const decimals = metadata.decimals;
|
|
1317
|
+
const padded = baseUnits.padStart(decimals + 1, "0");
|
|
1318
|
+
const integer = decimals === 0 ? padded : padded.slice(0, -decimals);
|
|
1319
|
+
const fraction = decimals === 0 ? "" : padded.slice(-decimals).replace(/0+$/, "");
|
|
1320
|
+
const value = `${groupDigits(integer)}${fraction ? `.${fraction}` : ""}`;
|
|
1321
|
+
return { formatted: `${value} ${metadata.symbol}` };
|
|
1322
|
+
}
|
|
1323
|
+
function relativeExpiry(expiresAt, now, locale) {
|
|
1324
|
+
const seconds = expiresAt - now;
|
|
1325
|
+
const absolute = Math.abs(seconds);
|
|
1326
|
+
const divisor = absolute >= 31536e3 ? 31536e3 : absolute >= 2592e3 ? 2592e3 : absolute >= 86400 ? 86400 : absolute >= 3600 ? 3600 : absolute >= 60 ? 60 : 1;
|
|
1327
|
+
const unit = divisor === 31536e3 ? "year" : divisor === 2592e3 ? "month" : divisor === 86400 ? "day" : divisor === 3600 ? "hour" : divisor === 60 ? "minute" : "second";
|
|
1328
|
+
return new Intl.RelativeTimeFormat(locale).format(
|
|
1329
|
+
Math.round(seconds / divisor),
|
|
1330
|
+
unit
|
|
1331
|
+
);
|
|
1332
|
+
}
|
|
1333
|
+
function describeAuthorization(input, options = {}) {
|
|
1334
|
+
const now = options.now ?? Math.floor(Date.now() / 1e3);
|
|
1335
|
+
const locale = options.locale ?? "en";
|
|
1336
|
+
const flags = "flags" in input ? input.flags : [];
|
|
1337
|
+
const label = "label" in input ? input.label ?? null : null;
|
|
1338
|
+
return {
|
|
1339
|
+
label,
|
|
1340
|
+
principal: input.principal ?? null,
|
|
1341
|
+
grants: input.grants.map((grant) => {
|
|
1342
|
+
const metadata = options.assets?.[grant.asset];
|
|
1343
|
+
return {
|
|
1344
|
+
asset: grant.asset,
|
|
1345
|
+
assetLabel: metadata?.symbol || assetAddress(grant.asset),
|
|
1346
|
+
recipients: grant.recipients.map((full) => ({
|
|
1347
|
+
shortened: full.length <= 14 ? full : `${full.slice(0, 6)}\u2026${full.slice(-6)}`,
|
|
1348
|
+
full
|
|
1349
|
+
})),
|
|
1350
|
+
perPayment: formatAuthorizationAmount(grant.maxPerPayment, metadata),
|
|
1351
|
+
total: formatAuthorizationAmount(grant.maxTotal, metadata),
|
|
1352
|
+
count: grant.maxCount ?? null,
|
|
1353
|
+
rails: grant.rails.map((r) => r.replace("-", " "))
|
|
1354
|
+
};
|
|
1355
|
+
}),
|
|
1356
|
+
expiry: {
|
|
1357
|
+
timestamp: input.expiresAt,
|
|
1358
|
+
absolute: new Intl.DateTimeFormat(locale, {
|
|
1359
|
+
year: "numeric",
|
|
1360
|
+
month: "short",
|
|
1361
|
+
day: "numeric",
|
|
1362
|
+
hour: "2-digit",
|
|
1363
|
+
minute: "2-digit",
|
|
1364
|
+
hourCycle: "h23",
|
|
1365
|
+
timeZone: "UTC",
|
|
1366
|
+
timeZoneName: "short"
|
|
1367
|
+
}).format(input.expiresAt * 1e3),
|
|
1368
|
+
relative: relativeExpiry(input.expiresAt, now, locale)
|
|
1369
|
+
},
|
|
1370
|
+
warnings: flags.map(
|
|
1371
|
+
(flag) => flag === "unrestricted-recipient-legacy" ? "This key can pay any recipient." : "This key can do more than shown here."
|
|
1372
|
+
)
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
var REFUSAL_SENTENCES = {
|
|
1376
|
+
expired: "This authorization has expired.",
|
|
1377
|
+
"not-yet-valid": "This authorization is not valid yet.",
|
|
1378
|
+
"no-matching-grant": "No grant covers this asset.",
|
|
1379
|
+
"recipient-not-allowed": "This recipient is not allowed.",
|
|
1380
|
+
"over-per-payment": "This amount exceeds the per-payment limit.",
|
|
1381
|
+
"over-total": "This amount exceeds the remaining total limit.",
|
|
1382
|
+
"over-count": "This authorization has reached its payment count limit.",
|
|
1383
|
+
"rail-not-allowed": "This payment rail is not allowed.",
|
|
1384
|
+
"invalid-authorization": "The authorization or spend request is invalid."
|
|
1385
|
+
};
|
|
1386
|
+
function explainSpend(authorization, request, options = {}) {
|
|
1387
|
+
const verdict = evaluateSpend(authorization, request);
|
|
1388
|
+
if (!verdict.allow) {
|
|
1389
|
+
return {
|
|
1390
|
+
allowed: false,
|
|
1391
|
+
reason: verdict.reason,
|
|
1392
|
+
sentence: REFUSAL_SENTENCES[verdict.reason]
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
const remainingTotal = authorization.grants[verdict.grant].maxTotal - request.spentSoFar - request.amount;
|
|
1396
|
+
const remainingTotalFormatted = formatAuthorizationAmount(
|
|
1397
|
+
remainingTotal,
|
|
1398
|
+
options.assets?.[authorization.grants[verdict.grant].asset]
|
|
1399
|
+
);
|
|
1400
|
+
return {
|
|
1401
|
+
allowed: true,
|
|
1402
|
+
grant: verdict.grant,
|
|
1403
|
+
remainingTotal,
|
|
1404
|
+
remainingTotalFormatted,
|
|
1405
|
+
sentence: `Allowed by grant ${verdict.grant + 1}; ${remainingTotalFormatted.formatted} remain.`
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1292
1409
|
// src/payment-fetch.ts
|
|
1410
|
+
var DEFAULT_VERIFY_RETRY = { attempts: 5, delayMs: 4e3 };
|
|
1411
|
+
function applySettlementVerification(payment, result) {
|
|
1412
|
+
return {
|
|
1413
|
+
...payment,
|
|
1414
|
+
verification: {
|
|
1415
|
+
status: result.status,
|
|
1416
|
+
..."reason" in result && result.reason !== void 0 ? { reason: result.reason } : {}
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1293
1420
|
function record(value) {
|
|
1294
1421
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
1295
1422
|
}
|
|
@@ -1319,7 +1446,8 @@ function describePayment(input, result) {
|
|
|
1319
1446
|
payTo: text(paid.payTo),
|
|
1320
1447
|
amount: text(paid.amount),
|
|
1321
1448
|
// A hash reported for another chain is not this payment's.
|
|
1322
|
-
reference: settlement?.success === true && settlement.network === paid.network ? text(settlement.transaction) : null
|
|
1449
|
+
reference: settlement?.success === true && settlement.network === paid.network ? text(settlement.transaction) : null,
|
|
1450
|
+
verification: { status: "unverified" }
|
|
1323
1451
|
};
|
|
1324
1452
|
}
|
|
1325
1453
|
const challenge = record(record(paid.challenge)?.params);
|
|
@@ -1333,7 +1461,8 @@ function describePayment(input, result) {
|
|
|
1333
1461
|
asset: text(request.currency),
|
|
1334
1462
|
payTo: text(request.recipient),
|
|
1335
1463
|
amount: text(request.amount),
|
|
1336
|
-
reference: text(record(result.receipt)?.reference)
|
|
1464
|
+
reference: text(record(result.receipt)?.reference),
|
|
1465
|
+
verification: { status: "unverified" }
|
|
1337
1466
|
};
|
|
1338
1467
|
}
|
|
1339
1468
|
return {
|
|
@@ -1343,10 +1472,41 @@ function describePayment(input, result) {
|
|
|
1343
1472
|
asset: null,
|
|
1344
1473
|
payTo: null,
|
|
1345
1474
|
amount: null,
|
|
1346
|
-
reference: null
|
|
1475
|
+
reference: null,
|
|
1476
|
+
verification: { status: "unverified" }
|
|
1347
1477
|
};
|
|
1348
1478
|
}
|
|
1349
1479
|
|
|
1480
|
+
// src/mpp-session.ts
|
|
1481
|
+
function record2(value) {
|
|
1482
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
1483
|
+
}
|
|
1484
|
+
function readMppSessionChannel(value) {
|
|
1485
|
+
const channel = record2(value);
|
|
1486
|
+
if (!channel || typeof channel.channelId !== "string" || typeof channel.payer !== "string" || typeof channel.payee !== "string" || typeof channel.mint !== "string" || typeof channel.channelProgram !== "string" || typeof channel.deposit !== "bigint" || typeof channel.gracePeriodSeconds !== "number" || typeof channel.openSlot !== "bigint" || typeof channel.salt !== "bigint") {
|
|
1487
|
+
return null;
|
|
1488
|
+
}
|
|
1489
|
+
return channel;
|
|
1490
|
+
}
|
|
1491
|
+
function readCurrentMppSessionChannel(session) {
|
|
1492
|
+
for (let index = session.channels.length - 1; index >= 0; index--) {
|
|
1493
|
+
const channel = readMppSessionChannel(session.channels[index]);
|
|
1494
|
+
if (channel) return channel;
|
|
1495
|
+
}
|
|
1496
|
+
return null;
|
|
1497
|
+
}
|
|
1498
|
+
function readMppSessionReceipt(value) {
|
|
1499
|
+
const receipt = record2(value);
|
|
1500
|
+
if (receipt?.status !== "success" || typeof receipt.method !== "string" || typeof receipt.timestamp !== "string" || typeof receipt.reference !== "string") {
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
return receipt;
|
|
1504
|
+
}
|
|
1505
|
+
function readMppRecoveryChannelId(error) {
|
|
1506
|
+
const channelId = record2(error)?.channelId;
|
|
1507
|
+
return typeof channelId === "string" && channelId !== "" ? channelId : null;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1350
1510
|
// src/solana-session-key.ts
|
|
1351
1511
|
import {
|
|
1352
1512
|
verifySignedOwnerTransaction,
|
|
@@ -1567,10 +1727,12 @@ function siwxResultToSession(result, now = /* @__PURE__ */ new Date()) {
|
|
|
1567
1727
|
}
|
|
1568
1728
|
export {
|
|
1569
1729
|
DEFAULT_NOTIFICATION_SETTINGS,
|
|
1730
|
+
DEFAULT_VERIFY_RETRY,
|
|
1570
1731
|
InvalidUserOperationReceiptError,
|
|
1571
1732
|
NOTIFICATION_SETTINGS_KEY,
|
|
1572
1733
|
__resetResolverForTests,
|
|
1573
1734
|
addInAppNotification,
|
|
1735
|
+
applySettlementVerification,
|
|
1574
1736
|
assertHexSignature,
|
|
1575
1737
|
atomicSupportFor,
|
|
1576
1738
|
bareEvmAddress,
|
|
@@ -1591,13 +1753,16 @@ export {
|
|
|
1591
1753
|
decodeRevertReason,
|
|
1592
1754
|
defaultSiwxDomain,
|
|
1593
1755
|
defaultSiwxUri,
|
|
1756
|
+
describeAuthorization,
|
|
1594
1757
|
describeChain,
|
|
1595
1758
|
describePayment,
|
|
1596
1759
|
eip155ChainIdToNumber,
|
|
1597
1760
|
encodeErc20Approve,
|
|
1598
1761
|
encodeErc20Transfer,
|
|
1599
1762
|
encodeErc20TransferFrom,
|
|
1763
|
+
explainSpend,
|
|
1600
1764
|
fetchUserOperationReceipt,
|
|
1765
|
+
formatAuthorizationAmount,
|
|
1601
1766
|
getResolver,
|
|
1602
1767
|
getSharedSessionKeyManager,
|
|
1603
1768
|
initialWeb3State,
|
|
@@ -1613,8 +1778,13 @@ export {
|
|
|
1613
1778
|
normalizeCapabilities,
|
|
1614
1779
|
normalizeEip155ChainId,
|
|
1615
1780
|
parseUserOperationReceipt,
|
|
1781
|
+
readCurrentMppSessionChannel,
|
|
1616
1782
|
readDecimals,
|
|
1783
|
+
readMppRecoveryChannelId,
|
|
1784
|
+
readMppSessionChannel,
|
|
1785
|
+
readMppSessionReceipt,
|
|
1617
1786
|
readSolanaRoles,
|
|
1787
|
+
replayNotificationSettings,
|
|
1618
1788
|
resetSharedSessionKeyManager,
|
|
1619
1789
|
resolveChain,
|
|
1620
1790
|
resolveContextSimulationEndpoint,
|