@capxul/sdk 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/{InMemoryAuthCacheAdapter-Rc8tCtml.mjs → InMemoryAuthCacheAdapter-PycLJWeW.mjs} +12 -2
- package/dist/{create-capxul-client-CMUq5w10.mjs → create-capxul-client-B8qMV-_e.mjs} +727 -530
- package/dist/index.d.mts +25 -64
- package/dist/index.mjs +141 -88
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.mjs +1 -1
- package/dist/{create-capxul-client-DmV6qEq4.d.mts → observation-BwPo8qeo.d.mts} +103 -17
- package/dist/{signer-Bj4F-RwT.d.mts → signer-D4roBkcX.d.mts} +94 -1
- package/dist/testing/index.d.mts +3 -1
- package/dist/testing/index.mjs +4 -3
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { concat, encodeAbiParameters, encodeFunctionData, encodePacked, formatUnits, getContractAddress, keccak256, padHex, parseUnits, stringToHex, toBytes, toEventSelector, toFunctionSelector, toFunctionSignature } from "viem";
|
|
1
|
+
import { C as toEmail, F as CapxulError, I as EXPECTED_OPERATION_OUTCOMES, L as Errors, O as toOrgId, R as isCapxulError, b as toCountryCode, c as BYTES32_RE, d as WEI_RE, f as ZERO_BYTES32, h as toAddress, j as toRoleKey, k as toPartyId, l as EVM_ADDRESS_RE$1, m as toAccountId, n as BrowserAuthCacheAdapter, s as APP_ID_RE, t as InMemoryAuthCacheAdapter, u as SUPPORTED_CURRENCY_CODES, v as toAuthUserId, x as toCurrencyCode, y as toChainId } from "./InMemoryAuthCacheAdapter-PycLJWeW.mjs";
|
|
2
|
+
import { concat, encodeAbiParameters, encodeFunctionData, encodePacked, formatUnits, getContractAddress, keccak256, padHex, parseUnits, recoverAddress, stringToHex, toBytes, toEventSelector, toFunctionSelector, toFunctionSignature } from "viem";
|
|
3
3
|
import { Context, Data, Deferred, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schema, SchemaGetter, Scope } from "effect";
|
|
4
4
|
import { makeFunctionReference } from "convex/server";
|
|
5
5
|
//#region src/domain/identity/model.ts
|
|
@@ -572,144 +572,6 @@ function normalizeBindingEmail(email) {
|
|
|
572
572
|
return normalizeSafeSaltEmail(email);
|
|
573
573
|
}
|
|
574
574
|
//#endregion
|
|
575
|
-
//#region ../config/src/route.ts
|
|
576
|
-
/** USDX on Base Sepolia — the only settlement token in v1. */
|
|
577
|
-
const USDX_BASE_SEPOLIA_TOKEN = {
|
|
578
|
-
chainId: BASE_SEPOLIA_CHAIN_ID,
|
|
579
|
-
address: USDX_ADDRESS_BASE_SEPOLIA,
|
|
580
|
-
decimals: 6
|
|
581
|
-
};
|
|
582
|
-
USDX_BASE_SEPOLIA_TOKEN.chainId;
|
|
583
|
-
USDX_BASE_SEPOLIA_TOKEN.chainId;
|
|
584
|
-
//#endregion
|
|
585
|
-
//#region ../config/src/role-dsl.ts
|
|
586
|
-
const USD_DECIMALS = 6;
|
|
587
|
-
const USD_SCALE = 10n ** BigInt(USD_DECIMALS);
|
|
588
|
-
const USD_DISPLAY_RE = /^\d+(?:\.\d{1,6})?$/;
|
|
589
|
-
const USD_BASE_UNIT_RE = /^\d+$/;
|
|
590
|
-
const EXEC_TRANSACTION_WITH_ROLE = "zodiac.roles.execTransactionWithRole";
|
|
591
|
-
const ASSIGN_ROLES = "zodiac.roles.assignRoles";
|
|
592
|
-
const SCOPE_TARGET = "zodiac.roles.scopeTarget";
|
|
593
|
-
const OWNER_ROLE_LABEL = "Owner";
|
|
594
|
-
const FOUNDER_BUDGET_ROLE_LABEL = "Founder Budget";
|
|
595
|
-
const FOUNDER_BUDGET_LIMIT = {
|
|
596
|
-
currency: "USD",
|
|
597
|
-
value: "1000000000000",
|
|
598
|
-
decimals: 6
|
|
599
|
-
};
|
|
600
|
-
function usd(value) {
|
|
601
|
-
return {
|
|
602
|
-
currency: "USD",
|
|
603
|
-
value: usdDisplayToBaseUnits(value),
|
|
604
|
-
decimals: USD_DECIMALS
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
function usdDisplayToBaseUnits(value) {
|
|
608
|
-
if (value.trim() !== value || !USD_DISPLAY_RE.test(value)) throw Errors.invalidInput("role.spend", "USD caps must be unsigned decimal strings with at most 6 fractional digits");
|
|
609
|
-
const parts = value.split(".");
|
|
610
|
-
const whole = parts[0] ?? "0";
|
|
611
|
-
const fraction = parts[1] ?? "";
|
|
612
|
-
return (BigInt(whole) * USD_SCALE + BigInt(fraction.padEnd(USD_DECIMALS, "0"))).toString();
|
|
613
|
-
}
|
|
614
|
-
function normalizeOrgRoleMoney(money, field) {
|
|
615
|
-
if (money.currency !== "USD" || money.decimals !== USD_DECIMALS || !USD_BASE_UNIT_RE.test(money.value)) throw Errors.invalidInput(field, `must be USD base units with ${USD_DECIMALS} decimals`);
|
|
616
|
-
return money;
|
|
617
|
-
}
|
|
618
|
-
function normalizeOrgRoleSpendCap(spend) {
|
|
619
|
-
if (spend === void 0) return void 0;
|
|
620
|
-
return {
|
|
621
|
-
...spend.perTx === void 0 ? {} : { perTx: normalizeOrgRoleMoney(spend.perTx, "roles.spend.perTx") },
|
|
622
|
-
...spend.perDay === void 0 ? {} : { perDay: normalizeOrgRoleMoney(spend.perDay, "roles.spend.perDay") },
|
|
623
|
-
...spend.toRecipients === void 0 ? {} : { toRecipients: spend.toRecipients }
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
function normalizeOrgRoleLabel(label) {
|
|
627
|
-
const normalized = label.trim().replace(/\s+/g, " ");
|
|
628
|
-
if (normalized.length === 0) throw Errors.invalidInput("role.label", "must be a non-empty role label");
|
|
629
|
-
return normalized;
|
|
630
|
-
}
|
|
631
|
-
function orgRoleKeyForLabel(label) {
|
|
632
|
-
return keccak256(toBytes(normalizeOrgRoleLabel(label).toLowerCase()));
|
|
633
|
-
}
|
|
634
|
-
function soloOrgRoleTemplate() {
|
|
635
|
-
return [{
|
|
636
|
-
label: "Owner",
|
|
637
|
-
canManageMembers: true,
|
|
638
|
-
canManageRoles: true
|
|
639
|
-
}, {
|
|
640
|
-
label: FOUNDER_BUDGET_ROLE_LABEL,
|
|
641
|
-
spend: {
|
|
642
|
-
perTx: FOUNDER_BUDGET_LIMIT,
|
|
643
|
-
perDay: FOUNDER_BUDGET_LIMIT,
|
|
644
|
-
toRecipients: "anyone"
|
|
645
|
-
}
|
|
646
|
-
}];
|
|
647
|
-
}
|
|
648
|
-
function startupOrgRoleTemplate() {
|
|
649
|
-
return [
|
|
650
|
-
...soloOrgRoleTemplate(),
|
|
651
|
-
{
|
|
652
|
-
label: "Finance Manager",
|
|
653
|
-
spend: {
|
|
654
|
-
perTx: usd("25000"),
|
|
655
|
-
perDay: usd("100000"),
|
|
656
|
-
toRecipients: "anyone"
|
|
657
|
-
}
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
label: "Team Lead",
|
|
661
|
-
spend: {
|
|
662
|
-
perTx: usd("5000"),
|
|
663
|
-
perDay: usd("15000"),
|
|
664
|
-
toRecipients: "anyone"
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
];
|
|
668
|
-
}
|
|
669
|
-
function orgRoleTemplateDefinitions(template, customRoles = []) {
|
|
670
|
-
switch (template) {
|
|
671
|
-
case "Solo": return soloOrgRoleTemplate();
|
|
672
|
-
case "Startup": return startupOrgRoleTemplate();
|
|
673
|
-
case "Custom": return customRoles.length === 0 ? soloOrgRoleTemplate() : customRoles;
|
|
674
|
-
default: return template;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
function compileOrgRoleDefinitions(definitions) {
|
|
678
|
-
if (definitions.length === 0) throw Errors.invalidInput("roles", "must include at least one role");
|
|
679
|
-
const seen = /* @__PURE__ */ new Set();
|
|
680
|
-
const roles = definitions.map((definition) => {
|
|
681
|
-
const label = normalizeOrgRoleLabel(definition.label);
|
|
682
|
-
const roleKey = orgRoleKeyForLabel(label);
|
|
683
|
-
if (seen.has(roleKey)) throw Errors.invalidInput("roles", `duplicate role label: ${label}`);
|
|
684
|
-
seen.add(roleKey);
|
|
685
|
-
const spend = normalizeOrgRoleSpendCap(definition.spend);
|
|
686
|
-
const permissions = [];
|
|
687
|
-
if (spend !== void 0 || label === OWNER_ROLE_LABEL) permissions.push(EXEC_TRANSACTION_WITH_ROLE);
|
|
688
|
-
if (definition.canManageMembers === true) permissions.push(ASSIGN_ROLES);
|
|
689
|
-
if (definition.canManageRoles === true) permissions.push(SCOPE_TARGET);
|
|
690
|
-
return {
|
|
691
|
-
label,
|
|
692
|
-
roleKey,
|
|
693
|
-
definition: {
|
|
694
|
-
...definition,
|
|
695
|
-
label,
|
|
696
|
-
...spend === void 0 ? {} : { spend }
|
|
697
|
-
},
|
|
698
|
-
permissions,
|
|
699
|
-
allowance: spend ?? null
|
|
700
|
-
};
|
|
701
|
-
});
|
|
702
|
-
const manager = roles.find((role) => role.definition.canManageMembers === true);
|
|
703
|
-
if (manager === void 0) throw Errors.invalidInput("roles.canManageMembers", "at least one role must compile to the on-chain member-management permission");
|
|
704
|
-
return {
|
|
705
|
-
roles,
|
|
706
|
-
memberManagementRole: {
|
|
707
|
-
roleKey: manager.roleKey,
|
|
708
|
-
permission: ASSIGN_ROLES
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
//#endregion
|
|
713
575
|
//#region ../config/src/capxul-payments-v2.ts
|
|
714
576
|
/** The exact compiled CapxulPaymentsV2 ABI. */
|
|
715
577
|
const CAPXUL_PAYMENTS_V2_ABI = [
|
|
@@ -1337,6 +1199,144 @@ const CAPXUL_PAYMENTS_V2_ABI = [
|
|
|
1337
1199
|
];
|
|
1338
1200
|
/** Immutable CapxulPaymentsV2 deployment on Base Sepolia. */
|
|
1339
1201
|
const CAPXUL_PAYMENTS_V2_ADDRESS = "0xA3ACDD016f706eD432A9a0545C45F0943f996b60";
|
|
1202
|
+
//#endregion
|
|
1203
|
+
//#region ../config/src/route.ts
|
|
1204
|
+
/** USDX on Base Sepolia — the only settlement token in v1. */
|
|
1205
|
+
const USDX_BASE_SEPOLIA_TOKEN = {
|
|
1206
|
+
chainId: BASE_SEPOLIA_CHAIN_ID,
|
|
1207
|
+
address: USDX_ADDRESS_BASE_SEPOLIA,
|
|
1208
|
+
decimals: 6
|
|
1209
|
+
};
|
|
1210
|
+
USDX_BASE_SEPOLIA_TOKEN.chainId;
|
|
1211
|
+
USDX_BASE_SEPOLIA_TOKEN.chainId;
|
|
1212
|
+
//#endregion
|
|
1213
|
+
//#region ../config/src/role-dsl.ts
|
|
1214
|
+
const USD_DECIMALS = 6;
|
|
1215
|
+
const USD_SCALE = 10n ** BigInt(USD_DECIMALS);
|
|
1216
|
+
const USD_DISPLAY_RE = /^\d+(?:\.\d{1,6})?$/;
|
|
1217
|
+
const USD_BASE_UNIT_RE = /^\d+$/;
|
|
1218
|
+
const EXEC_TRANSACTION_WITH_ROLE = "zodiac.roles.execTransactionWithRole";
|
|
1219
|
+
const ASSIGN_ROLES = "zodiac.roles.assignRoles";
|
|
1220
|
+
const SCOPE_TARGET = "zodiac.roles.scopeTarget";
|
|
1221
|
+
const OWNER_ROLE_LABEL = "Owner";
|
|
1222
|
+
const FOUNDER_BUDGET_ROLE_LABEL = "Founder Budget";
|
|
1223
|
+
const FOUNDER_BUDGET_LIMIT = {
|
|
1224
|
+
currency: "USD",
|
|
1225
|
+
value: "1000000000000",
|
|
1226
|
+
decimals: 6
|
|
1227
|
+
};
|
|
1228
|
+
function usd(value) {
|
|
1229
|
+
return {
|
|
1230
|
+
currency: "USD",
|
|
1231
|
+
value: usdDisplayToBaseUnits(value),
|
|
1232
|
+
decimals: USD_DECIMALS
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
function usdDisplayToBaseUnits(value) {
|
|
1236
|
+
if (value.trim() !== value || !USD_DISPLAY_RE.test(value)) throw Errors.invalidInput("role.spend", "USD caps must be unsigned decimal strings with at most 6 fractional digits");
|
|
1237
|
+
const parts = value.split(".");
|
|
1238
|
+
const whole = parts[0] ?? "0";
|
|
1239
|
+
const fraction = parts[1] ?? "";
|
|
1240
|
+
return (BigInt(whole) * USD_SCALE + BigInt(fraction.padEnd(USD_DECIMALS, "0"))).toString();
|
|
1241
|
+
}
|
|
1242
|
+
function normalizeOrgRoleMoney(money, field) {
|
|
1243
|
+
if (money.currency !== "USD" || money.decimals !== USD_DECIMALS || !USD_BASE_UNIT_RE.test(money.value)) throw Errors.invalidInput(field, `must be USD base units with ${USD_DECIMALS} decimals`);
|
|
1244
|
+
return money;
|
|
1245
|
+
}
|
|
1246
|
+
function normalizeOrgRoleSpendCap(spend) {
|
|
1247
|
+
if (spend === void 0) return void 0;
|
|
1248
|
+
return {
|
|
1249
|
+
...spend.perTx === void 0 ? {} : { perTx: normalizeOrgRoleMoney(spend.perTx, "roles.spend.perTx") },
|
|
1250
|
+
...spend.perDay === void 0 ? {} : { perDay: normalizeOrgRoleMoney(spend.perDay, "roles.spend.perDay") },
|
|
1251
|
+
...spend.toRecipients === void 0 ? {} : { toRecipients: spend.toRecipients }
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
function normalizeOrgRoleLabel(label) {
|
|
1255
|
+
const normalized = label.trim().replace(/\s+/g, " ");
|
|
1256
|
+
if (normalized.length === 0) throw Errors.invalidInput("role.label", "must be a non-empty role label");
|
|
1257
|
+
return normalized;
|
|
1258
|
+
}
|
|
1259
|
+
function orgRoleKeyForLabel(label) {
|
|
1260
|
+
return keccak256(toBytes(normalizeOrgRoleLabel(label).toLowerCase()));
|
|
1261
|
+
}
|
|
1262
|
+
function soloOrgRoleTemplate() {
|
|
1263
|
+
return [{
|
|
1264
|
+
label: "Owner",
|
|
1265
|
+
canManageMembers: true,
|
|
1266
|
+
canManageRoles: true
|
|
1267
|
+
}, {
|
|
1268
|
+
label: FOUNDER_BUDGET_ROLE_LABEL,
|
|
1269
|
+
spend: {
|
|
1270
|
+
perTx: FOUNDER_BUDGET_LIMIT,
|
|
1271
|
+
perDay: FOUNDER_BUDGET_LIMIT,
|
|
1272
|
+
toRecipients: "anyone"
|
|
1273
|
+
}
|
|
1274
|
+
}];
|
|
1275
|
+
}
|
|
1276
|
+
function startupOrgRoleTemplate() {
|
|
1277
|
+
return [
|
|
1278
|
+
...soloOrgRoleTemplate(),
|
|
1279
|
+
{
|
|
1280
|
+
label: "Finance Manager",
|
|
1281
|
+
spend: {
|
|
1282
|
+
perTx: usd("25000"),
|
|
1283
|
+
perDay: usd("100000"),
|
|
1284
|
+
toRecipients: "anyone"
|
|
1285
|
+
}
|
|
1286
|
+
},
|
|
1287
|
+
{
|
|
1288
|
+
label: "Team Lead",
|
|
1289
|
+
spend: {
|
|
1290
|
+
perTx: usd("5000"),
|
|
1291
|
+
perDay: usd("15000"),
|
|
1292
|
+
toRecipients: "anyone"
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
];
|
|
1296
|
+
}
|
|
1297
|
+
function orgRoleTemplateDefinitions(template, customRoles = []) {
|
|
1298
|
+
switch (template) {
|
|
1299
|
+
case "Solo": return soloOrgRoleTemplate();
|
|
1300
|
+
case "Startup": return startupOrgRoleTemplate();
|
|
1301
|
+
case "Custom": return customRoles.length === 0 ? soloOrgRoleTemplate() : customRoles;
|
|
1302
|
+
default: return template;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
function compileOrgRoleDefinitions(definitions) {
|
|
1306
|
+
if (definitions.length === 0) throw Errors.invalidInput("roles", "must include at least one role");
|
|
1307
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1308
|
+
const roles = definitions.map((definition) => {
|
|
1309
|
+
const label = normalizeOrgRoleLabel(definition.label);
|
|
1310
|
+
const roleKey = orgRoleKeyForLabel(label);
|
|
1311
|
+
if (seen.has(roleKey)) throw Errors.invalidInput("roles", `duplicate role label: ${label}`);
|
|
1312
|
+
seen.add(roleKey);
|
|
1313
|
+
const spend = normalizeOrgRoleSpendCap(definition.spend);
|
|
1314
|
+
const permissions = [];
|
|
1315
|
+
if (spend !== void 0 || label === OWNER_ROLE_LABEL) permissions.push(EXEC_TRANSACTION_WITH_ROLE);
|
|
1316
|
+
if (definition.canManageMembers === true) permissions.push(ASSIGN_ROLES);
|
|
1317
|
+
if (definition.canManageRoles === true) permissions.push(SCOPE_TARGET);
|
|
1318
|
+
return {
|
|
1319
|
+
label,
|
|
1320
|
+
roleKey,
|
|
1321
|
+
definition: {
|
|
1322
|
+
...definition,
|
|
1323
|
+
label,
|
|
1324
|
+
...spend === void 0 ? {} : { spend }
|
|
1325
|
+
},
|
|
1326
|
+
permissions,
|
|
1327
|
+
allowance: spend ?? null
|
|
1328
|
+
};
|
|
1329
|
+
});
|
|
1330
|
+
const manager = roles.find((role) => role.definition.canManageMembers === true);
|
|
1331
|
+
if (manager === void 0) throw Errors.invalidInput("roles.canManageMembers", "at least one role must compile to the on-chain member-management permission");
|
|
1332
|
+
return {
|
|
1333
|
+
roles,
|
|
1334
|
+
memberManagementRole: {
|
|
1335
|
+
roleKey: manager.roleKey,
|
|
1336
|
+
permission: ASSIGN_ROLES
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
1340
|
padHex(stringToHex("FM_DAILY"), {
|
|
1341
1341
|
size: 32,
|
|
1342
1342
|
dir: "right"
|
|
@@ -1358,97 +1358,35 @@ paymentsV2Signature("sendBatch");
|
|
|
1358
1358
|
paymentsV2Signature("createCommitment");
|
|
1359
1359
|
paymentsV2Signature("cancel");
|
|
1360
1360
|
paymentsV2Signature("redirect");
|
|
1361
|
-
new Map([
|
|
1362
|
-
["assignRoles(address,bytes32[],bool[])", "AssignRoles(address,bytes32[],bool[])"],
|
|
1363
|
-
["allowTarget(bytes32,address,uint8)", "AllowTarget(bytes32,address,uint8)"],
|
|
1364
|
-
["scopeTarget(bytes32,address)", "ScopeTarget(bytes32,address)"],
|
|
1365
|
-
["revokeTarget(bytes32,address)", "RevokeTarget(bytes32,address)"],
|
|
1366
|
-
["allowFunction(bytes32,address,bytes4,uint8)", "AllowFunction(bytes32,address,bytes4,uint8)"],
|
|
1367
|
-
["scopeFunction(bytes32,address,bytes4,(uint8,uint8,uint8,bytes)[],uint8)", "ScopeFunction(bytes32,address,bytes4,(uint8,uint8,uint8,bytes)[],uint8)"],
|
|
1368
|
-
["revokeFunction(bytes32,address,bytes4)", "RevokeFunction(bytes32,address,bytes4)"],
|
|
1369
|
-
["setAllowance(bytes32,uint128,uint128,uint128,uint64,uint64)", "SetAllowance(bytes32,uint128,uint128,uint128,uint64,uint64)"]
|
|
1370
|
-
].map(([functionSignature, eventSignature]) => [toFunctionSelector(functionSignature), toEventSelector(eventSignature)]));
|
|
1371
|
-
//#endregion
|
|
1372
|
-
//#region src/
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
* `at new ClassName (url:line:col)`
|
|
1380
|
-
*/
|
|
1381
|
-
const V8_FRAME_RE = /^\s*at\s+(?:(.+?)\s+\()?(?:(.+?)(?::(\d+):(\d+))?|(.+?))\)?\s*$/;
|
|
1382
|
-
function isNonUrlName(name) {
|
|
1383
|
-
return name === "<anonymous>" || name.startsWith("eval") || name.startsWith("new ") || name.startsWith("async ");
|
|
1361
|
+
new Map([
|
|
1362
|
+
["assignRoles(address,bytes32[],bool[])", "AssignRoles(address,bytes32[],bool[])"],
|
|
1363
|
+
["allowTarget(bytes32,address,uint8)", "AllowTarget(bytes32,address,uint8)"],
|
|
1364
|
+
["scopeTarget(bytes32,address)", "ScopeTarget(bytes32,address)"],
|
|
1365
|
+
["revokeTarget(bytes32,address)", "RevokeTarget(bytes32,address)"],
|
|
1366
|
+
["allowFunction(bytes32,address,bytes4,uint8)", "AllowFunction(bytes32,address,bytes4,uint8)"],
|
|
1367
|
+
["scopeFunction(bytes32,address,bytes4,(uint8,uint8,uint8,bytes)[],uint8)", "ScopeFunction(bytes32,address,bytes4,(uint8,uint8,uint8,bytes)[],uint8)"],
|
|
1368
|
+
["revokeFunction(bytes32,address,bytes4)", "RevokeFunction(bytes32,address,bytes4)"],
|
|
1369
|
+
["setAllowance(bytes32,uint128,uint128,uint128,uint64,uint64)", "SetAllowance(bytes32,uint128,uint128,uint128,uint64,uint64)"]
|
|
1370
|
+
].map(([functionSignature, eventSignature]) => [toFunctionSelector(functionSignature), toEventSelector(eventSignature)]));
|
|
1371
|
+
//#endregion
|
|
1372
|
+
//#region src/surface/_shared/provisioning-telemetry.ts
|
|
1373
|
+
async function emitProvisioningTelemetry(telemetry, smartAccount) {
|
|
1374
|
+
if (telemetry === void 0) return;
|
|
1375
|
+
await Effect.runPromise(telemetry.emit({
|
|
1376
|
+
name: "provisioning_safe_created",
|
|
1377
|
+
props: { safe_address: smartAccount.smartAccountAddress }
|
|
1378
|
+
}).pipe(Effect.catch((cause) => Effect.sync(() => reportProvisioningTelemetryFailure("error", smartAccount, cause))), Effect.catchDefect((cause) => Effect.sync(() => reportProvisioningTelemetryFailure("defect", smartAccount, cause)))));
|
|
1384
1379
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
* - `at async functionName (url:line:col)`
|
|
1393
|
-
* - `at new ClassName (url:line:col)`
|
|
1394
|
-
* - Native frames: `at Array.forEach (<anonymous>)`
|
|
1395
|
-
*/
|
|
1396
|
-
function parseV8StackFrames(error) {
|
|
1397
|
-
const stack = error.stack;
|
|
1398
|
-
if (stack === void 0 || stack === null || stack === "") return [];
|
|
1399
|
-
const lines = stack.split("\n");
|
|
1400
|
-
const frames = [];
|
|
1401
|
-
for (const line of lines) {
|
|
1402
|
-
const trimmed = line.trim();
|
|
1403
|
-
if (!trimmed.startsWith("at ")) continue;
|
|
1404
|
-
const match = V8_FRAME_RE.exec(trimmed);
|
|
1405
|
-
if (match === null) continue;
|
|
1406
|
-
if (match[1] !== void 0) frames.push({
|
|
1407
|
-
function: match[1],
|
|
1408
|
-
filename: match[2],
|
|
1409
|
-
lineno: match[3] !== void 0 ? Number(match[3]) : null,
|
|
1410
|
-
colno: match[4] !== void 0 ? Number(match[4]) : null
|
|
1411
|
-
});
|
|
1412
|
-
else if (match[2] !== void 0 && !isNonUrlName(match[2])) frames.push({
|
|
1413
|
-
function: "<anonymous>",
|
|
1414
|
-
filename: match[2],
|
|
1415
|
-
lineno: match[3] !== void 0 ? Number(match[3]) : null,
|
|
1416
|
-
colno: match[4] !== void 0 ? Number(match[4]) : null
|
|
1417
|
-
});
|
|
1418
|
-
else frames.push({
|
|
1419
|
-
function: match[1] ?? match[2] ?? match[5] ?? "<anonymous>",
|
|
1420
|
-
filename: match[2] ?? match[5] ?? "<anonymous>",
|
|
1421
|
-
lineno: match[3] !== void 0 ? Number(match[3]) : null,
|
|
1422
|
-
colno: match[4] !== void 0 ? Number(match[4]) : null
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
return frames;
|
|
1380
|
+
function reportProvisioningTelemetryFailure(kind, smartAccount, cause) {
|
|
1381
|
+
if (!isProvisioningTelemetryDebugEnabled()) return;
|
|
1382
|
+
globalThis.console?.warn?.("[capxul] provisioning telemetry dropped", {
|
|
1383
|
+
kind,
|
|
1384
|
+
safeAddress: smartAccount.smartAccountAddress,
|
|
1385
|
+
cause
|
|
1386
|
+
});
|
|
1426
1387
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
/**
|
|
1430
|
-
* Build PostHog's `$exception_list` (always a single entry). Error Tracking
|
|
1431
|
-
* groups on `type`, so it is ALWAYS present (the CapxulError code) — the
|
|
1432
|
-
* previous `[{ frames }]` shape omitted it and PostHog dropped the event as
|
|
1433
|
-
* "missing field `type`". When the error has no parseable stack, a synthetic
|
|
1434
|
-
* boundary frame stands in so the event still ingests as a real Issue (#1031).
|
|
1435
|
-
*/
|
|
1436
|
-
function buildExceptionList(input) {
|
|
1437
|
-
const frames = input.frames.length > 0 ? input.frames : [{
|
|
1438
|
-
filename: SDK_BOUNDARY_FILENAME,
|
|
1439
|
-
function: input.operation ?? "unknown",
|
|
1440
|
-
lineno: 1,
|
|
1441
|
-
colno: 1
|
|
1442
|
-
}];
|
|
1443
|
-
return [{
|
|
1444
|
-
type: input.type,
|
|
1445
|
-
value: input.value,
|
|
1446
|
-
mechanism: {
|
|
1447
|
-
handled: true,
|
|
1448
|
-
type: "capxul_sdk_boundary"
|
|
1449
|
-
},
|
|
1450
|
-
stacktrace: { frames }
|
|
1451
|
-
}];
|
|
1388
|
+
function isProvisioningTelemetryDebugEnabled() {
|
|
1389
|
+
return globalThis.process?.env?.CAPXUL_DEBUG_TELEMETRY === "1";
|
|
1452
1390
|
}
|
|
1453
1391
|
//#endregion
|
|
1454
1392
|
//#region src/telemetry/get-failure-mode.ts
|
|
@@ -1498,77 +1436,76 @@ function resolveFailureMode(error, contextFailureMode) {
|
|
|
1498
1436
|
return getFailureMode(error) ?? (isFailureMode(contextFailureMode) ? contextFailureMode : "unknown");
|
|
1499
1437
|
}
|
|
1500
1438
|
//#endregion
|
|
1501
|
-
//#region src/
|
|
1502
|
-
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
const capxulError = isCapxulError(error) ? error : null;
|
|
1519
|
-
const errorCode = capxulError?.code ?? context?.capxul_error_code ?? "UNKNOWN";
|
|
1520
|
-
const props = {
|
|
1521
|
-
capxul_error_code: errorCode,
|
|
1522
|
-
$exception_type: errorCode,
|
|
1523
|
-
$exception_message: EXCEPTION_MESSAGE,
|
|
1524
|
-
$exception_list: buildExceptionList({
|
|
1525
|
-
type: errorCode,
|
|
1526
|
-
value: EXCEPTION_MESSAGE,
|
|
1527
|
-
...context?.operation === void 0 ? {} : { operation: context.operation },
|
|
1528
|
-
frames
|
|
1529
|
-
}),
|
|
1530
|
-
layer: capxulError?.layer ?? context?.layer,
|
|
1531
|
-
operation: context?.operation,
|
|
1532
|
-
provider: context?.provider,
|
|
1533
|
-
failure_mode: resolveFailureMode(error, context?.failure_mode)
|
|
1534
|
-
};
|
|
1535
|
-
if (capxulError?.details !== void 0) props.details = JSON.stringify(capxulError.details);
|
|
1536
|
-
for (const key of Object.keys(props)) if (props[key] === void 0) delete props[key];
|
|
1537
|
-
return telemetry.emit({
|
|
1538
|
-
name: "$exception",
|
|
1539
|
-
props
|
|
1439
|
+
//#region src/signer.ts
|
|
1440
|
+
const EVM_ADDRESS_HEX = /^0x[0-9a-fA-F]{40}$/;
|
|
1441
|
+
const ECDSA_SIGNATURE_HEX = /^0x[0-9a-fA-F]{130}$/;
|
|
1442
|
+
const SAFE_OP_DIGEST_HEX = /^0x[0-9a-fA-F]{64}$/;
|
|
1443
|
+
/** Fold a signer throw into the public error contract. */
|
|
1444
|
+
function signerFailure(source, operation, cause) {
|
|
1445
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1446
|
+
let failureMode;
|
|
1447
|
+
let current = cause;
|
|
1448
|
+
while (typeof current === "object" && current !== null && !seen.has(current)) {
|
|
1449
|
+
seen.add(current);
|
|
1450
|
+
if (current instanceof CapxulError && current.code === "SIGNER_REJECTED") return current;
|
|
1451
|
+
failureMode = getFailureMode(current) ?? failureMode;
|
|
1452
|
+
const error = current;
|
|
1453
|
+
if (error.code === 4001 || error.error === "passkey_user_cancelled") return Errors.signerRejected({
|
|
1454
|
+
source,
|
|
1455
|
+
cause
|
|
1540
1456
|
});
|
|
1541
|
-
|
|
1457
|
+
current = error.cause;
|
|
1458
|
+
}
|
|
1459
|
+
return Errors.providerError("signer", operation, cause, failureMode === void 0 ? void 0 : { failure_mode: failureMode });
|
|
1542
1460
|
}
|
|
1543
1461
|
/**
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
1546
|
-
*
|
|
1462
|
+
* Browser `CapxulSigner` backed by an injected EIP-1193 wallet (MetaMask, etc.).
|
|
1463
|
+
* Signs the SafeOp digest via `eth_sign`, then verifies the returned signature
|
|
1464
|
+
* recovers the selected account against that raw digest. Wallets that prefix
|
|
1465
|
+
* `eth_sign` payloads are rejected before the backend submits an invalid SafeOp.
|
|
1466
|
+
* The node key signer lives in `@capxul/sdk/node` (`localPrivateKeySigner`).
|
|
1547
1467
|
*/
|
|
1548
|
-
function
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1468
|
+
function injectedWalletSigner(provider) {
|
|
1469
|
+
const resolveAddress = async () => {
|
|
1470
|
+
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
1471
|
+
const first = Array.isArray(accounts) ? accounts[0] : void 0;
|
|
1472
|
+
if (typeof first !== "string") throw new Error("injectedWalletSigner: wallet returned no accounts");
|
|
1473
|
+
if (!EVM_ADDRESS_HEX.test(first)) throw new Error("injectedWalletSigner: wallet returned invalid address format");
|
|
1474
|
+
return toAddress(first);
|
|
1475
|
+
};
|
|
1476
|
+
return {
|
|
1477
|
+
source: "injected-eip1193",
|
|
1478
|
+
getAddress: resolveAddress,
|
|
1479
|
+
async signUserOpHash(hash) {
|
|
1480
|
+
if (!SAFE_OP_DIGEST_HEX.test(hash)) throw new Error("injectedWalletSigner: SafeOp digest must be a 0x-prefixed 32-byte hex");
|
|
1481
|
+
const address = await resolveAddress();
|
|
1482
|
+
let signature;
|
|
1483
|
+
try {
|
|
1484
|
+
signature = await provider.request({
|
|
1485
|
+
method: "eth_sign",
|
|
1486
|
+
params: [address, hash]
|
|
1487
|
+
});
|
|
1488
|
+
} catch (cause) {
|
|
1489
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
1490
|
+
throw new Error(`injectedWalletSigner: eth_sign failed; enable raw-hash signing for deployment (${detail})`, { cause });
|
|
1491
|
+
}
|
|
1492
|
+
if (typeof signature !== "string") throw new Error("injectedWalletSigner: wallet returned a non-string signature");
|
|
1493
|
+
if (!ECDSA_SIGNATURE_HEX.test(signature)) throw new Error("injectedWalletSigner: wallet returned invalid signature format");
|
|
1494
|
+
if ((await recoverRawDigestSigner({
|
|
1495
|
+
hash,
|
|
1496
|
+
signature
|
|
1497
|
+
})).toLowerCase() !== address.toLowerCase()) throw new Error("injectedWalletSigner: wallet signature did not recover the selected account for the raw SafeOp digest; use a raw-hash-capable wallet or @capxul/sdk/node localPrivateKeySigner for deployed flows");
|
|
1498
|
+
return signature;
|
|
1499
|
+
}
|
|
1500
|
+
};
|
|
1569
1501
|
}
|
|
1570
|
-
function
|
|
1571
|
-
|
|
1502
|
+
async function recoverRawDigestSigner(input) {
|
|
1503
|
+
try {
|
|
1504
|
+
return toAddress(await recoverAddress(input));
|
|
1505
|
+
} catch (cause) {
|
|
1506
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
1507
|
+
throw new Error(`injectedWalletSigner: could not verify raw SafeOp digest signature (${detail})`, { cause });
|
|
1508
|
+
}
|
|
1572
1509
|
}
|
|
1573
1510
|
//#endregion
|
|
1574
1511
|
//#region src/internal/invocation-observation.ts
|
|
@@ -2137,7 +2074,7 @@ const accountStatusProgram = Effect.gen(function* () {
|
|
|
2137
2074
|
};
|
|
2138
2075
|
const signerAddress = yield* Effect.tryPromise({
|
|
2139
2076
|
try: () => signer.getAddress(),
|
|
2140
|
-
catch: (cause) =>
|
|
2077
|
+
catch: (cause) => signerFailure(signer.source, "getAddress", cause)
|
|
2141
2078
|
});
|
|
2142
2079
|
return {
|
|
2143
2080
|
status: "accountProviderReady",
|
|
@@ -2532,11 +2469,12 @@ const EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
|
2532
2469
|
* envelopes carrying it — so it MUST stay byte-identical across both. Exported
|
|
2533
2470
|
* once here to remove the drift risk of a mirrored declaration.
|
|
2534
2471
|
*/
|
|
2535
|
-
const PAYMENT_DOCUMENT_VERIFYING_CONTRACT = "
|
|
2472
|
+
const PAYMENT_DOCUMENT_VERIFYING_CONTRACT = "0xA3ACDD016f706eD432A9a0545C45F0943f996b60";
|
|
2536
2473
|
const PAYMENT_ID_RE = /^payment_[0-9A-Za-z]+$/;
|
|
2537
2474
|
const PAYEE_ID_RE = /^payee_[0-9A-Za-z]+$/;
|
|
2538
2475
|
const ORG_ID_RE = /^org_[0-9A-Za-z]+$/;
|
|
2539
2476
|
const USER_ID_RE = /^user_[0-9A-Za-z]+$/;
|
|
2477
|
+
const PARTY_ID_RE = /^party_[0-9A-Za-z]+$/;
|
|
2540
2478
|
const HANDLE_RE = /^@?[a-z0-9][a-z0-9-]{2,31}$/;
|
|
2541
2479
|
const ORG_HANDLE_RE = /^[a-z0-9][a-z0-9-]{2,31}$/;
|
|
2542
2480
|
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -2545,6 +2483,7 @@ const PaymentIdSchema$1 = Schema.String.pipe(Schema.check(Schema.makeFilter((val
|
|
|
2545
2483
|
const PayeeIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => PAYEE_ID_RE.test(value), { message: "must be payee_ plus an alphanumeric id" })));
|
|
2546
2484
|
const OrgIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => ORG_ID_RE.test(value), { message: "must be org_ plus an alphanumeric id" })));
|
|
2547
2485
|
const UserIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => USER_ID_RE.test(value), { message: "must be user_ plus an alphanumeric id" })));
|
|
2486
|
+
const PartyIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => PARTY_ID_RE.test(value), { message: "must be party_ plus an alphanumeric id" })));
|
|
2548
2487
|
const DecimalStringSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => DECIMAL_STRING_RE.test(value), { message: "must be a non-negative decimal string" })));
|
|
2549
2488
|
const HandleValueSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => !EVM_ADDRESS_RE.test(value) && HANDLE_RE.test(value), { message: "must be a handle; raw addresses are not accepted" })));
|
|
2550
2489
|
const OrgHandleValueSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => !EVM_ADDRESS_RE.test(value) && ORG_HANDLE_RE.test(value), { message: "must be an org handle; raw addresses are not accepted" })));
|
|
@@ -2691,6 +2630,7 @@ const PaymentRecipient = Schema.Struct({
|
|
|
2691
2630
|
"capxulUserId",
|
|
2692
2631
|
"me",
|
|
2693
2632
|
"org",
|
|
2633
|
+
"party",
|
|
2694
2634
|
"external_address"
|
|
2695
2635
|
]),
|
|
2696
2636
|
label: Schema.String,
|
|
@@ -2737,6 +2677,10 @@ const PaymentRef = Schema.Union([
|
|
|
2737
2677
|
Schema.Struct({
|
|
2738
2678
|
kind: Schema.Literal("payeeId"),
|
|
2739
2679
|
payeeId: PayeeIdSchema
|
|
2680
|
+
}),
|
|
2681
|
+
Schema.Struct({
|
|
2682
|
+
kind: Schema.Literal("party"),
|
|
2683
|
+
partyId: PartyIdSchema
|
|
2740
2684
|
})
|
|
2741
2685
|
]);
|
|
2742
2686
|
const Payment = Schema.Struct({
|
|
@@ -4013,55 +3957,42 @@ function makeActorRelationshipMethods(deps) {
|
|
|
4013
3957
|
const fns = actorScopeContract;
|
|
4014
3958
|
return {
|
|
4015
3959
|
addressBook: {
|
|
4016
|
-
list: (options) => mapOk$1(awaitableConvex(options?.signal, "addressBook.list", () => convexCall.query(fns.addressBookList, {
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
},
|
|
3960
|
+
list: (input, options) => mapOk$1("addressBook.list", awaitableConvex(options?.signal, "addressBook.list", () => convexCall.query(fns.addressBookList, {
|
|
3961
|
+
actor,
|
|
3962
|
+
...input?.includeHidden === void 0 ? {} : { includeHidden: input.includeHidden }
|
|
3963
|
+
})), (entries) => entries.map(mapAddressBookEntry)),
|
|
3964
|
+
get: (entryId, options) => mapOk$1("addressBook.get", awaitableConvex(options?.signal, "addressBook.get", () => convexCall.query(fns.addressBookGet, {
|
|
3965
|
+
actor,
|
|
3966
|
+
partyId: entryId
|
|
3967
|
+
})), (entry) => entry === null ? null : mapAddressBookEntry(entry)),
|
|
4025
3968
|
add: async (input, options) => {
|
|
4026
3969
|
const ref = normalizeRefForBackend$1(input.ref, "ref");
|
|
4027
3970
|
if (!ref.ok) return ref;
|
|
4028
|
-
return mapOk$1(await awaitableConvex(options?.signal, "addressBook.add", () => convexCall.mutation(fns.addressBookAdd, {
|
|
3971
|
+
return mapOk$1("addressBook.add", await awaitableConvex(options?.signal, "addressBook.add", () => convexCall.mutation(fns.addressBookAdd, {
|
|
4029
3972
|
actor,
|
|
4030
3973
|
ref: ref.value,
|
|
4031
3974
|
...input.label === void 0 ? {} : { label: input.label }
|
|
4032
3975
|
})), mapAddressBookEntry);
|
|
4033
3976
|
},
|
|
4034
|
-
hide:
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
},
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
ref: ref.value
|
|
4048
|
-
})), mapAddressBookEntry);
|
|
4049
|
-
},
|
|
4050
|
-
label: async (input, options) => {
|
|
4051
|
-
const ref = refFromEntryId(input.entryId);
|
|
4052
|
-
if (!ref.ok) return ref;
|
|
4053
|
-
return mapOk$1(await awaitableConvex(options?.signal, "addressBook.label", () => convexCall.mutation(fns.addressBookLabel, {
|
|
4054
|
-
actor,
|
|
4055
|
-
ref: ref.value,
|
|
4056
|
-
label: input.label
|
|
4057
|
-
})), mapAddressBookEntry);
|
|
4058
|
-
}
|
|
3977
|
+
hide: (entryId, options) => mapOk$1("addressBook.hide", awaitableConvex(options?.signal, "addressBook.hide", () => convexCall.mutation(fns.addressBookHide, {
|
|
3978
|
+
actor,
|
|
3979
|
+
partyId: entryId
|
|
3980
|
+
})), mapAddressBookEntry),
|
|
3981
|
+
unhide: (entryId, options) => mapOk$1("addressBook.unhide", awaitableConvex(options?.signal, "addressBook.unhide", () => convexCall.mutation(fns.addressBookUnhide, {
|
|
3982
|
+
actor,
|
|
3983
|
+
partyId: entryId
|
|
3984
|
+
})), mapAddressBookEntry),
|
|
3985
|
+
label: (input, options) => mapOk$1("addressBook.label", awaitableConvex(options?.signal, "addressBook.label", () => convexCall.mutation(fns.addressBookLabel, {
|
|
3986
|
+
actor,
|
|
3987
|
+
partyId: input.entryId,
|
|
3988
|
+
label: input.label
|
|
3989
|
+
})), mapAddressBookEntry)
|
|
4059
3990
|
},
|
|
4060
3991
|
requests: {
|
|
4061
3992
|
issue: async (input, options) => {
|
|
4062
3993
|
const payer = normalizeRefForBackend$1(input.payer, "payer");
|
|
4063
3994
|
if (!payer.ok) return payer;
|
|
4064
|
-
return mapOk$1(await awaitableConvex(options?.signal, "requests.issue", () => convexCall.mutation(fns.requestsIssue, {
|
|
3995
|
+
return mapOk$1("requests.issue", await awaitableConvex(options?.signal, "requests.issue", () => convexCall.mutation(fns.requestsIssue, {
|
|
4065
3996
|
actor,
|
|
4066
3997
|
payer: payer.value,
|
|
4067
3998
|
amount: input.amount,
|
|
@@ -4070,18 +4001,18 @@ function makeActorRelationshipMethods(deps) {
|
|
|
4070
4001
|
...input.expiresAt === void 0 ? {} : { expiresAt: input.expiresAt }
|
|
4071
4002
|
})), (request) => mapActorRequest(request, input.payer));
|
|
4072
4003
|
},
|
|
4073
|
-
list: (options) => mapOk$1(awaitableConvex(options?.signal, "requests.list", () => convexCall.query(fns.requestsList, { actor })), (requests) => requests.map((request) => mapActorRequest(request))),
|
|
4074
|
-
get: (requestId, options) => mapOk$1(awaitableConvex(options?.signal, "requests.get", () => convexCall.query(fns.requestsGet, {
|
|
4004
|
+
list: (options) => mapOk$1("requests.list", awaitableConvex(options?.signal, "requests.list", () => convexCall.query(fns.requestsList, { actor })), (requests) => requests.map((request) => mapActorRequest(request))),
|
|
4005
|
+
get: (requestId, options) => mapOk$1("requests.get", awaitableConvex(options?.signal, "requests.get", () => convexCall.query(fns.requestsGet, {
|
|
4075
4006
|
actor,
|
|
4076
4007
|
paymentRequestId: requestId
|
|
4077
4008
|
})), (request) => request === null ? null : mapActorRequest(request)),
|
|
4078
|
-
cancel: (requestId, options) => mapOk$1(awaitableConvex(options?.signal, "requests.cancel", () => convexCall.mutation(fns.requestsCancel, {
|
|
4009
|
+
cancel: (requestId, options) => mapOk$1("requests.cancel", awaitableConvex(options?.signal, "requests.cancel", () => convexCall.mutation(fns.requestsCancel, {
|
|
4079
4010
|
actor,
|
|
4080
4011
|
paymentRequestId: requestId
|
|
4081
4012
|
})), (request) => mapActorRequest(request))
|
|
4082
4013
|
},
|
|
4083
4014
|
inbox: {
|
|
4084
|
-
list: (options) => mapOk$1(awaitableConvex(options?.signal, "inbox.list", () => convexCall.query(fns.inboxList, { actor })), (items) => items.map(mapInboxItem)),
|
|
4015
|
+
list: (options) => mapOk$1("inbox.list", awaitableConvex(options?.signal, "inbox.list", () => convexCall.query(fns.inboxList, { actor })), (items) => items.map(mapInboxItem)),
|
|
4085
4016
|
approve: async (input, options) => {
|
|
4086
4017
|
const result = await awaitableConvex(options?.signal, "inbox.approve", () => convexCall.mutation(fns.inboxApprove, {
|
|
4087
4018
|
actor,
|
|
@@ -4092,7 +4023,7 @@ function makeActorRelationshipMethods(deps) {
|
|
|
4092
4023
|
if (!result.ok) return result;
|
|
4093
4024
|
return mapApprovedInboxPayment(result.value, input);
|
|
4094
4025
|
},
|
|
4095
|
-
decline: (requestId, options) => mapOk$1(awaitableConvex(options?.signal, "inbox.decline", () => convexCall.mutation(fns.inboxDecline, {
|
|
4026
|
+
decline: (requestId, options) => mapOk$1("inbox.decline", awaitableConvex(options?.signal, "inbox.decline", () => convexCall.mutation(fns.inboxDecline, {
|
|
4096
4027
|
actor,
|
|
4097
4028
|
paymentRequestId: requestId
|
|
4098
4029
|
})), mapInboxItem)
|
|
@@ -4160,30 +4091,52 @@ function missingConvexCall(operation) {
|
|
|
4160
4091
|
error: Errors.providerError("convex", operation, "ConvexCallPort is required")
|
|
4161
4092
|
});
|
|
4162
4093
|
}
|
|
4163
|
-
|
|
4094
|
+
/**
|
|
4095
|
+
* Project a successful backend reply, WITHOUT leaving the result boundary.
|
|
4096
|
+
*
|
|
4097
|
+
* The projection can refuse: `mapAddressBookEntry` proves the entry id is a
|
|
4098
|
+
* `PartyId` rather than trusting the wire, and `toPartyId` throws on a
|
|
4099
|
+
* malformed one. Every verb on this surface returns `CapxulResult`, so that
|
|
4100
|
+
* throw has to become a value here — otherwise a malformed reply rejects the
|
|
4101
|
+
* promise and the caller's `if (!result.ok)` never runs (ADR-0023: errors are
|
|
4102
|
+
* values, and a code crosses the seam).
|
|
4103
|
+
*/
|
|
4104
|
+
async function mapOk$1(operation, resultOrPromise, f) {
|
|
4164
4105
|
const result = await resultOrPromise;
|
|
4165
4106
|
if (!result.ok) return result;
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4107
|
+
try {
|
|
4108
|
+
return {
|
|
4109
|
+
ok: true,
|
|
4110
|
+
value: f(result.value)
|
|
4111
|
+
};
|
|
4112
|
+
} catch (cause) {
|
|
4113
|
+
return {
|
|
4114
|
+
ok: false,
|
|
4115
|
+
error: cause instanceof CapxulError ? cause : Errors.providerError("convex", operation, cause)
|
|
4116
|
+
};
|
|
4117
|
+
}
|
|
4170
4118
|
}
|
|
4171
4119
|
const awaitableConvex = runIfActive;
|
|
4120
|
+
const ADDRESS_BOOK_RELATIONSHIPS = [
|
|
4121
|
+
"paid",
|
|
4122
|
+
"paidBy",
|
|
4123
|
+
"invoiced",
|
|
4124
|
+
"invoicedBy",
|
|
4125
|
+
"member",
|
|
4126
|
+
"manual",
|
|
4127
|
+
"employed"
|
|
4128
|
+
];
|
|
4129
|
+
function isAddressBookRelationship(value) {
|
|
4130
|
+
return ADDRESS_BOOK_RELATIONSHIPS.includes(value);
|
|
4131
|
+
}
|
|
4172
4132
|
function mapAddressBookEntry(entry) {
|
|
4173
|
-
const relationship = /* @__PURE__ */ new Set();
|
|
4174
|
-
for (const edge of entry.edges) {
|
|
4175
|
-
if (edge === "paid") relationship.add("paid");
|
|
4176
|
-
if (edge === "paidBy") relationship.add("paidBy");
|
|
4177
|
-
if (edge === "requested" || edge === "requestedBy") relationship.add("requested");
|
|
4178
|
-
if (edge === "member") relationship.add("member");
|
|
4179
|
-
if (edge === "employee") relationship.add("employee");
|
|
4180
|
-
}
|
|
4181
4133
|
return {
|
|
4182
|
-
id: entry.id,
|
|
4134
|
+
id: toPartyId(entry.id),
|
|
4183
4135
|
ref: entry.ref,
|
|
4184
|
-
label: entry.label
|
|
4185
|
-
relationship:
|
|
4186
|
-
hidden: entry.hidden
|
|
4136
|
+
label: entry.label,
|
|
4137
|
+
relationship: entry.relationship.filter(isAddressBookRelationship),
|
|
4138
|
+
hidden: entry.hidden,
|
|
4139
|
+
lastActivityAt: entry.lastActivityAt
|
|
4187
4140
|
};
|
|
4188
4141
|
}
|
|
4189
4142
|
function mapActorRequest(request, payer) {
|
|
@@ -4277,8 +4230,14 @@ function mapInboxStatus(status) {
|
|
|
4277
4230
|
}
|
|
4278
4231
|
function normalizeRefForBackend$1(ref, field) {
|
|
4279
4232
|
try {
|
|
4280
|
-
if (typeof ref === "string")
|
|
4281
|
-
|
|
4233
|
+
if (typeof ref === "string") return {
|
|
4234
|
+
ok: false,
|
|
4235
|
+
error: Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
4236
|
+
};
|
|
4237
|
+
if (typeof ref !== "object" || ref === null || !("kind" in ref)) return {
|
|
4238
|
+
ok: false,
|
|
4239
|
+
error: Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
4240
|
+
};
|
|
4282
4241
|
switch (ref.kind) {
|
|
4283
4242
|
case "handle": return {
|
|
4284
4243
|
ok: true,
|
|
@@ -4315,55 +4274,22 @@ function normalizeRefForBackend$1(ref, field) {
|
|
|
4315
4274
|
payeeId: nonEmptyRefValue$1(ref.payeeId, "payeeId")
|
|
4316
4275
|
}
|
|
4317
4276
|
};
|
|
4318
|
-
|
|
4277
|
+
case "party": return {
|
|
4278
|
+
ok: true,
|
|
4279
|
+
value: {
|
|
4280
|
+
kind: "party",
|
|
4281
|
+
partyId: toPartyId(ref.partyId)
|
|
4282
|
+
}
|
|
4283
|
+
};
|
|
4284
|
+
default: return {
|
|
4285
|
+
ok: false,
|
|
4286
|
+
error: Errors.invalidInput(field, "recipient must be a known Ref variant")
|
|
4287
|
+
};
|
|
4319
4288
|
}
|
|
4320
4289
|
} catch (cause) {
|
|
4321
|
-
if (cause instanceof Error && "code" in cause) return {
|
|
4322
|
-
ok: false,
|
|
4323
|
-
error: cause
|
|
4324
|
-
};
|
|
4325
4290
|
return {
|
|
4326
4291
|
ok: false,
|
|
4327
|
-
error: Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
4328
|
-
};
|
|
4329
|
-
}
|
|
4330
|
-
}
|
|
4331
|
-
function refFromEntryId(entryId) {
|
|
4332
|
-
try {
|
|
4333
|
-
const parsed = JSON.parse(entryId);
|
|
4334
|
-
if (typeof parsed === "object" && parsed !== null && "kind" in parsed) return normalizeRefForBackend$1(parsed, "entryId");
|
|
4335
|
-
} catch {}
|
|
4336
|
-
const separator = entryId.indexOf(":");
|
|
4337
|
-
if (separator === -1) return {
|
|
4338
|
-
ok: false,
|
|
4339
|
-
error: Errors.invalidInput("entryId", "must be an address-book entry id")
|
|
4340
|
-
};
|
|
4341
|
-
const prefix = entryId.slice(0, separator);
|
|
4342
|
-
const value = entryId.slice(separator + 1);
|
|
4343
|
-
switch (prefix) {
|
|
4344
|
-
case "email": return normalizeRefForBackend$1({
|
|
4345
|
-
kind: "email",
|
|
4346
|
-
email: value
|
|
4347
|
-
}, "entryId");
|
|
4348
|
-
case "user": return normalizeRefForBackend$1({
|
|
4349
|
-
kind: "capxulUserId",
|
|
4350
|
-
capxulUserId: value
|
|
4351
|
-
}, "entryId");
|
|
4352
|
-
case "org": return normalizeRefForBackend$1({
|
|
4353
|
-
kind: "orgHandle",
|
|
4354
|
-
orgHandle: value
|
|
4355
|
-
}, "entryId");
|
|
4356
|
-
case "payee": return normalizeRefForBackend$1({
|
|
4357
|
-
kind: "payeeId",
|
|
4358
|
-
payeeId: value
|
|
4359
|
-
}, "entryId");
|
|
4360
|
-
case "handle": return normalizeRefForBackend$1({
|
|
4361
|
-
kind: "handle",
|
|
4362
|
-
handle: value
|
|
4363
|
-
}, "entryId");
|
|
4364
|
-
default: return {
|
|
4365
|
-
ok: false,
|
|
4366
|
-
error: Errors.invalidInput("entryId", "must be an address-book entry id")
|
|
4292
|
+
error: cause instanceof CapxulError ? cause : Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
4367
4293
|
};
|
|
4368
4294
|
}
|
|
4369
4295
|
}
|
|
@@ -4377,15 +4303,6 @@ function handleRefValue$1(value, field) {
|
|
|
4377
4303
|
const trimmed = nonEmptyRefValue$1(value, field);
|
|
4378
4304
|
return trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
|
|
4379
4305
|
}
|
|
4380
|
-
function refLabel(ref) {
|
|
4381
|
-
switch (ref.kind) {
|
|
4382
|
-
case "handle": return ref.handle;
|
|
4383
|
-
case "email": return ref.email;
|
|
4384
|
-
case "orgHandle": return ref.orgHandle;
|
|
4385
|
-
case "capxulUserId": return ref.capxulUserId;
|
|
4386
|
-
case "payeeId": return ref.payeeId;
|
|
4387
|
-
}
|
|
4388
|
-
}
|
|
4389
4306
|
//#endregion
|
|
4390
4307
|
//#region src/surface/account.ts
|
|
4391
4308
|
const provisioningPhase = (state) => {
|
|
@@ -4408,6 +4325,10 @@ const actorFailure = (failure) => new CapxulError(failure.reason === "WORK_DIED"
|
|
|
4408
4325
|
...failure.details === void 0 ? {} : { details: failure.details },
|
|
4409
4326
|
layer: "identity"
|
|
4410
4327
|
});
|
|
4328
|
+
const accountFailureResult = (error) => ({
|
|
4329
|
+
ok: false,
|
|
4330
|
+
error
|
|
4331
|
+
});
|
|
4411
4332
|
function makeAccountMethods(deps) {
|
|
4412
4333
|
toChainId(deps.chainId);
|
|
4413
4334
|
const requirement = deps.requirement;
|
|
@@ -4550,26 +4471,16 @@ function makeAccountMethods(deps) {
|
|
|
4550
4471
|
value: provisioningPhase(deps.actor.snapshot())
|
|
4551
4472
|
};
|
|
4552
4473
|
};
|
|
4553
|
-
const reportAndReturn = (error, operation = "getLifecycle") => {
|
|
4554
|
-
if (deps.telemetry) captureExceptionSync(deps.telemetry, error, {
|
|
4555
|
-
layer: "account",
|
|
4556
|
-
operation
|
|
4557
|
-
});
|
|
4558
|
-
return {
|
|
4559
|
-
ok: false,
|
|
4560
|
-
error
|
|
4561
|
-
};
|
|
4562
|
-
};
|
|
4563
4474
|
const resolveLifecycle = async () => {
|
|
4564
4475
|
const phase = provisioningPhase(deps.actor.snapshot());
|
|
4565
4476
|
const status = await getStatus();
|
|
4566
|
-
if (!status.ok) return
|
|
4477
|
+
if (!status.ok) return accountFailureResult(status.error);
|
|
4567
4478
|
let accountId;
|
|
4568
4479
|
if (status.value.status !== "notAuthenticated" && (phase.status === "ready" || isRequirementMet(status.value, requirement))) {
|
|
4569
4480
|
const accountReadPort = deps.accountReadPort;
|
|
4570
|
-
if (accountReadPort === void 0) return
|
|
4481
|
+
if (accountReadPort === void 0) return accountFailureResult(Errors.invalidInput("account", "accountReadPort is required to resolve ready lifecycle"));
|
|
4571
4482
|
const account = await runPortEffect(accountReadPort.readBalance({ chainId: toChainId(deps.chainId) }));
|
|
4572
|
-
if (!account.ok) return
|
|
4483
|
+
if (!account.ok) return accountFailureResult(account.error);
|
|
4573
4484
|
accountId = String(account.value.id);
|
|
4574
4485
|
}
|
|
4575
4486
|
return {
|
|
@@ -4588,10 +4499,10 @@ function makeAccountMethods(deps) {
|
|
|
4588
4499
|
if (typeof resetSession === "function") try {
|
|
4589
4500
|
resetSession.call(deps.signer);
|
|
4590
4501
|
} catch (cause) {
|
|
4591
|
-
return
|
|
4502
|
+
return accountFailureResult(signerFailure(deps.signer.source, "resetSession", cause));
|
|
4592
4503
|
}
|
|
4593
4504
|
const retried = await drive({ _tag: "RetryAccount" });
|
|
4594
|
-
if (!retried.ok) return
|
|
4505
|
+
if (!retried.ok) return accountFailureResult(retried.error);
|
|
4595
4506
|
return resolveLifecycle();
|
|
4596
4507
|
};
|
|
4597
4508
|
return {
|
|
@@ -4744,7 +4655,7 @@ function cancelled(operation) {
|
|
|
4744
4655
|
function isAborted$2(signal) {
|
|
4745
4656
|
return signal?.aborted === true;
|
|
4746
4657
|
}
|
|
4747
|
-
async function signerCall(operation, run) {
|
|
4658
|
+
async function signerCall(source, operation, run) {
|
|
4748
4659
|
try {
|
|
4749
4660
|
return {
|
|
4750
4661
|
ok: true,
|
|
@@ -4753,7 +4664,7 @@ async function signerCall(operation, run) {
|
|
|
4753
4664
|
} catch (cause) {
|
|
4754
4665
|
return {
|
|
4755
4666
|
ok: false,
|
|
4756
|
-
error:
|
|
4667
|
+
error: signerFailure(source, operation, cause)
|
|
4757
4668
|
};
|
|
4758
4669
|
}
|
|
4759
4670
|
}
|
|
@@ -4765,7 +4676,7 @@ async function executePersonalPayment(deps, payment, signal, requestKey) {
|
|
|
4765
4676
|
ok: false,
|
|
4766
4677
|
error: Errors.notAuthenticated()
|
|
4767
4678
|
};
|
|
4768
|
-
const signerAddress = await signerCall("getAddress", () => deps.signer.getAddress());
|
|
4679
|
+
const signerAddress = await signerCall(deps.signer.source, "getAddress", () => deps.signer.getAddress());
|
|
4769
4680
|
if (!signerAddress.ok) return signerAddress;
|
|
4770
4681
|
const expectedSafe = deriveCapxulSafeAddress({ email: session.email });
|
|
4771
4682
|
const resolvedRequestKey = requestKey ?? `pay_${crypto.randomUUID()}`;
|
|
@@ -4784,7 +4695,7 @@ async function executePersonalPayment(deps, payment, signal, requestKey) {
|
|
|
4784
4695
|
paymentId: prepared.value.paymentId
|
|
4785
4696
|
});
|
|
4786
4697
|
if (isAborted$2(signal)) return cancelled("payments.pay");
|
|
4787
|
-
const signature = await signerCall("signUserOpHash", () => deps.signer.signUserOpHash(prepared.value.digest));
|
|
4698
|
+
const signature = await signerCall(deps.signer.source, "signUserOpHash", () => deps.signer.signUserOpHash(prepared.value.digest));
|
|
4788
4699
|
if (!signature.ok) return signature;
|
|
4789
4700
|
if (isAborted$2(signal)) return cancelled("payments.pay");
|
|
4790
4701
|
return runIfActive(void 0, "payments.submitExecution", () => deps.convexCall.action(deps.functions.submitPaymentExecution, { input: {
|
|
@@ -4797,11 +4708,11 @@ async function executePersonalPayment(deps, payment, signal, requestKey) {
|
|
|
4797
4708
|
function isAborted$1(signal) {
|
|
4798
4709
|
return signal?.aborted === true;
|
|
4799
4710
|
}
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4711
|
+
/** Return one stable fingerprint for one JSON payment intent. */
|
|
4712
|
+
async function fingerprintPaymentIntent(intent) {
|
|
4713
|
+
const canonical = JSON.stringify(intent, (_key, value) => value !== null && typeof value === "object" && !Array.isArray(value) ? Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right))) : value);
|
|
4714
|
+
if (canonical === void 0) throw new TypeError("Payment intent must be JSON data");
|
|
4715
|
+
return keccak256(toBytes(canonical));
|
|
4805
4716
|
}
|
|
4806
4717
|
async function executePrepared(deps, prepare, expectedRequest, signal) {
|
|
4807
4718
|
if (isAborted$1(signal)) return {
|
|
@@ -4817,11 +4728,14 @@ async function executePrepared(deps, prepare, expectedRequest, signal) {
|
|
|
4817
4728
|
try {
|
|
4818
4729
|
signerAddress = await deps.signer.getAddress();
|
|
4819
4730
|
} catch (cause) {
|
|
4820
|
-
return
|
|
4731
|
+
return {
|
|
4732
|
+
ok: false,
|
|
4733
|
+
error: signerFailure(deps.signer.source, "getAddress", cause)
|
|
4734
|
+
};
|
|
4821
4735
|
}
|
|
4822
4736
|
const prepared = await prepare(signerAddress);
|
|
4823
4737
|
if (!prepared.ok) return prepared;
|
|
4824
|
-
if (
|
|
4738
|
+
if (await fingerprintPaymentIntent(prepared.value.request) !== await fingerprintPaymentIntent(expectedRequest)) return {
|
|
4825
4739
|
ok: false,
|
|
4826
4740
|
error: Errors.invalidInput("payment", "prepared command mismatch")
|
|
4827
4741
|
};
|
|
@@ -4838,7 +4752,10 @@ async function executePrepared(deps, prepare, expectedRequest, signal) {
|
|
|
4838
4752
|
try {
|
|
4839
4753
|
signature = await deps.signer.signUserOpHash(prepared.value.digest);
|
|
4840
4754
|
} catch (cause) {
|
|
4841
|
-
return
|
|
4755
|
+
return {
|
|
4756
|
+
ok: false,
|
|
4757
|
+
error: signerFailure(deps.signer.source, "signUserOpHash", cause)
|
|
4758
|
+
};
|
|
4842
4759
|
}
|
|
4843
4760
|
if (isAborted$1(signal)) return {
|
|
4844
4761
|
ok: false,
|
|
@@ -4937,36 +4854,36 @@ async function paymentRequestKeyLifecycle(operation, intent, provided) {
|
|
|
4937
4854
|
key: provided,
|
|
4938
4855
|
finish: async () => void 0
|
|
4939
4856
|
};
|
|
4940
|
-
const slot = `capxul.payment.request-key.v3:${await fingerprintPaymentIntent({
|
|
4941
|
-
operation,
|
|
4942
|
-
intent
|
|
4943
|
-
})}`;
|
|
4944
|
-
if (typeof window === "undefined") {
|
|
4945
|
-
const attemptId = randomPaymentRequestKey();
|
|
4946
|
-
const state = memoryPaymentRequestKeys.get(slot) ?? {
|
|
4947
|
-
key: randomPaymentRequestKey(),
|
|
4948
|
-
active: [],
|
|
4949
|
-
resolved: false
|
|
4950
|
-
};
|
|
4951
|
-
state.active.push(attemptId);
|
|
4952
|
-
memoryPaymentRequestKeys.set(slot, state);
|
|
4953
|
-
let finished = false;
|
|
4954
|
-
return {
|
|
4955
|
-
key: state.key,
|
|
4956
|
-
finish: async (succeeded) => {
|
|
4957
|
-
if (finished) return;
|
|
4958
|
-
finished = true;
|
|
4959
|
-
const attemptIndex = state.active.indexOf(attemptId);
|
|
4960
|
-
if (attemptIndex < 0) return;
|
|
4961
|
-
state.active.splice(attemptIndex, 1);
|
|
4962
|
-
state.resolved = succeeded;
|
|
4963
|
-
if (state.active.length === 0 && state.resolved) memoryPaymentRequestKeys.delete(slot);
|
|
4964
|
-
}
|
|
4965
|
-
};
|
|
4966
|
-
}
|
|
4967
4857
|
let releaseAttemptLock;
|
|
4968
4858
|
let forgetPagehideRelease;
|
|
4969
4859
|
try {
|
|
4860
|
+
const slot = `capxul.payment.request-key.v3:${await fingerprintPaymentIntent({
|
|
4861
|
+
operation,
|
|
4862
|
+
intent
|
|
4863
|
+
})}`;
|
|
4864
|
+
if (typeof window === "undefined") {
|
|
4865
|
+
const attemptId = randomPaymentRequestKey();
|
|
4866
|
+
const state = memoryPaymentRequestKeys.get(slot) ?? {
|
|
4867
|
+
key: randomPaymentRequestKey(),
|
|
4868
|
+
active: [],
|
|
4869
|
+
resolved: false
|
|
4870
|
+
};
|
|
4871
|
+
state.active.push(attemptId);
|
|
4872
|
+
memoryPaymentRequestKeys.set(slot, state);
|
|
4873
|
+
let finished = false;
|
|
4874
|
+
return {
|
|
4875
|
+
key: state.key,
|
|
4876
|
+
finish: async (succeeded) => {
|
|
4877
|
+
if (finished) return;
|
|
4878
|
+
finished = true;
|
|
4879
|
+
const attemptIndex = state.active.indexOf(attemptId);
|
|
4880
|
+
if (attemptIndex < 0) return;
|
|
4881
|
+
state.active.splice(attemptIndex, 1);
|
|
4882
|
+
state.resolved = succeeded;
|
|
4883
|
+
if (state.active.length === 0 && state.resolved) memoryPaymentRequestKeys.delete(slot);
|
|
4884
|
+
}
|
|
4885
|
+
};
|
|
4886
|
+
}
|
|
4970
4887
|
const attemptId = randomPaymentRequestKey();
|
|
4971
4888
|
releaseAttemptLock = await holdPaymentAttemptLock(paymentAttemptLockName(slot, attemptId));
|
|
4972
4889
|
forgetPagehideRelease = releasePaymentAttemptOnPagehide(releaseAttemptLock);
|
|
@@ -5021,13 +4938,20 @@ async function paymentRequestKeyLifecycle(operation, intent, provided) {
|
|
|
5021
4938
|
throw Errors.providerError("sdk", "paymentRequestKey", cause);
|
|
5022
4939
|
}
|
|
5023
4940
|
}
|
|
4941
|
+
function paymentSubmissionFailure(cause) {
|
|
4942
|
+
return {
|
|
4943
|
+
ok: false,
|
|
4944
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
4945
|
+
};
|
|
4946
|
+
}
|
|
5024
4947
|
async function waitForPaymentSubmission(submission, signal, operation, onCancel = () => false) {
|
|
5025
|
-
|
|
5026
|
-
if (signal
|
|
4948
|
+
const foldedSubmission = submission.catch((cause) => paymentSubmissionFailure(cause));
|
|
4949
|
+
if (signal === void 0) return foldedSubmission;
|
|
4950
|
+
if (signal.aborted) return onCancel() ? foldedSubmission : {
|
|
5027
4951
|
ok: false,
|
|
5028
4952
|
error: Errors.cancelled({ operation })
|
|
5029
4953
|
};
|
|
5030
|
-
return new Promise((resolve
|
|
4954
|
+
return new Promise((resolve) => {
|
|
5031
4955
|
const onAbort = () => {
|
|
5032
4956
|
signal.removeEventListener("abort", onAbort);
|
|
5033
4957
|
if (!onCancel()) resolve({
|
|
@@ -5036,21 +4960,12 @@ async function waitForPaymentSubmission(submission, signal, operation, onCancel
|
|
|
5036
4960
|
});
|
|
5037
4961
|
};
|
|
5038
4962
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5039
|
-
|
|
4963
|
+
foldedSubmission.then((result) => {
|
|
5040
4964
|
signal.removeEventListener("abort", onAbort);
|
|
5041
4965
|
resolve(result);
|
|
5042
|
-
}, (cause) => {
|
|
5043
|
-
signal.removeEventListener("abort", onAbort);
|
|
5044
|
-
reject(cause instanceof Error ? cause : new Error(String(cause)));
|
|
5045
4966
|
});
|
|
5046
4967
|
});
|
|
5047
4968
|
}
|
|
5048
|
-
/** Return one stable fingerprint for one JSON payment intent. */
|
|
5049
|
-
async function fingerprintPaymentIntent(intent) {
|
|
5050
|
-
const canonical = JSON.stringify(intent, (_key, value) => value !== null && typeof value === "object" && !Array.isArray(value) ? Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right))) : value);
|
|
5051
|
-
if (canonical === void 0) throw new TypeError("Payment intent must be JSON data");
|
|
5052
|
-
return keccak256(toBytes(canonical));
|
|
5053
|
-
}
|
|
5054
4969
|
function paymentExecutionIntent(input) {
|
|
5055
4970
|
if (actorReferenceToBackend(input.actor)?.kind === "org") return {
|
|
5056
4971
|
ok: false,
|
|
@@ -5092,7 +5007,7 @@ function makeFinancialOpsMethods(deps) {
|
|
|
5092
5007
|
} catch (cause) {
|
|
5093
5008
|
return {
|
|
5094
5009
|
ok: false,
|
|
5095
|
-
error: cause instanceof CapxulError ? cause : Errors.
|
|
5010
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
5096
5011
|
};
|
|
5097
5012
|
}
|
|
5098
5013
|
const sharedKey = `${requestKeyScope}:${requestKey.key}`;
|
|
@@ -5140,7 +5055,10 @@ function makeFinancialOpsMethods(deps) {
|
|
|
5140
5055
|
try {
|
|
5141
5056
|
await requestKey.finish(false);
|
|
5142
5057
|
} catch {}
|
|
5143
|
-
|
|
5058
|
+
return {
|
|
5059
|
+
ok: false,
|
|
5060
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
5061
|
+
};
|
|
5144
5062
|
}
|
|
5145
5063
|
release(false);
|
|
5146
5064
|
try {
|
|
@@ -5164,11 +5082,25 @@ function makeFinancialOpsMethods(deps) {
|
|
|
5164
5082
|
const runLifecycle = async (intent, signal) => {
|
|
5165
5083
|
const execution = lifecycleDependencies();
|
|
5166
5084
|
if (!execution.ok) return execution;
|
|
5167
|
-
|
|
5168
|
-
const
|
|
5169
|
-
if (
|
|
5170
|
-
|
|
5171
|
-
|
|
5085
|
+
try {
|
|
5086
|
+
const submitted = await executePaymentLifecycle(execution.value, intent, signal);
|
|
5087
|
+
if (!submitted.ok) return submitted;
|
|
5088
|
+
const payments = submitted.value.payments;
|
|
5089
|
+
const payment = payments[0];
|
|
5090
|
+
if (payment === void 0 || payments.length !== 1) return {
|
|
5091
|
+
ok: false,
|
|
5092
|
+
error: Errors.unknown()
|
|
5093
|
+
};
|
|
5094
|
+
return {
|
|
5095
|
+
ok: true,
|
|
5096
|
+
value: normalizePaymentTiming(payment)
|
|
5097
|
+
};
|
|
5098
|
+
} catch (cause) {
|
|
5099
|
+
return {
|
|
5100
|
+
ok: false,
|
|
5101
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
5102
|
+
};
|
|
5103
|
+
}
|
|
5172
5104
|
};
|
|
5173
5105
|
return {
|
|
5174
5106
|
me: {
|
|
@@ -5219,9 +5151,10 @@ function makeFinancialOpsMethods(deps) {
|
|
|
5219
5151
|
value: resolvedTargetFromPayee(reference, payee.value)
|
|
5220
5152
|
};
|
|
5221
5153
|
}
|
|
5154
|
+
case "party":
|
|
5222
5155
|
case "destination": return Promise.resolve({
|
|
5223
5156
|
ok: false,
|
|
5224
|
-
error: Errors.notImplemented("targets",
|
|
5157
|
+
error: Errors.notImplemented("targets", `resolve.${reference.kind}`)
|
|
5225
5158
|
});
|
|
5226
5159
|
}
|
|
5227
5160
|
} },
|
|
@@ -5355,8 +5288,14 @@ function handleRefValue(value, field) {
|
|
|
5355
5288
|
}
|
|
5356
5289
|
function refFromTargetReference(reference, field) {
|
|
5357
5290
|
try {
|
|
5358
|
-
if (typeof reference === "string")
|
|
5359
|
-
|
|
5291
|
+
if (typeof reference === "string") return {
|
|
5292
|
+
ok: false,
|
|
5293
|
+
error: Errors.invalidInput(field, "target must be a typed TargetReference variant")
|
|
5294
|
+
};
|
|
5295
|
+
if (typeof reference !== "object" || reference === null || !("kind" in reference)) return {
|
|
5296
|
+
ok: false,
|
|
5297
|
+
error: Errors.invalidInput(field, "target must be a typed TargetReference variant")
|
|
5298
|
+
};
|
|
5360
5299
|
switch (reference.kind) {
|
|
5361
5300
|
case "handle": return {
|
|
5362
5301
|
ok: true,
|
|
@@ -5386,20 +5325,26 @@ function refFromTargetReference(reference, field) {
|
|
|
5386
5325
|
payeeId: reference.id
|
|
5387
5326
|
}
|
|
5388
5327
|
};
|
|
5328
|
+
case "party": return {
|
|
5329
|
+
ok: true,
|
|
5330
|
+
value: {
|
|
5331
|
+
kind: "party",
|
|
5332
|
+
partyId: reference.partyId
|
|
5333
|
+
}
|
|
5334
|
+
};
|
|
5389
5335
|
case "destination": return {
|
|
5390
5336
|
ok: false,
|
|
5391
5337
|
error: Errors.notImplemented("targets", "reference.destination")
|
|
5392
5338
|
};
|
|
5393
|
-
default:
|
|
5339
|
+
default: return {
|
|
5340
|
+
ok: false,
|
|
5341
|
+
error: Errors.invalidInput(field, "target must be a known TargetReference variant")
|
|
5342
|
+
};
|
|
5394
5343
|
}
|
|
5395
5344
|
} catch (cause) {
|
|
5396
|
-
if (cause instanceof Error && "code" in cause) return {
|
|
5397
|
-
ok: false,
|
|
5398
|
-
error: cause
|
|
5399
|
-
};
|
|
5400
5345
|
return {
|
|
5401
5346
|
ok: false,
|
|
5402
|
-
error: Errors.invalidInput(field, "target must be a typed TargetReference variant")
|
|
5347
|
+
error: cause instanceof CapxulError ? cause : Errors.invalidInput(field, "target must be a typed TargetReference variant")
|
|
5403
5348
|
};
|
|
5404
5349
|
}
|
|
5405
5350
|
}
|
|
@@ -5453,6 +5398,10 @@ function targetReferenceFromBackendRef(ref) {
|
|
|
5453
5398
|
kind: "payee",
|
|
5454
5399
|
id: ref.payeeId
|
|
5455
5400
|
};
|
|
5401
|
+
case "party": return {
|
|
5402
|
+
kind: "party",
|
|
5403
|
+
partyId: ref.partyId
|
|
5404
|
+
};
|
|
5456
5405
|
case "capxulUserId": throw Errors.notImplemented("targets", "reference.capxulUserId");
|
|
5457
5406
|
}
|
|
5458
5407
|
}
|
|
@@ -5539,8 +5488,14 @@ function normalizeDestinationRefForBackend(ref, field) {
|
|
|
5539
5488
|
}
|
|
5540
5489
|
function normalizeRefForBackend(ref, field) {
|
|
5541
5490
|
try {
|
|
5542
|
-
if (typeof ref === "string")
|
|
5543
|
-
|
|
5491
|
+
if (typeof ref === "string") return {
|
|
5492
|
+
ok: false,
|
|
5493
|
+
error: Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
5494
|
+
};
|
|
5495
|
+
if (typeof ref !== "object" || ref === null || !("kind" in ref)) return {
|
|
5496
|
+
ok: false,
|
|
5497
|
+
error: Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
5498
|
+
};
|
|
5544
5499
|
switch (ref.kind) {
|
|
5545
5500
|
case "handle": return {
|
|
5546
5501
|
ok: true,
|
|
@@ -5577,16 +5532,22 @@ function normalizeRefForBackend(ref, field) {
|
|
|
5577
5532
|
payeeId: nonEmptyRefValue(ref.payeeId, "payeeId")
|
|
5578
5533
|
}
|
|
5579
5534
|
};
|
|
5580
|
-
|
|
5535
|
+
case "party": return {
|
|
5536
|
+
ok: true,
|
|
5537
|
+
value: {
|
|
5538
|
+
kind: "party",
|
|
5539
|
+
partyId: toPartyId(ref.partyId)
|
|
5540
|
+
}
|
|
5541
|
+
};
|
|
5542
|
+
default: return {
|
|
5543
|
+
ok: false,
|
|
5544
|
+
error: Errors.invalidInput(field, "recipient must be a known Ref variant")
|
|
5545
|
+
};
|
|
5581
5546
|
}
|
|
5582
5547
|
} catch (cause) {
|
|
5583
|
-
if (cause instanceof Error && "code" in cause) return {
|
|
5584
|
-
ok: false,
|
|
5585
|
-
error: cause
|
|
5586
|
-
};
|
|
5587
5548
|
return {
|
|
5588
5549
|
ok: false,
|
|
5589
|
-
error: Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
5550
|
+
error: cause instanceof CapxulError ? cause : Errors.invalidInput(field, "recipient must be a typed Ref variant")
|
|
5590
5551
|
};
|
|
5591
5552
|
}
|
|
5592
5553
|
}
|
|
@@ -5605,16 +5566,15 @@ function mapOk(result, f) {
|
|
|
5605
5566
|
value: f(result.value)
|
|
5606
5567
|
};
|
|
5607
5568
|
} catch (cause) {
|
|
5608
|
-
|
|
5569
|
+
return {
|
|
5609
5570
|
ok: false,
|
|
5610
|
-
error: cause
|
|
5571
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
5611
5572
|
};
|
|
5612
|
-
throw cause;
|
|
5613
5573
|
}
|
|
5614
5574
|
}
|
|
5615
5575
|
//#endregion
|
|
5616
5576
|
//#region package.json
|
|
5617
|
-
var version = "2.
|
|
5577
|
+
var version = "2.2.0";
|
|
5618
5578
|
//#endregion
|
|
5619
5579
|
//#region src/ports/auth-client.ts
|
|
5620
5580
|
var AuthClientError = class extends Data.TaggedError("AuthClientError") {};
|
|
@@ -6625,7 +6585,7 @@ const modelSession = (session) => ({
|
|
|
6625
6585
|
});
|
|
6626
6586
|
const claimAccount = (input, authUserId, signer) => call("smart-account.claim", Effect.tryPromise({
|
|
6627
6587
|
try: () => signer.getAddress(),
|
|
6628
|
-
catch: (cause) =>
|
|
6588
|
+
catch: (cause) => signerFailure(signer.source, "getAddress", cause)
|
|
6629
6589
|
}).pipe(Effect.flatMap((signerAddress) => input.ports.smartAccount.claim({
|
|
6630
6590
|
authUserId: toAuthUserId(authUserId),
|
|
6631
6591
|
chainId: toChainId(input.chainId),
|
|
@@ -7560,12 +7520,6 @@ const permissionContract = { read: makeFunctionReference(CAPXUL_FUNCTIONS["permi
|
|
|
7560
7520
|
function isAborted(signal) {
|
|
7561
7521
|
return signal?.aborted === true;
|
|
7562
7522
|
}
|
|
7563
|
-
function fail$1(cause, operation) {
|
|
7564
|
-
return {
|
|
7565
|
-
ok: false,
|
|
7566
|
-
error: cause instanceof CapxulError ? cause : Errors.providerError("wallet-signer", operation, cause)
|
|
7567
|
-
};
|
|
7568
|
-
}
|
|
7569
7523
|
async function execute(deps, orgId, command, signal) {
|
|
7570
7524
|
if (isAborted(signal)) return {
|
|
7571
7525
|
ok: false,
|
|
@@ -7584,7 +7538,10 @@ async function execute(deps, orgId, command, signal) {
|
|
|
7584
7538
|
try {
|
|
7585
7539
|
signerAddress = await deps.signer.getAddress();
|
|
7586
7540
|
} catch (cause) {
|
|
7587
|
-
return
|
|
7541
|
+
return {
|
|
7542
|
+
ok: false,
|
|
7543
|
+
error: signerFailure(deps.signer.source, "getAddress", cause)
|
|
7544
|
+
};
|
|
7588
7545
|
}
|
|
7589
7546
|
const executionFns = deps.executionFunctions ?? moneyExecutionContract;
|
|
7590
7547
|
const prepared = await runIfActive(signal, "permissions.prepareExecution", () => deps.convexCall.action(executionFns.preparePermissionExecution, { input: {
|
|
@@ -7606,7 +7563,10 @@ async function execute(deps, orgId, command, signal) {
|
|
|
7606
7563
|
try {
|
|
7607
7564
|
signature = await deps.signer.signUserOpHash(prepared.value.digest);
|
|
7608
7565
|
} catch (cause) {
|
|
7609
|
-
return
|
|
7566
|
+
return {
|
|
7567
|
+
ok: false,
|
|
7568
|
+
error: signerFailure(deps.signer.source, "signUserOpHash", cause)
|
|
7569
|
+
};
|
|
7610
7570
|
}
|
|
7611
7571
|
if (isAborted(signal)) return {
|
|
7612
7572
|
ok: false,
|
|
@@ -7684,7 +7644,7 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
|
|
|
7684
7644
|
} catch (cause) {
|
|
7685
7645
|
return {
|
|
7686
7646
|
ok: false,
|
|
7687
|
-
error: cause instanceof CapxulError ? cause : Errors.
|
|
7647
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
7688
7648
|
};
|
|
7689
7649
|
}
|
|
7690
7650
|
const flightKey = `${requestKeyScope}:${operation}:${requestKey.key}`;
|
|
@@ -7731,16 +7691,16 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
|
|
|
7731
7691
|
try {
|
|
7732
7692
|
await requestKey.finish(false);
|
|
7733
7693
|
} catch {}
|
|
7734
|
-
|
|
7694
|
+
return {
|
|
7695
|
+
ok: false,
|
|
7696
|
+
error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
|
|
7697
|
+
};
|
|
7735
7698
|
}
|
|
7736
7699
|
release(false);
|
|
7737
7700
|
try {
|
|
7738
7701
|
await requestKey.finish(result.ok);
|
|
7739
7702
|
} catch {}
|
|
7740
|
-
return result.
|
|
7741
|
-
ok: true,
|
|
7742
|
-
value: result.value.payments.map((payment) => normalizePaymentTiming(payment))
|
|
7743
|
-
} : result;
|
|
7703
|
+
return mapOk(result, (value) => value.payments.map((payment) => normalizePaymentTiming(payment)));
|
|
7744
7704
|
};
|
|
7745
7705
|
return {
|
|
7746
7706
|
pay: async (input, options) => {
|
|
@@ -8383,6 +8343,142 @@ function detectAuthCacheAdapter() {
|
|
|
8383
8343
|
return new InMemoryAuthCacheAdapter();
|
|
8384
8344
|
}
|
|
8385
8345
|
//#endregion
|
|
8346
|
+
//#region src/telemetry/stack-frame-parser.ts
|
|
8347
|
+
/**
|
|
8348
|
+
* Regex for V8/Chrome stack trace frame lines.
|
|
8349
|
+
* Matches:
|
|
8350
|
+
* `at functionName (url:line:col)`
|
|
8351
|
+
* `at url:line:col`
|
|
8352
|
+
* `at async functionName (url:line:col)`
|
|
8353
|
+
* `at new ClassName (url:line:col)`
|
|
8354
|
+
*/
|
|
8355
|
+
const V8_FRAME_RE = /^\s*at\s+(?:(.+?)\s+\()?(?:(.+?)(?::(\d+):(\d+))?|(.+?))\)?\s*$/;
|
|
8356
|
+
function isNonUrlName(name) {
|
|
8357
|
+
return name === "<anonymous>" || name.startsWith("eval") || name.startsWith("new ") || name.startsWith("async ");
|
|
8358
|
+
}
|
|
8359
|
+
/**
|
|
8360
|
+
* Parse a V8/Chrome-style stack trace string into PostHog `ExceptionFrame` objects.
|
|
8361
|
+
* Returns an empty array when `error.stack` is absent or empty.
|
|
8362
|
+
*
|
|
8363
|
+
* Handles:
|
|
8364
|
+
* - Standard `at functionName (url:line:col)`
|
|
8365
|
+
* - Bare `at url:line:col` (no function name)
|
|
8366
|
+
* - `at async functionName (url:line:col)`
|
|
8367
|
+
* - `at new ClassName (url:line:col)`
|
|
8368
|
+
* - Native frames: `at Array.forEach (<anonymous>)`
|
|
8369
|
+
*/
|
|
8370
|
+
function parseV8StackFrames(error) {
|
|
8371
|
+
const stack = error.stack;
|
|
8372
|
+
if (stack === void 0 || stack === null || stack === "") return [];
|
|
8373
|
+
const lines = stack.split("\n");
|
|
8374
|
+
const frames = [];
|
|
8375
|
+
for (const line of lines) {
|
|
8376
|
+
const trimmed = line.trim();
|
|
8377
|
+
if (!trimmed.startsWith("at ")) continue;
|
|
8378
|
+
const match = V8_FRAME_RE.exec(trimmed);
|
|
8379
|
+
if (match === null) continue;
|
|
8380
|
+
if (match[1] !== void 0) frames.push({
|
|
8381
|
+
function: match[1],
|
|
8382
|
+
filename: match[2],
|
|
8383
|
+
lineno: match[3] !== void 0 ? Number(match[3]) : null,
|
|
8384
|
+
colno: match[4] !== void 0 ? Number(match[4]) : null
|
|
8385
|
+
});
|
|
8386
|
+
else if (match[2] !== void 0 && !isNonUrlName(match[2])) frames.push({
|
|
8387
|
+
function: "<anonymous>",
|
|
8388
|
+
filename: match[2],
|
|
8389
|
+
lineno: match[3] !== void 0 ? Number(match[3]) : null,
|
|
8390
|
+
colno: match[4] !== void 0 ? Number(match[4]) : null
|
|
8391
|
+
});
|
|
8392
|
+
else frames.push({
|
|
8393
|
+
function: match[1] ?? match[2] ?? match[5] ?? "<anonymous>",
|
|
8394
|
+
filename: match[2] ?? match[5] ?? "<anonymous>",
|
|
8395
|
+
lineno: match[3] !== void 0 ? Number(match[3]) : null,
|
|
8396
|
+
colno: match[4] !== void 0 ? Number(match[4]) : null
|
|
8397
|
+
});
|
|
8398
|
+
}
|
|
8399
|
+
return frames;
|
|
8400
|
+
}
|
|
8401
|
+
/** Fixed, leak-safe frame used when the error carries no parseable stack. */
|
|
8402
|
+
const SDK_BOUNDARY_FILENAME = "capxul-sdk-observation://boundary";
|
|
8403
|
+
/**
|
|
8404
|
+
* Build PostHog's `$exception_list` (always a single entry). Error Tracking
|
|
8405
|
+
* groups on `type`, so it is ALWAYS present (the CapxulError code) — the
|
|
8406
|
+
* previous `[{ frames }]` shape omitted it and PostHog dropped the event as
|
|
8407
|
+
* "missing field `type`". When the error has no parseable stack, a synthetic
|
|
8408
|
+
* boundary frame stands in so the event still ingests as a real Issue (#1031).
|
|
8409
|
+
*/
|
|
8410
|
+
function buildExceptionList(input) {
|
|
8411
|
+
const frames = input.frames.length > 0 ? input.frames : [{
|
|
8412
|
+
filename: SDK_BOUNDARY_FILENAME,
|
|
8413
|
+
function: input.operation ?? "unknown",
|
|
8414
|
+
lineno: 1,
|
|
8415
|
+
colno: 1
|
|
8416
|
+
}];
|
|
8417
|
+
return [{
|
|
8418
|
+
type: input.type,
|
|
8419
|
+
value: input.value,
|
|
8420
|
+
mechanism: {
|
|
8421
|
+
handled: true,
|
|
8422
|
+
type: "capxul_sdk_boundary"
|
|
8423
|
+
},
|
|
8424
|
+
stacktrace: { frames }
|
|
8425
|
+
}];
|
|
8426
|
+
}
|
|
8427
|
+
//#endregion
|
|
8428
|
+
//#region src/telemetry/capture-exception.ts
|
|
8429
|
+
/** Fixed, leak-safe message — the raw error message may carry PII and never ships. */
|
|
8430
|
+
const EXCEPTION_MESSAGE = "Capxul SDK operation failed";
|
|
8431
|
+
/**
|
|
8432
|
+
* Capture an error as a `$exception` event through the telemetry port,
|
|
8433
|
+
* formatted for PostHog Error Tracking.
|
|
8434
|
+
*
|
|
8435
|
+
* Parses stack traces into `$exception_list` format, extracts structured
|
|
8436
|
+
* metadata from CapxulError objects, and supplements with context props.
|
|
8437
|
+
* Fire-and-forget: telemetry defects are silently swallowed.
|
|
8438
|
+
* Returns `Effect<void, never>` for use in Effect pipelines; the underlying
|
|
8439
|
+
* adapter work is synchronous, so callers outside Effect contexts can
|
|
8440
|
+
* use `Effect.runSync`.
|
|
8441
|
+
*/
|
|
8442
|
+
function captureException(telemetry, error, context) {
|
|
8443
|
+
return Effect.catchDefect(Effect.sync(() => {
|
|
8444
|
+
const frames = error instanceof Error ? parseV8StackFrames(error) : [];
|
|
8445
|
+
const capxulError = isCapxulError(error) ? error : null;
|
|
8446
|
+
const errorCode = capxulError?.code ?? context?.capxul_error_code ?? "UNKNOWN";
|
|
8447
|
+
const props = {
|
|
8448
|
+
capxul_error_code: errorCode,
|
|
8449
|
+
$exception_type: errorCode,
|
|
8450
|
+
$exception_message: EXCEPTION_MESSAGE,
|
|
8451
|
+
$exception_list: buildExceptionList({
|
|
8452
|
+
type: errorCode,
|
|
8453
|
+
value: EXCEPTION_MESSAGE,
|
|
8454
|
+
...context?.operation === void 0 ? {} : { operation: context.operation },
|
|
8455
|
+
frames
|
|
8456
|
+
}),
|
|
8457
|
+
layer: capxulError?.layer ?? context?.layer,
|
|
8458
|
+
operation: context?.operation,
|
|
8459
|
+
provider: context?.provider,
|
|
8460
|
+
failure_mode: resolveFailureMode(error, context?.failure_mode)
|
|
8461
|
+
};
|
|
8462
|
+
if (capxulError?.details !== void 0) props.details = JSON.stringify(capxulError.details);
|
|
8463
|
+
for (const key of Object.keys(props)) if (props[key] === void 0) delete props[key];
|
|
8464
|
+
return telemetry.emit({
|
|
8465
|
+
name: "$exception",
|
|
8466
|
+
props
|
|
8467
|
+
});
|
|
8468
|
+
}).pipe(Effect.flatten), () => Effect.void);
|
|
8469
|
+
}
|
|
8470
|
+
/**
|
|
8471
|
+
* Synchronous fire-and-forget capture. Runs the Effect inline with
|
|
8472
|
+
* `Effect.runSync` so callers outside an Effect context can report errors
|
|
8473
|
+
* without awaiting. Core SDK public methods use the assembled observation
|
|
8474
|
+
* boundary instead.
|
|
8475
|
+
*/
|
|
8476
|
+
function captureExceptionSync(telemetry, error, context) {
|
|
8477
|
+
try {
|
|
8478
|
+
Effect.runSync(captureException(telemetry, error, context));
|
|
8479
|
+
} catch {}
|
|
8480
|
+
}
|
|
8481
|
+
//#endregion
|
|
8386
8482
|
//#region src/observation.ts
|
|
8387
8483
|
const SDK_VERSION = version;
|
|
8388
8484
|
/** Stable PostHog event used for typed failures that are expected product outcomes. */
|
|
@@ -8431,16 +8527,98 @@ function postHogFailureObservation(policy, fixedSnapshot) {
|
|
|
8431
8527
|
function classifyOperationOutcome(kind) {
|
|
8432
8528
|
return EXPECTED_OPERATION_OUTCOMES.has(kind) ? "expected" : "unexpected";
|
|
8433
8529
|
}
|
|
8530
|
+
/** @internal Observe public result methods at the assembled Core SDK boundary. */
|
|
8531
|
+
function observeSdkClient(client, adapter, snapshot) {
|
|
8532
|
+
if (adapter === void 0) return client;
|
|
8533
|
+
const objectProxies = /* @__PURE__ */ new WeakMap();
|
|
8534
|
+
const proxyTargets = /* @__PURE__ */ new WeakMap();
|
|
8535
|
+
const functionWrappers = /* @__PURE__ */ new WeakMap();
|
|
8536
|
+
const wrapObject = (target, path, internal = false) => {
|
|
8537
|
+
const cacheKey = `${internal ? "internal" : "public"}:${path.join(".")}`;
|
|
8538
|
+
let targetProxies = objectProxies.get(target);
|
|
8539
|
+
const cached = targetProxies?.get(cacheKey);
|
|
8540
|
+
if (cached !== void 0) return cached;
|
|
8541
|
+
const proxy = new Proxy(target, { get(currentTarget, property, receiver) {
|
|
8542
|
+
const value = Reflect.get(currentTarget, property, receiver);
|
|
8543
|
+
if (typeof property !== "string") return value;
|
|
8544
|
+
if (path.length === 0 && property === "_internal" && isPlainObject(value)) return wrapObject(value, ["_internal"], true);
|
|
8545
|
+
if (internal && property !== "accounts") return value;
|
|
8546
|
+
return wrapValue(value, [...path, property], currentTarget);
|
|
8547
|
+
} });
|
|
8548
|
+
proxyTargets.set(proxy, target);
|
|
8549
|
+
if (targetProxies === void 0) {
|
|
8550
|
+
targetProxies = /* @__PURE__ */ new Map();
|
|
8551
|
+
objectProxies.set(target, targetProxies);
|
|
8552
|
+
}
|
|
8553
|
+
targetProxies.set(cacheKey, proxy);
|
|
8554
|
+
return proxy;
|
|
8555
|
+
};
|
|
8556
|
+
const wrapValue = (value, path, owner) => {
|
|
8557
|
+
if (typeof value === "function") {
|
|
8558
|
+
const callable = value;
|
|
8559
|
+
const operation = path.join(".");
|
|
8560
|
+
let ownerWrappers = functionWrappers.get(owner);
|
|
8561
|
+
if (ownerWrappers === void 0) {
|
|
8562
|
+
ownerWrappers = /* @__PURE__ */ new Map();
|
|
8563
|
+
functionWrappers.set(owner, ownerWrappers);
|
|
8564
|
+
}
|
|
8565
|
+
const cached = ownerWrappers.get(operation);
|
|
8566
|
+
if (cached !== void 0) return cached;
|
|
8567
|
+
let wrapped;
|
|
8568
|
+
wrapped = new Proxy(callable, {
|
|
8569
|
+
apply(currentTarget, thisArg, args) {
|
|
8570
|
+
const invocation = resolveInvocationSnapshot(adapter, snapshot);
|
|
8571
|
+
let output;
|
|
8572
|
+
try {
|
|
8573
|
+
output = Reflect.apply(currentTarget, unwrapReceiver(thisArg), args);
|
|
8574
|
+
} catch (cause) {
|
|
8575
|
+
report(adapter, "exception", operation, cause, invocation);
|
|
8576
|
+
throw cause;
|
|
8577
|
+
}
|
|
8578
|
+
if (isPromiseLike(output)) return Promise.resolve(output).then((result) => processOutput(result, path, invocation), (cause) => {
|
|
8579
|
+
report(adapter, "exception", operation, cause, invocation);
|
|
8580
|
+
throw cause;
|
|
8581
|
+
});
|
|
8582
|
+
return processOutput(output, path, invocation);
|
|
8583
|
+
},
|
|
8584
|
+
get(currentTarget, property) {
|
|
8585
|
+
if (property === "bind") return Function.prototype.bind.bind(wrapped);
|
|
8586
|
+
if (property === "call") return Function.prototype.call.bind(wrapped);
|
|
8587
|
+
if (property === "apply") return Function.prototype.apply.bind(wrapped);
|
|
8588
|
+
const attached = Reflect.get(currentTarget, property, currentTarget);
|
|
8589
|
+
if (typeof property !== "string") return attached;
|
|
8590
|
+
return wrapValue(attached, [...path, property], currentTarget);
|
|
8591
|
+
}
|
|
8592
|
+
});
|
|
8593
|
+
proxyTargets.set(wrapped, callable);
|
|
8594
|
+
ownerWrappers.set(operation, wrapped);
|
|
8595
|
+
return wrapped;
|
|
8596
|
+
}
|
|
8597
|
+
return isPlainObject(value) ? wrapObject(value, path) : value;
|
|
8598
|
+
};
|
|
8599
|
+
const processOutput = (output, path, invocation) => {
|
|
8600
|
+
if (isFailedResult(output)) {
|
|
8601
|
+
report(adapter, "operation", path.join("."), output.error, invocation);
|
|
8602
|
+
return output;
|
|
8603
|
+
}
|
|
8604
|
+
if (isCapxulResult(output)) return output;
|
|
8605
|
+
return isPlainObject(output) ? wrapObject(output, path) : output;
|
|
8606
|
+
};
|
|
8607
|
+
return wrapObject(client, []);
|
|
8608
|
+
function unwrapReceiver(receiver) {
|
|
8609
|
+
return (typeof receiver === "object" || typeof receiver === "function") && receiver !== null ? proxyTargets.get(receiver) ?? receiver : receiver;
|
|
8610
|
+
}
|
|
8611
|
+
}
|
|
8434
8612
|
/** @internal Reports a factory-level typed failure without changing its identity. */
|
|
8435
8613
|
function observeFailedResult(result, adapter, operation) {
|
|
8436
|
-
if (adapter !== void 0 && isFailedResult(result)) report(adapter, "operation", operation, result.error,
|
|
8614
|
+
if (adapter !== void 0 && isFailedResult(result)) report(adapter, "operation", operation, result.error, resolveAdapterSnapshot(adapter));
|
|
8437
8615
|
return result;
|
|
8438
8616
|
}
|
|
8439
|
-
function report(adapter, kind, operation, cause,
|
|
8617
|
+
function report(adapter, kind, operation, cause, invocation) {
|
|
8440
8618
|
const operationName = normalizeOperation(operation);
|
|
8441
8619
|
const kindName = normalizeErrorKind(errorKind(cause));
|
|
8442
8620
|
const context = sanitizeObservationContext({
|
|
8443
|
-
...
|
|
8621
|
+
...invocation.context,
|
|
8444
8622
|
...isCapxulError(cause) && cause.correlationId !== void 0 ? { correlationId: cause.correlationId } : {}
|
|
8445
8623
|
});
|
|
8446
8624
|
const failure = markFailureInvocationSnapshot({
|
|
@@ -8450,13 +8628,27 @@ function report(adapter, kind, operation, cause, invocationContext) {
|
|
|
8450
8628
|
errorKind: kindName,
|
|
8451
8629
|
...context === void 0 ? {} : { context }
|
|
8452
8630
|
}, {
|
|
8453
|
-
active:
|
|
8631
|
+
active: invocation.active,
|
|
8454
8632
|
...context === void 0 ? {} : { context }
|
|
8455
8633
|
});
|
|
8456
8634
|
try {
|
|
8457
8635
|
ignoreDeliveryFailure(kind === "operation" ? adapter.captureOperationFailure(failure) : adapter.captureException(failure));
|
|
8458
8636
|
} catch {}
|
|
8459
8637
|
}
|
|
8638
|
+
function resolveInvocationSnapshot(adapter, snapshot) {
|
|
8639
|
+
if (snapshot !== void 0) try {
|
|
8640
|
+
const captured = snapshot();
|
|
8641
|
+
if (captured !== void 0) return captured;
|
|
8642
|
+
} catch {}
|
|
8643
|
+
return resolveAdapterSnapshot(adapter);
|
|
8644
|
+
}
|
|
8645
|
+
function resolveAdapterSnapshot(adapter) {
|
|
8646
|
+
const context = resolveAdapterContext(adapter);
|
|
8647
|
+
return context === void 0 ? { active: false } : {
|
|
8648
|
+
active: true,
|
|
8649
|
+
context
|
|
8650
|
+
};
|
|
8651
|
+
}
|
|
8460
8652
|
function resolveAdapterContext(adapter) {
|
|
8461
8653
|
try {
|
|
8462
8654
|
return adapter.resolveContext?.();
|
|
@@ -8747,6 +8939,7 @@ function executeIdentityProductObservation(telemetry, record, state) {
|
|
|
8747
8939
|
//#endregion
|
|
8748
8940
|
//#region src/surface/create-capxul-client.ts
|
|
8749
8941
|
function assembleCapxulClient(input) {
|
|
8942
|
+
const observation = input;
|
|
8750
8943
|
const authCache = input.authCache ?? detectAuthCacheAdapter();
|
|
8751
8944
|
const effectRunner = input.effectRunner ?? {
|
|
8752
8945
|
runSync: Effect.runSync,
|
|
@@ -8760,7 +8953,7 @@ function assembleCapxulClient(input) {
|
|
|
8760
8953
|
...input.signer === void 0 ? {} : { signer: input.signer },
|
|
8761
8954
|
...input.organizationSetup === void 0 ? {} : { organizationSetup: input.organizationSetup },
|
|
8762
8955
|
...input.otpTtlMs === void 0 ? {} : { otpTtlMs: input.otpTtlMs }
|
|
8763
|
-
}), scope)),
|
|
8956
|
+
}), scope)), observation.hostObservationSnapshot);
|
|
8764
8957
|
const unsubscribeProductTelemetry = actor.subscribeTransitions((record) => {
|
|
8765
8958
|
effectRunner.runPromise(executeIdentityProductObservation(input.ports.telemetry, record, actor.snapshot())).catch(() => {});
|
|
8766
8959
|
});
|
|
@@ -8809,7 +9002,11 @@ function assembleCapxulClient(input) {
|
|
|
8809
9002
|
...input.invokeTimeoutMs === void 0 ? {} : { invokeTimeoutMs: input.invokeTimeoutMs },
|
|
8810
9003
|
afterVerifyOtp: async () => {
|
|
8811
9004
|
const browserSigner = input.signer;
|
|
8812
|
-
if (browserSigner !== void 0 && "resetSession" in browserSigner && typeof browserSigner.resetSession === "function")
|
|
9005
|
+
if (browserSigner !== void 0 && "resetSession" in browserSigner && typeof browserSigner.resetSession === "function") try {
|
|
9006
|
+
browserSigner.resetSession();
|
|
9007
|
+
} catch (cause) {
|
|
9008
|
+
throw signerFailure(browserSigner.source, "resetSession", cause);
|
|
9009
|
+
}
|
|
8813
9010
|
await detectPendingOrgInvitations?.();
|
|
8814
9011
|
kickProvisioning?.();
|
|
8815
9012
|
}
|
|
@@ -8915,7 +9112,7 @@ function assembleCapxulClient(input) {
|
|
|
8915
9112
|
};
|
|
8916
9113
|
}
|
|
8917
9114
|
};
|
|
8918
|
-
return {
|
|
9115
|
+
return observeSdkClient({
|
|
8919
9116
|
auth,
|
|
8920
9117
|
smartAccount,
|
|
8921
9118
|
identity,
|
|
@@ -8945,7 +9142,7 @@ function assembleCapxulClient(input) {
|
|
|
8945
9142
|
telemetry: input.ports.telemetry,
|
|
8946
9143
|
close: stopActor
|
|
8947
9144
|
}
|
|
8948
|
-
};
|
|
9145
|
+
}, observation.failureObservation, observation.hostObservationSnapshot);
|
|
8949
9146
|
}
|
|
8950
9147
|
function withHostObservation(actor, snapshot) {
|
|
8951
9148
|
if (snapshot === void 0) return actor;
|
|
@@ -8962,4 +9159,4 @@ function withHostObservation(actor, snapshot) {
|
|
|
8962
9159
|
};
|
|
8963
9160
|
}
|
|
8964
9161
|
//#endregion
|
|
8965
|
-
export {
|
|
9162
|
+
export { fingerprintPaymentIntent as A, formatTraceparent as B, ClockPortTag as C, AuthClientError as D, authClientPortFromPromiseAdapter as E, sanitizeObservationContext as F, CAPXUL_PAYMENTS_V2_ADDRESS as G, readInvocationObservation as H, CAPXUL_FUNCTIONS as I, deriveCapxulSafeAddress as J, normalizeBindingEmail as K, BootstrapEnvelope as L, fromWei as M, OBSERVATION_CONTEXT_HEADER as N, AuthClientPortTag as O, encodeObservationContextHeader as P, EngineeringTelemetryBootstrapPolicy as R, ClockError as S, bootstrapErrorFromCapxul as T, injectedWalletSigner as U, copyInvocationObservation as V, signerFailure as W, destination as Y, wireChainId as _, observeFailedResult as a, ConvexCallPortTag as b, captureExceptionSync as c, TelemetryPortTag as d, redactTelemetryEvent as f, accountReadErrorFromCapxul as g, AccountReadPortTag as h, observationContextProps as i, toWei as j, version as k, detectAuthCacheAdapter as l, smartAccountErrorFromCapxul as m, postHogProductTelemetry as n, postHogFailureObservation as o, SmartAccountPortTag as p, BASE_SEPOLIA_CHAIN_ID as q, CAPXUL_SDK_EXPECTED_OUTCOME_EVENT as r, captureException as s, assembleCapxulClient as t, PostHogTelemetryLayer as u, IdentityPortTag as v, BootstrapPortTag as w, convexCallErrorFromCapxul as x, identityErrorFromCapxul as y, isSettingUpLifecycle as z };
|