@capxul/sdk 3.2.0 → 4.0.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.
@@ -1,5 +1,5 @@
1
- import { $ as CHAIN_UPSTREAMS, A as toBudgetId, B as toOrgId, C as ZERO_BYTES32, E as toAddress, F as toEmail, G as toRoleKey, H as toPayrollGroupId, J as CAPXUL_ERROR_CODES, M as toCountryCode, N as toCurrencyCode, Q as isCapxulError, S as WEI_RE, T as toAccountId, U as toPayrollRunId, V as toPartyId, X as EXPECTED_OPERATION_OUTCOMES, Y as CapxulError, Z as Errors, _ as deriveCapxulSafeAddress, at as failureFingerprint, b as EVM_ADDRESS_RE$1, ct as revertSummaryText, et as FAILURE_MODES$1, it as decodeChainCause, j as toChainId, k as toAuthUserId, lt as containsSensitiveMaterial, n as InMemoryAuthCacheAdapter, nt as chainCauseProperties, ot as isChainUpstream, p as orgRoleKeyForLabel, r as BrowserAuthCacheAdapter, rt as chainEvidenceLabel, st as isFailureMode, tt as boundedResponseHeaders, ut as redactSecrets, v as APP_ID_RE, x as SUPPORTED_CURRENCY_CODES, y as BYTES32_RE } from "./clock-CWpcQlLy.mjs";
2
- import { Context, Data, Deferred, Duration, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schema, SchemaGetter, Scope } from "effect";
1
+ import { $ as CapxulError, A as toAuthUserId, C as WEI_RE, D as toAddress, E as toAccountId, G as toPayrollRunId, H as toOrgId, I as toEmail, M as toChainId, N as toCountryCode, P as toCurrencyCode, Q as CAPXUL_ERROR_CODES, S as SUPPORTED_CURRENCY_CODES, U as toPartyId, W as toPayrollGroupId, _ as deriveCapxulSafeAddress, at as boundedResponseHeaders, b as BYTES32_RE, ct as decodeChainCause, dt as isFailureMode, et as EXPECTED_OPERATION_OUTCOMES, ft as revertSummaryText, it as FAILURE_MODES$1, j as toBudgetId, lt as failureFingerprint, mt as redactSecrets, n as InMemoryAuthCacheAdapter, nt as isCapxulError, ot as chainCauseProperties, p as orgRoleKeyForLabel, pt as containsSensitiveMaterial, q as toRoleKey, r as BrowserAuthCacheAdapter, rt as CHAIN_UPSTREAMS, st as chainEvidenceLabel, tt as Errors, ut as isChainUpstream, v as validateHandle, w as ZERO_BYTES32, x as EVM_ADDRESS_RE$1, y as APP_ID_RE } from "./clock-C2AUlq1V.mjs";
2
+ import { Context, Data, Deferred, Duration, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schema, SchemaGetter, SchemaParser, Scope } from "effect";
3
3
  import { formatUnits, keccak256, parseUnits, recoverAddress, toBytes } from "viem";
4
4
  import { makeFunctionReference } from "convex/server";
5
5
  //#region src/domain/identity/model.ts
@@ -494,7 +494,6 @@ const CAPXUL_OPERATIONS = {
494
494
  current: "holdings.current",
495
495
  primary: "holdings.primary"
496
496
  },
497
- handles: { resolve: "handles.resolve" },
498
497
  identity: {
499
498
  accountAt: "identity.AccountAt",
500
499
  accountClaimed: "identity.AccountClaimed",
@@ -530,7 +529,7 @@ const CAPXUL_OPERATIONS = {
530
529
  signOut: "identity.SignOut",
531
530
  signOutFailed: "identity.SignOutFailed",
532
531
  update: "identity.update",
533
- usernameAvailable: "identity.usernameAvailable",
532
+ handleAvailable: "identity.handleAvailable",
534
533
  verified: "identity.Verified",
535
534
  verifyFailed: "identity.VerifyFailed",
536
535
  verifyOtp: "identity.VerifyOtp"
@@ -546,10 +545,12 @@ const CAPXUL_OPERATIONS = {
546
545
  get: "me.get"
547
546
  },
548
547
  moneyExecution: {
548
+ abandonPaymentExecution: "moneyExecution.abandonPaymentExecution",
549
549
  prepareOrganizationPaymentExecution: "moneyExecution.prepareOrganizationPaymentExecution",
550
550
  preparePaymentExecution: "moneyExecution.preparePaymentExecution",
551
551
  preparePaymentLifecycleExecution: "moneyExecution.preparePaymentLifecycleExecution",
552
552
  preparePermissionExecution: "moneyExecution.preparePermissionExecution",
553
+ recoverSubmissionClaims: "moneyExecution.recoverSubmissionClaims",
553
554
  submit: "moneyExecution.submit",
554
555
  submitPaymentCommandExecution: "moneyExecution.submitPaymentCommandExecution",
555
556
  submitPaymentExecution: "moneyExecution.submitPaymentExecution",
@@ -568,9 +569,14 @@ const CAPXUL_OPERATIONS = {
568
569
  quote: "offramp.quote",
569
570
  status: "offramp.status"
570
571
  },
571
- onboarding: { completePerson: "onboarding.completePerson" },
572
+ onboarding: {
573
+ completeOrganization: "onboarding.completeOrganization",
574
+ completePerson: "onboarding.completePerson"
575
+ },
572
576
  org: {
577
+ acceptInvitations: "org.acceptInvitations",
573
578
  account: { get: "org.account.get" },
579
+ activateMember: "org.activateMember",
574
580
  auditLog: "org.auditLog",
575
581
  confirmBootstrap: "org.confirmBootstrap",
576
582
  createOrg: "org.createOrg",
@@ -581,6 +587,7 @@ const CAPXUL_OPERATIONS = {
581
587
  getProofReceipt: "org.getProofReceipt",
582
588
  invite: "org.invite",
583
589
  inviteMember: "org.inviteMember",
590
+ list: "org.list",
584
591
  load: "org.load",
585
592
  me: "org.me",
586
593
  members: "org.members",
@@ -673,11 +680,7 @@ const CAPXUL_OPERATIONS = {
673
680
  render: "paymentDocuments.render",
674
681
  verify: "paymentDocuments.verify"
675
682
  },
676
- payees: {
677
- create: "payees.create",
678
- get: "payees.get",
679
- resolve: "payees.resolve"
680
- },
683
+ recipient: { resolve: "recipient.resolve" },
681
684
  payroll: {
682
685
  authorizeRun: "payroll.authorizeRun",
683
686
  groups: {
@@ -759,12 +762,6 @@ const CAPXUL_OPERATIONS = {
759
762
  ping: "system.ping",
760
763
  runtimeChain: "system.runtimeChain"
761
764
  },
762
- targets: { resolve: {
763
- email: "targets.resolve.email",
764
- handle: "targets.resolve.handle",
765
- organization: "targets.resolve.organization",
766
- payee: "targets.resolve.payee"
767
- } },
768
765
  testUsdc: { mint: "TestUSDC.mint" },
769
766
  _internal: {
770
767
  accounts: { fund: "_internal.accounts.fund" },
@@ -1192,32 +1189,116 @@ const OrgInviteExpiredProps = Schema.Struct({
1192
1189
  role: OptionalString,
1193
1190
  status: OptionalString
1194
1191
  });
1192
+ const RecipientLocatorKindSchema = Schema.Literals([
1193
+ "handle",
1194
+ "email",
1195
+ "address",
1196
+ "party"
1197
+ ]);
1198
+ const RecipientResolutionStatusSchema = Schema.Literals([
1199
+ "known_party",
1200
+ "new_email",
1201
+ "external_address"
1202
+ ]);
1203
+ const RecipientPartyKindSchema = Schema.Literals([
1204
+ "person",
1205
+ "organization",
1206
+ "unresolved"
1207
+ ]);
1208
+ const RecipientTelemetryProps = {
1209
+ recipient_locator_kind: Schema.optional(RecipientLocatorKindSchema),
1210
+ recipient_resolution_status: Schema.optional(RecipientResolutionStatusSchema),
1211
+ recipient_party_id: OptionalString,
1212
+ recipient_party_kind: Schema.optional(RecipientPartyKindSchema),
1213
+ recipient_is_capxul_account: Schema.optional(Schema.Boolean),
1214
+ recipient_handle: OptionalString,
1215
+ recipient_address: OptionalAddress,
1216
+ external_address_acknowledged: Schema.optional(Schema.Boolean)
1217
+ };
1195
1218
  const PaymentInitiatedProps = Schema.Struct({
1219
+ command_id: OptionalString,
1220
+ execution_id: OptionalString,
1221
+ payment_lifecycle_id: OptionalString,
1196
1222
  ...TelemetryEnvelopeProps,
1223
+ ...RecipientTelemetryProps,
1197
1224
  kind: Schema.String,
1198
1225
  payment_id: Schema.String
1199
1226
  });
1227
+ const PaymentLifecycleProps = {
1228
+ payment_state: OptionalString,
1229
+ execution_state: OptionalString,
1230
+ occurred_at: Schema.optional(Schema.Number),
1231
+ causal_sequence: Schema.optional(Schema.Number),
1232
+ sponsorship_valid_until: Schema.optional(Schema.Number),
1233
+ terminal_event_id: OptionalString
1234
+ };
1200
1235
  const PaymentSettledL2Props = Schema.Struct({
1236
+ ...PaymentLifecycleProps,
1201
1237
  ...TelemetryEnvelopeProps,
1238
+ ...RecipientTelemetryProps,
1202
1239
  kind: Schema.String,
1203
1240
  chain_id: Schema.Number,
1204
- settlement_id: Schema.String
1241
+ settlement_id: Schema.String,
1242
+ payment_id: OptionalString,
1243
+ payment_ids: OptionalString,
1244
+ command_id: OptionalString,
1245
+ payment_lifecycle_id: OptionalString,
1246
+ execution_id: OptionalString,
1247
+ user_op_hash: OptionalString,
1248
+ transaction_hash: OptionalString
1205
1249
  });
1206
1250
  const PaymentFailedL2Props = Schema.Struct({
1251
+ ...PaymentLifecycleProps,
1207
1252
  ...TelemetryEnvelopeProps,
1208
1253
  ...ChainCauseTelemetryProps,
1254
+ ...RecipientTelemetryProps,
1209
1255
  kind: Schema.String,
1210
1256
  payment_id: Schema.String,
1211
- reason_code: Schema.String
1257
+ payment_ids: OptionalString,
1258
+ reason_code: Schema.String,
1259
+ command_id: OptionalString,
1260
+ payment_lifecycle_id: OptionalString,
1261
+ execution_id: OptionalString,
1262
+ user_op_hash: OptionalString
1212
1263
  });
1213
1264
  const PaymentVerificationRetryProps = Schema.Struct({
1265
+ ...PaymentLifecycleProps,
1214
1266
  ...TelemetryEnvelopeProps,
1267
+ ...RecipientTelemetryProps,
1215
1268
  command_id: Schema.String,
1269
+ payment_lifecycle_id: Schema.String,
1216
1270
  attempt: Schema.Number,
1217
1271
  reason_code: Schema.String,
1218
1272
  chain_id: Schema.Number,
1219
1273
  delay_ms: DurationMsSchema$1,
1220
- outcome: Schema.Literals(["scheduled", "unresolved"])
1274
+ outcome: Schema.Literals(["scheduled", "unresolved"]),
1275
+ payment_id: OptionalString,
1276
+ payment_ids: OptionalString,
1277
+ execution_id: OptionalString,
1278
+ user_op_hash: OptionalString
1279
+ });
1280
+ const PaymentLifecycleTransitionProps = Schema.Struct({
1281
+ ...TelemetryEnvelopeProps,
1282
+ ...RecipientTelemetryProps,
1283
+ payment_id: Schema.String,
1284
+ payment_lifecycle_id: Schema.String,
1285
+ command_id: Schema.String,
1286
+ payment_state: Schema.String,
1287
+ occurred_at: Schema.Number,
1288
+ causal_sequence: Schema.Number,
1289
+ execution_id: OptionalString,
1290
+ execution_state: OptionalString,
1291
+ user_op_hash: OptionalString,
1292
+ sponsorship_valid_until: Schema.optional(Schema.Number),
1293
+ reason_code: OptionalString
1294
+ });
1295
+ const QuickPayExternalAddressAcknowledgedProps = Schema.Struct({
1296
+ ...TelemetryEnvelopeProps,
1297
+ recipient_locator_kind: Schema.Literal("address"),
1298
+ recipient_resolution_status: Schema.Literal("external_address"),
1299
+ recipient_address: AddressSchema$1,
1300
+ external_address_acknowledged: Schema.Literal(true),
1301
+ organization_id: OptionalOrgId
1221
1302
  });
1222
1303
  const DepositInitiatedProps = Schema.Struct({ ...TelemetryEnvelopeProps });
1223
1304
  const DepositSettledProps = Schema.Struct({
@@ -1425,6 +1506,14 @@ Schema.Struct({
1425
1506
  name: Schema.Literal("payment_verification_retry"),
1426
1507
  props: PaymentVerificationRetryProps
1427
1508
  });
1509
+ Schema.Struct({
1510
+ name: Schema.Literal("payment_lifecycle_transition"),
1511
+ props: PaymentLifecycleTransitionProps
1512
+ });
1513
+ Schema.Struct({
1514
+ name: Schema.Literal("quick_pay_external_address_acknowledged"),
1515
+ props: QuickPayExternalAddressAcknowledgedProps
1516
+ });
1428
1517
  Schema.Struct({
1429
1518
  name: Schema.Literal("deposit_initiated"),
1430
1519
  props: DepositInitiatedProps
@@ -1774,16 +1863,13 @@ const CAPXUL_FUNCTIONS = {
1774
1863
  list: "financialOps/destinations:list",
1775
1864
  remove: "financialOps/destinations:remove"
1776
1865
  },
1777
- "financialOps/mutations": { createPayee: "financialOps/mutations:createPayee" },
1778
1866
  "financialOps/queries": {
1779
1867
  depositInstructions: "financialOps/queries:depositInstructions",
1780
- getPayee: "financialOps/queries:getPayee",
1781
1868
  getPayment: "financialOps/queries:getPayment",
1782
1869
  listPayments: "financialOps/queries:listPayments",
1783
1870
  me: "financialOps/queries:me",
1784
1871
  renderStoredDocument: "financialOps/queries:renderStoredDocument",
1785
- resolveHandle: "financialOps/queries:resolveHandle",
1786
- resolvePayee: "financialOps/queries:resolvePayee",
1872
+ resolveRecipient: "financialOps/queries:resolveRecipient",
1787
1873
  verifyPaymentDocument: "financialOps/queries:verifyPaymentDocument"
1788
1874
  },
1789
1875
  "financialOps/requestsInbox": {
@@ -1802,7 +1888,7 @@ const CAPXUL_FUNCTIONS = {
1802
1888
  },
1803
1889
  "identity/queries": {
1804
1890
  loadByAuthUserId: "identity/queries:loadByAuthUserId",
1805
- usernameAvailable: "identity/queries:usernameAvailable"
1891
+ handleAvailable: "identity/queries:handleAvailable"
1806
1892
  },
1807
1893
  "holdings/actions": { current: "holdings/actions:current" },
1808
1894
  "movement/activity": {
@@ -1812,6 +1898,7 @@ const CAPXUL_FUNCTIONS = {
1812
1898
  summary: "movement/activity:summary"
1813
1899
  },
1814
1900
  "moneyExecution/actions": {
1901
+ abandonPaymentExecution: "moneyExecution/actions:abandonPaymentExecution",
1815
1902
  preparePermissionExecution: "moneyExecution/actions:preparePermissionExecution",
1816
1903
  preparePaymentExecution: "moneyExecution/actions:preparePaymentExecution",
1817
1904
  submitPermissionExecution: "moneyExecution/actions:submitPermissionExecution",
@@ -1889,6 +1976,7 @@ const CAPXUL_FUNCTIONS = {
1889
1976
  const PAYMENT_STATUSES = [
1890
1977
  "pending",
1891
1978
  "settling",
1979
+ "unresolved",
1892
1980
  "scheduled",
1893
1981
  "streaming",
1894
1982
  "pending_claim",
@@ -1896,6 +1984,30 @@ const PAYMENT_STATUSES = [
1896
1984
  "cancelled",
1897
1985
  "failed"
1898
1986
  ];
1987
+ /** The lifecycle of one signed Payment execution attempt. */
1988
+ const PAYMENT_EXECUTION_STATUS = {
1989
+ PENDING: "pending",
1990
+ INCLUDED: "included",
1991
+ DROPPED: "dropped",
1992
+ REPLACED: "replaced",
1993
+ EXPIRED: "expired",
1994
+ UNRESOLVED: "unresolved",
1995
+ SUPERSEDED: "superseded",
1996
+ FAILED: "failed",
1997
+ SETTLED: "settled"
1998
+ };
1999
+ const PAYMENT_EXECUTION_STATUSES = [
2000
+ PAYMENT_EXECUTION_STATUS.PENDING,
2001
+ PAYMENT_EXECUTION_STATUS.INCLUDED,
2002
+ PAYMENT_EXECUTION_STATUS.DROPPED,
2003
+ PAYMENT_EXECUTION_STATUS.REPLACED,
2004
+ PAYMENT_EXECUTION_STATUS.EXPIRED,
2005
+ PAYMENT_EXECUTION_STATUS.UNRESOLVED,
2006
+ PAYMENT_EXECUTION_STATUS.SUPERSEDED,
2007
+ PAYMENT_EXECUTION_STATUS.FAILED,
2008
+ PAYMENT_EXECUTION_STATUS.SETTLED
2009
+ ];
2010
+ PAYMENT_EXECUTION_STATUS.DROPPED, PAYMENT_EXECUTION_STATUS.REPLACED, PAYMENT_EXECUTION_STATUS.EXPIRED, PAYMENT_EXECUTION_STATUS.SUPERSEDED;
1899
2011
  /** The payment direction relative to the current actor. */
1900
2012
  const PAYMENT_DIRECTIONS = [
1901
2013
  "in",
@@ -1931,22 +2043,16 @@ const EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
1931
2043
  */
1932
2044
  const PAYMENT_DOCUMENT_VERIFYING_CONTRACT = "0x7a5c25aB7ce91d7a475B71cd1ec33E230291f8a4";
1933
2045
  const PAYMENT_ID_RE = /^payment_[0-9A-Za-z]+$/;
1934
- const PAYEE_ID_RE = /^payee_[0-9A-Za-z]+$/;
1935
2046
  const ORG_ID_RE = /^org_[0-9A-Za-z]+$/;
1936
- const USER_ID_RE = /^user_[0-9A-Za-z]+$/;
1937
2047
  const PARTY_ID_RE = /^party_[0-9A-Za-z]+$/;
1938
- const HANDLE_RE = /^@?[a-z0-9][a-z0-9-]{2,31}$/;
1939
- const ORG_HANDLE_RE = /^[a-z0-9][a-z0-9-]{2,31}$/;
2048
+ const HANDLE_RE = /^@?[a-z0-9_-]{3,30}$/;
1940
2049
  const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1941
2050
  const MinorUnitStringSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => MINOR_UNIT_STRING_RE.test(value), { message: "must be a non-negative integer minor-unit string" })));
1942
2051
  const PaymentIdSchema$1 = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => PAYMENT_ID_RE.test(value), { message: "must be payment_ plus an alphanumeric id" })));
1943
- const PayeeIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => PAYEE_ID_RE.test(value), { message: "must be payee_ plus an alphanumeric id" })));
1944
2052
  const OrgIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => ORG_ID_RE.test(value), { message: "must be org_ plus an alphanumeric id" })));
1945
- const UserIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => USER_ID_RE.test(value), { message: "must be user_ plus an alphanumeric id" })));
1946
2053
  const PartyIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => PARTY_ID_RE.test(value), { message: "must be party_ plus an alphanumeric id" })));
1947
2054
  const DecimalStringSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => DECIMAL_STRING_RE.test(value), { message: "must be a non-negative decimal string" })));
1948
2055
  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" })));
1949
- 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" })));
1950
2056
  const EmailValueSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => !EVM_ADDRESS_RE.test(value) && EMAIL_RE.test(value), { message: "must be an email; raw addresses are not accepted" })));
1951
2057
  const Uint8Schema$1 = Schema.Number.pipe(Schema.check(Schema.makeFilter((value) => Number.isSafeInteger(value) && value >= 0 && value <= 255, { message: "must be a uint8" })));
1952
2058
  const Uint64Schema = Schema.Number.pipe(Schema.check(Schema.makeFilter((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" })));
@@ -2066,42 +2172,39 @@ const WithdrawalDocumentEnvelope = Schema.Struct({
2066
2172
  primaryType: Schema.Literal("Withdrawal"),
2067
2173
  message: WithdrawalDocument
2068
2174
  });
2069
- Schema.Union([AttachablePaymentDocumentEnvelope, WithdrawalDocumentEnvelope]);
2070
- Schema.Struct({
2071
- payeeId: PayeeIdSchema,
2072
- label: Schema.String,
2073
- trustState: Schema.Literals([
2074
- "unverified",
2075
- "trusted",
2076
- "blocked"
2077
- ]),
2078
- destinationKind: Schema.Literals([
2079
- "handle",
2080
- "email",
2081
- "saved-payee",
2082
- "org"
2083
- ])
2084
- });
2085
- const PaymentRecipient = Schema.Struct({
2086
- kind: Schema.Literals([
2087
- "handle",
2088
- "email",
2089
- "payee",
2090
- "capxulUserId",
2091
- "me",
2092
- "org",
2093
- "party",
2094
- "external_address"
2095
- ]),
2096
- label: Schema.String,
2097
- payeeId: Schema.optional(PayeeIdSchema)
2098
- });
2175
+ const PaymentDocumentEnvelope = Schema.Union([AttachablePaymentDocumentEnvelope, WithdrawalDocumentEnvelope]);
2176
+ const ENVELOPE_PRIMARY_TYPE_TO_KIND = {
2177
+ Memo: "memo",
2178
+ Invoice: "invoice",
2179
+ Payslip: "payslip",
2180
+ Receipt: "receipt",
2181
+ Withdrawal: "withdrawal"
2182
+ };
2099
2183
  /**
2100
- * A raw external EVM address for the B3 withdraw lane — the cash-out
2101
- * destination. This is the ONE schema that ACCEPTS a bare 0x (the withdraw
2102
- * mutation args use it), as opposed to `PaymentRecipientRefSchema` which
2103
- * REJECTS bare addresses to protect the pay lane. The full address never
2104
- * crosses the model wire; it lives on the kind:4 Withdrawal document only.
2184
+ * Derive the wire `paymentType` an UNKNOWN document envelope classifies to
2185
+ * (payment-document-spec.md D11: memo/withdrawal → unspecified, invoice →
2186
+ * invoice, payslip → payroll, receipt → reimbursement), or `undefined` if the
2187
+ * envelope is absent / malformed — the same tolerance as
2188
+ * `tryHashPaymentDocument`. Callers holding an untyped envelope (e.g. the MCP
2189
+ * org spend port, #712) use this so the type they record agrees with the type
2190
+ * the backend re-derives from the same document.
2191
+ */
2192
+ function paymentTypeForDocumentEnvelope(envelope) {
2193
+ if (envelope === void 0 || envelope === null) return void 0;
2194
+ const decoded = SchemaParser.decodeUnknownResult(PaymentDocumentEnvelope)(envelope);
2195
+ if (decoded._tag === "Failure") return void 0;
2196
+ return paymentTypeForDocumentKind(ENVELOPE_PRIMARY_TYPE_TO_KIND[decoded.success.primaryType]);
2197
+ }
2198
+ const PaymentRecipient = Schema.Union([Schema.Struct({
2199
+ kind: Schema.Literal("party"),
2200
+ partyId: PartyIdSchema,
2201
+ label: Schema.String
2202
+ }), Schema.Struct({
2203
+ kind: Schema.Literal("external_address"),
2204
+ label: Schema.String
2205
+ })]);
2206
+ /**
2207
+ * A raw external EVM address for a payment or withdrawal destination.
2105
2208
  */
2106
2209
  const ExternalAddressSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => EVM_ADDRESS_RE.test(value), { message: "must be a 0x EVM address (40 hex chars)" })));
2107
2210
  const PaymentTiming = Schema.Union([
@@ -2127,16 +2230,8 @@ const PaymentRef = Schema.Union([
2127
2230
  email: EmailValueSchema
2128
2231
  }),
2129
2232
  Schema.Struct({
2130
- kind: Schema.Literal("orgHandle"),
2131
- orgHandle: OrgHandleValueSchema
2132
- }),
2133
- Schema.Struct({
2134
- kind: Schema.Literal("capxulUserId"),
2135
- capxulUserId: UserIdSchema
2136
- }),
2137
- Schema.Struct({
2138
- kind: Schema.Literal("payeeId"),
2139
- payeeId: PayeeIdSchema
2233
+ kind: Schema.Literal("address"),
2234
+ address: ExternalAddressSchema
2140
2235
  }),
2141
2236
  Schema.Struct({
2142
2237
  kind: Schema.Literal("party"),
@@ -2159,6 +2254,10 @@ const Payment = Schema.Struct({
2159
2254
  timing: PaymentTiming,
2160
2255
  released: FinancialOpsMoney,
2161
2256
  availableToClaim: FinancialOpsMoney,
2257
+ execution: Schema.optional(Schema.Struct({
2258
+ status: Schema.Literals(PAYMENT_EXECUTION_STATUSES),
2259
+ retryRequired: Schema.Boolean
2260
+ })),
2162
2261
  createdAt: EpochMsSchema,
2163
2262
  updatedAt: EpochMsSchema
2164
2263
  }).pipe(Schema.check(Schema.makeFilter((payment) => payment.documents.every((document) => paymentTypeForDocumentKind(document.kind) === payment.paymentType), { message: "document kind must map to paymentType" })));
@@ -2303,11 +2402,21 @@ const MovementIdentitySchema = Schema.Struct({
2303
2402
  txHash: TxHashSchema,
2304
2403
  logIndex: LogIndexSchema
2305
2404
  });
2306
- const MovementCanonicalStateSchema = Schema.Literals([
2405
+ const MovementCanonicalStateInputSchema = Schema.Literals([
2307
2406
  "observed",
2407
+ "included",
2308
2408
  "finalized",
2309
2409
  "removed"
2310
2410
  ]);
2411
+ const MovementCanonicalStateOutputSchema = Schema.Literals([
2412
+ "observed",
2413
+ "included",
2414
+ "removed"
2415
+ ]);
2416
+ const MovementCanonicalStateSchema = MovementCanonicalStateInputSchema.pipe(Schema.decodeTo(MovementCanonicalStateOutputSchema, {
2417
+ decode: SchemaGetter.transform((state) => state === "finalized" ? "included" : state),
2418
+ encode: SchemaGetter.transform((state) => state)
2419
+ }));
2311
2420
  const MovementSchema = Schema.Struct({
2312
2421
  ...MovementIdentitySchema.fields,
2313
2422
  movementId: MovementIdSchema,
@@ -2658,7 +2767,7 @@ Schema.Struct({
2658
2767
  transfers: Schema.Array(TransferEvidenceSchema),
2659
2768
  requestCount: nonNegativeInteger("requestCount")
2660
2769
  });
2661
- const FinalizedMoneyEvidenceCommonSchema = Schema.Struct({
2770
+ const VerifiedMoneyEvidenceCommonSchema = Schema.Struct({
2662
2771
  chainId: BaseSepoliaChainIdSchema,
2663
2772
  contractAddress: AddressSchema,
2664
2773
  userOpHash: Bytes32Schema,
@@ -2668,8 +2777,8 @@ const FinalizedMoneyEvidenceCommonSchema = Schema.Struct({
2668
2777
  blockTimestamp: Uint48Schema,
2669
2778
  eventLogIndex: LogIndexSchema
2670
2779
  });
2671
- const FinalizedPaymentEvidenceSchema = Schema.Struct({
2672
- ...FinalizedMoneyEvidenceCommonSchema.fields,
2780
+ const VerifiedPaymentEvidenceSchema = Schema.Struct({
2781
+ ...VerifiedMoneyEvidenceCommonSchema.fields,
2673
2782
  operation: Schema.Literal("send"),
2674
2783
  settlementId: SettlementIdSchema,
2675
2784
  purposeKind: PaymentPurposeKindSchema,
@@ -2681,8 +2790,8 @@ const FinalizedPaymentEvidenceSchema = Schema.Struct({
2681
2790
  destination: AddressSchema,
2682
2791
  rawAmount: WeiAmountSchema
2683
2792
  });
2684
- const FinalizedCommitmentCreationEvidenceSchema = Schema.Struct({
2685
- ...FinalizedMoneyEvidenceCommonSchema.fields,
2793
+ const VerifiedCommitmentCreationEvidenceSchema = Schema.Struct({
2794
+ ...VerifiedMoneyEvidenceCommonSchema.fields,
2686
2795
  operation: Schema.Literal("create_commitment"),
2687
2796
  commitmentId: Uint256StringSchema,
2688
2797
  settlementId: SettlementIdSchema,
@@ -2698,8 +2807,8 @@ const FinalizedCommitmentCreationEvidenceSchema = Schema.Struct({
2698
2807
  documentHash: NonzeroDocumentHashSchema,
2699
2808
  transferLogIndex: LogIndexSchema
2700
2809
  });
2701
- const FinalizedCommitmentClaimEvidenceSchema = Schema.Struct({
2702
- ...FinalizedMoneyEvidenceCommonSchema.fields,
2810
+ const VerifiedCommitmentClaimEvidenceSchema = Schema.Struct({
2811
+ ...VerifiedMoneyEvidenceCommonSchema.fields,
2703
2812
  operation: Schema.Literal("claim_commitment"),
2704
2813
  commitmentId: Uint256StringSchema,
2705
2814
  settlementId: SettlementIdSchema,
@@ -2712,8 +2821,8 @@ const FinalizedCommitmentClaimEvidenceSchema = Schema.Struct({
2712
2821
  documentHash: NonzeroDocumentHashSchema,
2713
2822
  transferLogIndex: LogIndexSchema
2714
2823
  });
2715
- const FinalizedCommitmentCancelEvidenceSchema = Schema.Struct({
2716
- ...FinalizedMoneyEvidenceCommonSchema.fields,
2824
+ const VerifiedCommitmentCancelEvidenceSchema = Schema.Struct({
2825
+ ...VerifiedMoneyEvidenceCommonSchema.fields,
2717
2826
  operation: Schema.Literal("cancel_commitment"),
2718
2827
  commitmentId: Uint256StringSchema,
2719
2828
  settlementId: SettlementIdSchema,
@@ -2727,8 +2836,8 @@ const FinalizedCommitmentCancelEvidenceSchema = Schema.Struct({
2727
2836
  documentHash: NonzeroDocumentHashSchema,
2728
2837
  transfer: Schema.NullOr(TransferEvidenceSchema)
2729
2838
  });
2730
- const FinalizedCommitmentRedirectEvidenceSchema = Schema.Struct({
2731
- ...FinalizedMoneyEvidenceCommonSchema.fields,
2839
+ const VerifiedCommitmentRedirectEvidenceSchema = Schema.Struct({
2840
+ ...VerifiedMoneyEvidenceCommonSchema.fields,
2732
2841
  operation: Schema.Literal("redirect_commitment"),
2733
2842
  commitmentId: Uint256StringSchema,
2734
2843
  settlementId: SettlementIdSchema,
@@ -2739,12 +2848,12 @@ const FinalizedCommitmentRedirectEvidenceSchema = Schema.Struct({
2739
2848
  documentHash: NonzeroDocumentHashSchema,
2740
2849
  transfer: Schema.Null
2741
2850
  });
2742
- const FinalizedMoneyEvidenceSchema = Schema.Union([
2743
- FinalizedPaymentEvidenceSchema,
2744
- FinalizedCommitmentCreationEvidenceSchema,
2745
- FinalizedCommitmentClaimEvidenceSchema,
2746
- FinalizedCommitmentCancelEvidenceSchema,
2747
- FinalizedCommitmentRedirectEvidenceSchema
2851
+ const VerifiedMoneyEvidenceSchema = Schema.Union([
2852
+ VerifiedPaymentEvidenceSchema,
2853
+ VerifiedCommitmentCreationEvidenceSchema,
2854
+ VerifiedCommitmentClaimEvidenceSchema,
2855
+ VerifiedCommitmentCancelEvidenceSchema,
2856
+ VerifiedCommitmentRedirectEvidenceSchema
2748
2857
  ]);
2749
2858
  Schema.Union([
2750
2859
  Schema.Struct({
@@ -2754,7 +2863,7 @@ Schema.Union([
2754
2863
  }),
2755
2864
  Schema.Struct({
2756
2865
  status: Schema.Literal("verified"),
2757
- evidence: FinalizedMoneyEvidenceSchema
2866
+ evidence: VerifiedMoneyEvidenceSchema
2758
2867
  }),
2759
2868
  Schema.Struct({
2760
2869
  status: Schema.Literal("mismatch"),
@@ -2766,7 +2875,7 @@ Schema.Union([
2766
2875
  retryable: Schema.Literal(true)
2767
2876
  })
2768
2877
  ]);
2769
- const FinalizedAttributedInboundMovementSchema = Schema.Struct({
2878
+ const VerifiedAttributedInboundMovementSchema = Schema.Struct({
2770
2879
  movement: MovementSchema,
2771
2880
  attribution: MovementAttributionSchema
2772
2881
  });
@@ -2792,6 +2901,25 @@ const ProtocolBirthInputSchema = Schema.Struct({
2792
2901
  release: ReleaseTermsSchema,
2793
2902
  lineage: Schema.optional(PaymentCommandLineageSchema)
2794
2903
  }).pipe(Schema.refine((birth) => hasActorBoundPermission(birth.actor, birth.actor.kind === "organization" ? birth.actor.orgId : void 0, birth.permissionId), { message: "Organization Payment and Payout births require permissionId; personal births forbid it" }));
2904
+ const ApplyVerifiedEvidenceCommandSchema = Schema.Struct({
2905
+ kind: Schema.Literal("apply_verified_evidence"),
2906
+ paymentId: PaymentIdSchema,
2907
+ evidence: VerifiedMoneyEvidenceSchema
2908
+ });
2909
+ const ApplyFinalizedEvidenceCommandSchema = Schema.Struct({
2910
+ kind: Schema.Literal("apply_finalized_evidence"),
2911
+ paymentId: PaymentIdSchema,
2912
+ evidence: VerifiedMoneyEvidenceSchema
2913
+ }).pipe(Schema.decodeTo(ApplyVerifiedEvidenceCommandSchema, {
2914
+ decode: SchemaGetter.transform((value) => ({
2915
+ ...value,
2916
+ kind: "apply_verified_evidence"
2917
+ })),
2918
+ encode: SchemaGetter.transform((value) => ({
2919
+ ...value,
2920
+ kind: "apply_finalized_evidence"
2921
+ }))
2922
+ }));
2795
2923
  Schema.Union([
2796
2924
  Schema.Struct({
2797
2925
  kind: Schema.Literal("birth"),
@@ -2799,7 +2927,7 @@ Schema.Union([
2799
2927
  }),
2800
2928
  Schema.Struct({
2801
2929
  kind: Schema.Literal("birth_deposit"),
2802
- movement: FinalizedAttributedInboundMovementSchema
2930
+ movement: VerifiedAttributedInboundMovementSchema
2803
2931
  }),
2804
2932
  Schema.Struct({
2805
2933
  kind: Schema.Literal("rollback_deposit"),
@@ -2811,11 +2939,8 @@ Schema.Union([
2811
2939
  paymentIds: Schema.Array(PaymentIdSchema),
2812
2940
  userOpHash: Bytes32Schema
2813
2941
  }),
2814
- Schema.Struct({
2815
- kind: Schema.Literal("apply_finalized_evidence"),
2816
- paymentId: PaymentIdSchema,
2817
- evidence: FinalizedMoneyEvidenceSchema
2818
- }),
2942
+ ApplyVerifiedEvidenceCommandSchema,
2943
+ ApplyFinalizedEvidenceCommandSchema,
2819
2944
  Schema.Struct({
2820
2945
  kind: Schema.Literal("transition"),
2821
2946
  paymentId: PaymentIdSchema,
@@ -2957,6 +3082,7 @@ const MoneyExecutionIdSchema = Schema.String.pipe(Schema.refine((value) => /^mon
2957
3082
  const OwnerSignatureSchema = Schema.String.pipe(Schema.refine((value) => /^0x[0-9a-fA-F]{130}$/u.test(value), { message: "signature must be a 65-byte 0x value" }));
2958
3083
  const PaymentExecutionIntentSchema = Schema.Struct({
2959
3084
  to: PaymentRef,
3085
+ externalAddressAcknowledged: Schema.optional(Schema.Literal(true)),
2960
3086
  amount: FinancialOpsMoney,
2961
3087
  paymentType: Schema.optional(Schema.Literals([
2962
3088
  "unspecified",
@@ -2973,7 +3099,31 @@ Schema.Struct({
2973
3099
  signerAddress: AddressSchema,
2974
3100
  payment: PaymentExecutionIntentSchema
2975
3101
  });
3102
+ const RecipientObservationSchema = Schema.Struct({
3103
+ recipient_locator_kind: Schema.Literals([
3104
+ "handle",
3105
+ "email",
3106
+ "party",
3107
+ "address"
3108
+ ]),
3109
+ recipient_resolution_status: Schema.Literals([
3110
+ "known_party",
3111
+ "new_email",
3112
+ "external_address"
3113
+ ]),
3114
+ recipient_is_capxul_account: Schema.Boolean,
3115
+ recipient_party_id: Schema.optional(Schema.String),
3116
+ recipient_party_kind: Schema.optional(Schema.Literals([
3117
+ "person",
3118
+ "organization",
3119
+ "unresolved"
3120
+ ])),
3121
+ recipient_handle: Schema.optional(Schema.String),
3122
+ recipient_address: AddressSchema,
3123
+ external_address_acknowledged: Schema.Boolean
3124
+ });
2976
3125
  Schema.Struct({
3126
+ recipientObservation: RecipientObservationSchema,
2977
3127
  executionId: MoneyExecutionIdSchema,
2978
3128
  commandId: PaymentCommandIdSchema,
2979
3129
  paymentId: PaymentIdSchema,
@@ -2990,6 +3140,14 @@ Schema.Struct({
2990
3140
  executionId: MoneyExecutionIdSchema,
2991
3141
  signature: OwnerSignatureSchema
2992
3142
  });
3143
+ Schema.Struct({
3144
+ executionId: MoneyExecutionIdSchema,
3145
+ reason: Schema.Literals([
3146
+ "signer_rejected",
3147
+ "cancelled",
3148
+ "prepared_mismatch"
3149
+ ])
3150
+ });
2993
3151
  Schema.Struct({
2994
3152
  executionId: MoneyExecutionIdSchema,
2995
3153
  commandId: PaymentCommandIdSchema,
@@ -3003,6 +3161,10 @@ Schema.Struct({
3003
3161
  payments: Schema.Array(Payment)
3004
3162
  });
3005
3163
  const PaymentLifecycleExecutionIntentSchema = Schema.Union([
3164
+ Schema.Struct({
3165
+ kind: Schema.Literal("retry"),
3166
+ paymentId: PaymentIdSchema
3167
+ }),
3006
3168
  Schema.Struct({
3007
3169
  kind: Schema.Literal("claim"),
3008
3170
  paymentId: PaymentIdSchema
@@ -3023,6 +3185,7 @@ Schema.Struct({
3023
3185
  });
3024
3186
  const OrganizationPaymentExecutionItemSchema = Schema.Struct({
3025
3187
  to: PaymentRef,
3188
+ externalAddressAcknowledged: Schema.optional(Schema.Literal(true)),
3026
3189
  amount: FinancialOpsMoney,
3027
3190
  paymentType: Schema.optional(Schema.Literals([
3028
3191
  "unspecified",
@@ -3041,6 +3204,8 @@ Schema.Struct({
3041
3204
  lineage: Schema.optional(PaymentCommandLineageSchema)
3042
3205
  });
3043
3206
  const PreparedPaymentCommandExecutionSchema = Schema.Struct({
3207
+ recipientObservations: Schema.Array(RecipientObservationSchema),
3208
+ emitPaymentInitiated: Schema.Boolean,
3044
3209
  executionId: MoneyExecutionIdSchema,
3045
3210
  commandId: PaymentCommandIdSchema,
3046
3211
  paymentIds: Schema.Array(PaymentIdSchema),
@@ -3076,7 +3241,8 @@ const PermissionCommandSchema = Schema.Union([
3076
3241
  operation: Schema.Literal("assign"),
3077
3242
  requestKey: nonEmpty("requestKey"),
3078
3243
  permissionId: PermissionIdSchema,
3079
- accountId: nonEmpty("accountId")
3244
+ accountId: nonEmpty("accountId"),
3245
+ expectedMemberEmail: Schema.optional(nonEmpty("expectedMemberEmail"))
3080
3246
  }),
3081
3247
  Schema.Struct({
3082
3248
  operation: Schema.Literal("revoke"),
@@ -4520,25 +4686,11 @@ function normalizeRefForBackend$1(ref, field) {
4520
4686
  email: nonEmptyRefValue$1(ref.email, "email")
4521
4687
  }
4522
4688
  };
4523
- case "orgHandle": return {
4689
+ case "address": return {
4524
4690
  ok: true,
4525
4691
  value: {
4526
- kind: "orgHandle",
4527
- orgHandle: nonEmptyRefValue$1(ref.orgHandle, "orgHandle")
4528
- }
4529
- };
4530
- case "capxulUserId": return {
4531
- ok: true,
4532
- value: {
4533
- kind: "capxulUserId",
4534
- capxulUserId: nonEmptyRefValue$1(ref.capxulUserId, "capxulUserId")
4535
- }
4536
- };
4537
- case "payeeId": return {
4538
- ok: true,
4539
- value: {
4540
- kind: "payeeId",
4541
- payeeId: nonEmptyRefValue$1(ref.payeeId, "payeeId")
4692
+ kind: "address",
4693
+ address: toAddress(ref.address)
4542
4694
  }
4543
4695
  };
4544
4696
  case "party": return {
@@ -4802,10 +4954,7 @@ function makeAccountMethods(deps) {
4802
4954
  const financialOpsContract = {
4803
4955
  me: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].me),
4804
4956
  depositInstructions: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].depositInstructions),
4805
- resolveHandle: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].resolveHandle),
4806
- createPayee: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/mutations"].createPayee),
4807
- getPayee: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].getPayee),
4808
- resolvePayee: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].resolvePayee),
4957
+ resolveRecipient: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].resolveRecipient),
4809
4958
  addDestination: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/destinations"].add),
4810
4959
  listDestinations: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/destinations"].list),
4811
4960
  removeDestination: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/destinations"].remove),
@@ -4821,6 +4970,7 @@ const financialOpsContract = {
4821
4970
  //#endregion
4822
4971
  //#region src/contract/money-execution.ts
4823
4972
  const moneyExecutionContract = {
4973
+ abandonPaymentExecution: makeFunctionReference(CAPXUL_FUNCTIONS["moneyExecution/actions"].abandonPaymentExecution),
4824
4974
  preparePermissionExecution: makeFunctionReference(CAPXUL_FUNCTIONS["moneyExecution/actions"].preparePermissionExecution),
4825
4975
  preparePaymentExecution: makeFunctionReference(CAPXUL_FUNCTIONS["moneyExecution/actions"].preparePaymentExecution),
4826
4976
  prepareOrganizationPaymentExecution: makeFunctionReference(CAPXUL_FUNCTIONS["moneyExecution/paymentCommandActions"].prepareOrganizationPaymentExecution),
@@ -4831,7 +4981,7 @@ const moneyExecutionContract = {
4831
4981
  };
4832
4982
  //#endregion
4833
4983
  //#region package.json
4834
- var version = "3.2.0";
4984
+ var version = "4.0.0";
4835
4985
  //#endregion
4836
4986
  //#region src/telemetry/exception-projection.ts
4837
4987
  /** Fixed fallback for failures that have no safe message. */
@@ -5542,7 +5692,11 @@ function emitPaymentInitiated(telemetry, input) {
5542
5692
  name: "payment_initiated",
5543
5693
  props: {
5544
5694
  kind: input.kind,
5545
- payment_id: input.paymentId
5695
+ payment_id: input.paymentId,
5696
+ payment_lifecycle_id: `payment_lifecycle_${input.paymentId}`,
5697
+ ...input.commandId === void 0 ? {} : { command_id: input.commandId },
5698
+ ...input.executionId === void 0 ? {} : { execution_id: input.executionId },
5699
+ ...input.recipient
5546
5700
  }
5547
5701
  });
5548
5702
  }
@@ -5574,7 +5728,17 @@ async function fingerprintPaymentIntent(intent) {
5574
5728
  function matchesIntent(expected) {
5575
5729
  return async (request) => await fingerprintPaymentIntent(request) === await fingerprintPaymentIntent(expected);
5576
5730
  }
5577
- async function executePrepared(deps, prepare, isExpectedRequest, signal) {
5731
+ async function abandonPrepared$1(deps, executionId, closePayment, reason, result, onPreparedClosed) {
5732
+ if (!closePayment) return result;
5733
+ const abandoned = await runIfActive(void 0, CAPXUL_OPERATIONS.moneyExecution.abandonPaymentExecution, () => deps.convexCall.action(deps.functions.abandonPaymentExecution, { input: {
5734
+ executionId,
5735
+ reason
5736
+ } }));
5737
+ if (!abandoned.ok) return abandoned;
5738
+ if (abandoned.value) onPreparedClosed?.();
5739
+ return result;
5740
+ }
5741
+ async function executePrepared(deps, prepare, isExpectedRequest, closePaymentOnExit, onPreparedClosed, signal) {
5578
5742
  if (isAborted$2(signal)) return {
5579
5743
  ok: false,
5580
5744
  error: Errors.cancelled({ operation: "payments" })
@@ -5595,32 +5759,45 @@ async function executePrepared(deps, prepare, isExpectedRequest, signal) {
5595
5759
  }
5596
5760
  const prepared = await prepare(signerAddress);
5597
5761
  if (!prepared.ok) return prepared;
5598
- if (!await isExpectedRequest(prepared.value.request)) return {
5762
+ if (!await isExpectedRequest(prepared.value.request)) return abandonPrepared$1(deps, prepared.value.executionId, closePaymentOnExit, "prepared_mismatch", {
5599
5763
  ok: false,
5600
5764
  error: Errors.invalidInput("payment", "prepared command mismatch")
5601
- };
5765
+ }, onPreparedClosed);
5602
5766
  const expectedSafe = deriveCapxulSafeAddress({ email: session.email });
5603
- if (prepared.value.chainId !== deps.chainId || prepared.value.signerAddress.toLowerCase() !== signerAddress.toLowerCase() || prepared.value.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return {
5767
+ if (prepared.value.chainId !== deps.chainId || prepared.value.signerAddress.toLowerCase() !== signerAddress.toLowerCase() || prepared.value.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return abandonPrepared$1(deps, prepared.value.executionId, closePaymentOnExit, "prepared_mismatch", {
5604
5768
  ok: false,
5605
5769
  error: Errors.invalidInput("payment", "prepared authority mismatch")
5606
- };
5607
- if (isAborted$2(signal)) return {
5770
+ }, onPreparedClosed);
5771
+ if (isAborted$2(signal)) return abandonPrepared$1(deps, prepared.value.executionId, closePaymentOnExit, "cancelled", {
5608
5772
  ok: false,
5609
5773
  error: Errors.cancelled({ operation: "payments" })
5610
- };
5774
+ }, onPreparedClosed);
5775
+ if (prepared.value.emitPaymentInitiated && "items" in prepared.value.request) for (const [index, item] of prepared.value.request.items.entries()) {
5776
+ const paymentId = prepared.value.paymentIds[index];
5777
+ const recipient = prepared.value.recipientObservations[index];
5778
+ if (paymentId === void 0 || recipient === void 0) continue;
5779
+ const paymentType = paymentTypeForDocumentEnvelope(item.document) ?? item.paymentType ?? "unspecified";
5780
+ await emitPaymentInitiated(deps.telemetry, {
5781
+ commandId: prepared.value.commandId,
5782
+ executionId: prepared.value.executionId,
5783
+ paymentId,
5784
+ kind: paymentType === "unspecified" ? "quick_pay" : paymentType,
5785
+ recipient
5786
+ });
5787
+ }
5611
5788
  let signature;
5612
5789
  try {
5613
5790
  signature = await deps.signer.signUserOpHash(prepared.value.digest);
5614
5791
  } catch (cause) {
5615
- return {
5792
+ return abandonPrepared$1(deps, prepared.value.executionId, closePaymentOnExit, "signer_rejected", {
5616
5793
  ok: false,
5617
5794
  error: signerFailure(deps.signer.source, "signUserOpHash", cause)
5618
- };
5795
+ }, onPreparedClosed);
5619
5796
  }
5620
- if (isAborted$2(signal)) return {
5797
+ if (isAborted$2(signal)) return abandonPrepared$1(deps, prepared.value.executionId, closePaymentOnExit, "cancelled", {
5621
5798
  ok: false,
5622
5799
  error: Errors.cancelled({ operation: "payments" })
5623
- };
5800
+ }, onPreparedClosed);
5624
5801
  return runIfActive(void 0, CAPXUL_OPERATIONS.payments.submitCommandExecution, () => deps.convexCall.action(deps.functions.submitPaymentCommandExecution, { input: {
5625
5802
  executionId: prepared.value.executionId,
5626
5803
  signature
@@ -5630,13 +5807,13 @@ function executePaymentLifecycle(deps, intent, signal) {
5630
5807
  return executePrepared(deps, (signerAddress) => runIfActive(signal, CAPXUL_OPERATIONS.payments.prepareLifecycleExecution, () => deps.convexCall.action(deps.functions.preparePaymentLifecycleExecution, { input: {
5631
5808
  signerAddress,
5632
5809
  intent
5633
- } })), matchesIntent(intent), signal);
5810
+ } })), matchesIntent(intent), false, void 0, signal);
5634
5811
  }
5635
- function executeOrganizationPayment(deps, input, signal) {
5812
+ function executeOrganizationPayment(deps, input, signal, onPreparedClosed) {
5636
5813
  return executePrepared(deps, (signerAddress) => runIfActive(signal, CAPXUL_OPERATIONS.organizationPayments.prepareExecution, () => deps.convexCall.action(deps.functions.prepareOrganizationPaymentExecution, { input: {
5637
5814
  ...input,
5638
5815
  signerAddress
5639
- } })), matchesIntent(input), signal);
5816
+ } })), matchesIntent(input), true, onPreparedClosed, signal);
5640
5817
  }
5641
5818
  //#endregion
5642
5819
  //#region src/surface/payment-execution.ts
@@ -5668,7 +5845,16 @@ async function signerCall(source, operation, run) {
5668
5845
  };
5669
5846
  }
5670
5847
  }
5671
- async function executePersonalPayment(deps, payment, signal, requestKey) {
5848
+ async function abandonPrepared(deps, executionId, reason, result, onPreparedClosed) {
5849
+ const abandoned = await runIfActive(void 0, CAPXUL_OPERATIONS.moneyExecution.abandonPaymentExecution, () => deps.convexCall.action(deps.functions.abandonPaymentExecution, { input: {
5850
+ executionId,
5851
+ reason
5852
+ } }));
5853
+ if (!abandoned.ok) return abandoned;
5854
+ if (abandoned.value) onPreparedClosed?.();
5855
+ return result;
5856
+ }
5857
+ async function executePersonalPayment(deps, payment, signal, requestKey, onPreparedClosed) {
5672
5858
  if (isAborted$1(signal)) return cancelled(CAPXUL_OPERATIONS.payments.pay);
5673
5859
  if (deps.signer === void 0) return mismatch("signer", "payments.pay requires a configured CapxulSigner");
5674
5860
  const session = deps.actor.authSession();
@@ -5686,18 +5872,21 @@ async function executePersonalPayment(deps, payment, signal, requestKey) {
5686
5872
  payment
5687
5873
  } }));
5688
5874
  if (!prepared.ok) return prepared;
5689
- if (prepared.value.requestKey !== resolvedRequestKey || canonicalJson(prepared.value.payment) !== canonicalJson(payment)) return mismatch("payment", "prepared Payment execution uses another request");
5690
- if (prepared.value.chainId !== deps.chainId) return mismatch("chainId", "prepared Payment execution uses another chain");
5691
- if (prepared.value.signerAddress.toLowerCase() !== signerAddress.value.toLowerCase()) return mismatch("signerAddress", "prepared Payment execution uses another signer");
5692
- if (prepared.value.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return mismatch("userOpSenderSafe", "prepared Payment execution uses another Account Safe");
5875
+ if (prepared.value.requestKey !== resolvedRequestKey || canonicalJson(prepared.value.payment) !== canonicalJson(payment)) return abandonPrepared(deps, prepared.value.executionId, "prepared_mismatch", mismatch("payment", "prepared Payment execution uses another request"), onPreparedClosed);
5876
+ if (prepared.value.chainId !== deps.chainId) return abandonPrepared(deps, prepared.value.executionId, "prepared_mismatch", mismatch("chainId", "prepared Payment execution uses another chain"), onPreparedClosed);
5877
+ if (prepared.value.signerAddress.toLowerCase() !== signerAddress.value.toLowerCase()) return abandonPrepared(deps, prepared.value.executionId, "prepared_mismatch", mismatch("signerAddress", "prepared Payment execution uses another signer"), onPreparedClosed);
5878
+ if (prepared.value.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return abandonPrepared(deps, prepared.value.executionId, "prepared_mismatch", mismatch("userOpSenderSafe", "prepared Payment execution uses another Account Safe"), onPreparedClosed);
5693
5879
  if (prepared.value.emitPaymentInitiated) await emitPaymentInitiated(deps.telemetry, {
5694
5880
  kind: prepared.value.purposeKind,
5695
- paymentId: prepared.value.paymentId
5881
+ paymentId: prepared.value.paymentId,
5882
+ commandId: prepared.value.commandId,
5883
+ executionId: prepared.value.executionId,
5884
+ recipient: prepared.value.recipientObservation
5696
5885
  });
5697
- if (isAborted$1(signal)) return cancelled(CAPXUL_OPERATIONS.payments.pay);
5886
+ if (isAborted$1(signal)) return abandonPrepared(deps, prepared.value.executionId, "cancelled", cancelled(CAPXUL_OPERATIONS.payments.pay), onPreparedClosed);
5698
5887
  const signature = await signerCall(deps.signer.source, "signUserOpHash", () => deps.signer.signUserOpHash(prepared.value.digest));
5699
- if (!signature.ok) return signature;
5700
- if (isAborted$1(signal)) return cancelled(CAPXUL_OPERATIONS.payments.pay);
5888
+ if (!signature.ok) return abandonPrepared(deps, prepared.value.executionId, "signer_rejected", signature, onPreparedClosed);
5889
+ if (isAborted$1(signal)) return abandonPrepared(deps, prepared.value.executionId, "cancelled", cancelled(CAPXUL_OPERATIONS.payments.pay), onPreparedClosed);
5701
5890
  return runIfActive(void 0, CAPXUL_OPERATIONS.payments.submitExecution, () => deps.convexCall.action(deps.functions.submitPaymentExecution, { input: {
5702
5891
  executionId: prepared.value.executionId,
5703
5892
  signature: signature.value
@@ -5925,6 +6114,30 @@ async function waitForPaymentSubmission(submission, signal, operation, onCancel
5925
6114
  });
5926
6115
  });
5927
6116
  }
6117
+ function normalizeActivityDetail(detail) {
6118
+ if (detail === null) return null;
6119
+ if (detail.kind === "payment") {
6120
+ if (detail.evidence === null) return detail;
6121
+ return {
6122
+ ...detail,
6123
+ evidence: {
6124
+ ...detail.evidence,
6125
+ inclusion: "included",
6126
+ verification: "verified",
6127
+ finality: "finalized"
6128
+ }
6129
+ };
6130
+ }
6131
+ return {
6132
+ ...detail,
6133
+ evidence: {
6134
+ ...detail.evidence,
6135
+ inclusion: "included",
6136
+ verification: "verified",
6137
+ canonicalState: "finalized"
6138
+ }
6139
+ };
6140
+ }
5928
6141
  function paymentExecutionIntent(input) {
5929
6142
  if (actorReferenceToBackend(input.actor)?.kind === "org") return {
5930
6143
  ok: false,
@@ -5937,6 +6150,7 @@ function paymentExecutionIntent(input) {
5937
6150
  value: {
5938
6151
  to: to.value,
5939
6152
  amount: input.amount,
6153
+ ...input.externalAddressAcknowledged === void 0 ? {} : { externalAddressAcknowledged: input.externalAddressAcknowledged },
5940
6154
  ...input.paymentType === void 0 ? {} : { paymentType: input.paymentType },
5941
6155
  ...input.document === void 0 ? {} : { document: input.document },
5942
6156
  ...input.timing === void 0 ? {} : { timing: input.timing },
@@ -5974,6 +6188,7 @@ function makeFinancialOpsMethods(deps) {
5974
6188
  let flight = inFlightPersonalPayments.get(sharedKey);
5975
6189
  if (flight === void 0) {
5976
6190
  const controller = new AbortController();
6191
+ const requestState = { resolved: false };
5977
6192
  const submission = executePersonalPayment({
5978
6193
  actor: deps.actor,
5979
6194
  chainId: deps.chainId,
@@ -5981,10 +6196,11 @@ function makeFinancialOpsMethods(deps) {
5981
6196
  functions: executionFns,
5982
6197
  ...deps.signer === void 0 ? {} : { signer: deps.signer },
5983
6198
  ...deps.telemetry === void 0 ? {} : { telemetry: deps.telemetry }
5984
- }, payment.value, controller.signal, requestKey.key);
6199
+ }, payment.value, controller.signal, requestKey.key, () => requestState.resolved = true);
5985
6200
  flight = {
5986
6201
  controller,
5987
6202
  promise: submission,
6203
+ requestState,
5988
6204
  waiters: 0,
5989
6205
  settled: false
5990
6206
  };
@@ -6022,7 +6238,7 @@ function makeFinancialOpsMethods(deps) {
6022
6238
  }
6023
6239
  release(false);
6024
6240
  try {
6025
- await requestKey.finish(submitted.ok);
6241
+ await requestKey.finish(submitted.ok || flight.requestState.resolved);
6026
6242
  } catch {}
6027
6243
  return mapOk(submitted, (value) => normalizePaymentTiming(value.payment));
6028
6244
  };
@@ -6062,61 +6278,34 @@ function makeFinancialOpsMethods(deps) {
6062
6278
  };
6063
6279
  }
6064
6280
  };
6281
+ const retryPayment = async (paymentId, signal) => {
6282
+ const execution = lifecycleDependencies();
6283
+ if (!execution.ok) return execution;
6284
+ try {
6285
+ const submitted = await executePaymentLifecycle(execution.value, {
6286
+ kind: "retry",
6287
+ paymentId
6288
+ }, signal);
6289
+ return submitted.ok ? {
6290
+ ok: true,
6291
+ value: submitted.value.payments.map((payment) => normalizePaymentTiming(payment))
6292
+ } : submitted;
6293
+ } catch (cause) {
6294
+ return {
6295
+ ok: false,
6296
+ error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
6297
+ };
6298
+ }
6299
+ };
6065
6300
  return {
6066
6301
  me: {
6067
6302
  get: (options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.me.get, () => deps.convexCall.query(fns.me, {})),
6068
6303
  depositInstructions: (options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.me.depositInstructions, () => deps.convexCall.query(fns.depositInstructions, {}).pipe(Effect.tap(() => Effect.promise(() => emitDepositInitiated(deps.telemetry)))))
6069
6304
  },
6070
- handles: { resolve: (handle, options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.handles.resolve, () => deps.convexCall.query(fns.resolveHandle, { handle })) },
6071
- payees: {
6072
- create: (input, options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.payees.create, () => deps.convexCall.mutation(fns.createPayee, {
6073
- label: input.label,
6074
- recipient: input.recipient,
6075
- ...input.handle === void 0 ? {} : { handle: input.handle }
6076
- })),
6077
- get: (payeeId, options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.payees.get, () => deps.convexCall.query(fns.getPayee, { payeeId })),
6078
- resolve: (recipient, options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.payees.resolve, () => deps.convexCall.query(fns.resolvePayee, { recipient }))
6079
- },
6080
6305
  targets: { resolve: async (reference, options) => {
6081
- switch (reference.kind) {
6082
- case "handle": return mapOk(await runIfActive(options?.signal, CAPXUL_OPERATIONS.targets.resolve.handle, () => deps.convexCall.query(fns.resolveHandle, { handle: reference.handle })), (target) => resolvedTargetFromResolution(reference, target));
6083
- case "email": return mapOk(await runIfActive(options?.signal, CAPXUL_OPERATIONS.targets.resolve.email, () => deps.convexCall.query(fns.resolvePayee, { recipient: reference.email })), (target) => resolvedTargetFromResolution(reference, target));
6084
- case "organization": {
6085
- const resolved = await runIfActive(options?.signal, CAPXUL_OPERATIONS.targets.resolve.organization, () => deps.convexCall.query(fns.resolveHandle, { handle: reference.handle }));
6086
- if (!resolved.ok) return {
6087
- ok: false,
6088
- error: resolved.error
6089
- };
6090
- if (resolved.value.kind !== "org") return {
6091
- ok: false,
6092
- error: Errors.invalidInput("reference", "organization handle could not be resolved")
6093
- };
6094
- return {
6095
- ok: true,
6096
- value: resolvedTargetFromResolution(reference, resolved.value)
6097
- };
6098
- }
6099
- case "payee": {
6100
- const payee = await runIfActive(options?.signal, CAPXUL_OPERATIONS.targets.resolve.payee, () => deps.convexCall.query(fns.getPayee, { payeeId: reference.id }));
6101
- if (!payee.ok) return {
6102
- ok: false,
6103
- error: payee.error
6104
- };
6105
- if (payee.value === null) return {
6106
- ok: false,
6107
- error: Errors.invalidInput("reference", "payee not found")
6108
- };
6109
- return {
6110
- ok: true,
6111
- value: resolvedTargetFromPayee(reference, payee.value)
6112
- };
6113
- }
6114
- case "party":
6115
- case "destination": return Promise.resolve({
6116
- ok: false,
6117
- error: Errors.notImplemented("targets", `resolve.${reference.kind}`)
6118
- });
6119
- }
6306
+ const recipient = normalizeTargetForBackend(reference, "reference");
6307
+ if (!recipient.ok) return recipient;
6308
+ return mapOk(await runIfActive(options?.signal, CAPXUL_OPERATIONS.recipient.resolve, () => deps.convexCall.query(fns.resolveRecipient, { recipient: recipient.value })), resolvedTargetFromResolution);
6120
6309
  } },
6121
6310
  destinations: {
6122
6311
  add: async (input, options) => {
@@ -6159,6 +6348,7 @@ function makeFinancialOpsMethods(deps) {
6159
6348
  },
6160
6349
  payments: {
6161
6350
  pay,
6351
+ retry: (paymentId, options) => retryPayment(paymentId, options?.signal),
6162
6352
  createCommitment: (input, options) => pay(input, options),
6163
6353
  claim: (paymentId, options) => runLifecycle({
6164
6354
  kind: "claim",
@@ -6201,7 +6391,7 @@ function makeFinancialOpsMethods(deps) {
6201
6391
  ...reference.kind === "payment" ? activityActorField(reference.actor) : {}
6202
6392
  },
6203
6393
  ...actor === void 0 ? {} : { actor }
6204
- }));
6394
+ }).pipe(Effect.map(normalizeActivityDetail)));
6205
6395
  },
6206
6396
  annotate: (input, options) => {
6207
6397
  if (input.actor !== void 0 && input.reference.kind === "payment" && input.reference.actor !== void 0 && !sameActor(input.actor, input.reference.actor)) return Promise.resolve({
@@ -6288,18 +6478,11 @@ function refFromTargetReference(reference, field) {
6288
6478
  email: reference.email
6289
6479
  }
6290
6480
  };
6291
- case "organization": return {
6292
- ok: true,
6293
- value: {
6294
- kind: "orgHandle",
6295
- orgHandle: reference.handle
6296
- }
6297
- };
6298
- case "payee": return {
6481
+ case "address": return {
6299
6482
  ok: true,
6300
6483
  value: {
6301
- kind: "payeeId",
6302
- payeeId: reference.id
6484
+ kind: "address",
6485
+ address: reference.address
6303
6486
  }
6304
6487
  };
6305
6488
  case "party": return {
@@ -6309,10 +6492,6 @@ function refFromTargetReference(reference, field) {
6309
6492
  partyId: reference.partyId
6310
6493
  }
6311
6494
  };
6312
- case "destination": return {
6313
- ok: false,
6314
- error: Errors.notImplemented("targets", "reference.destination")
6315
- };
6316
6495
  default: return {
6317
6496
  ok: false,
6318
6497
  error: Errors.invalidInput(field, "target must be a known TargetReference variant")
@@ -6367,39 +6546,28 @@ function targetReferenceFromBackendRef(ref) {
6367
6546
  kind: "email",
6368
6547
  email: ref.email
6369
6548
  };
6370
- case "orgHandle": return {
6371
- kind: "organization",
6372
- handle: ref.orgHandle
6373
- };
6374
- case "payeeId": return {
6375
- kind: "payee",
6376
- id: ref.payeeId
6549
+ case "address": return {
6550
+ kind: "address",
6551
+ address: ref.address
6377
6552
  };
6378
6553
  case "party": return {
6379
6554
  kind: "party",
6380
6555
  partyId: ref.partyId
6381
6556
  };
6382
- case "capxulUserId": throw Errors.notImplemented("targets", "reference.capxulUserId");
6383
6557
  }
6384
6558
  }
6385
- function resolvedTargetFromResolution(reference, resolution) {
6386
- const kind = resolution.kind === "org" ? "organization" : resolution.kind === "payee" ? "payee" : "person";
6559
+ function resolvedTargetFromResolution(resolution) {
6560
+ const kind = resolution.status === "known_party" ? resolution.partyKind === "org" ? "organization" : "person" : resolution.status === "external_address" ? "external_address" : "unresolved";
6387
6561
  return {
6388
- reference,
6562
+ reference: targetReferenceFromBackendRef(resolution.recipient),
6389
6563
  label: resolution.label,
6564
+ status: resolution.status,
6390
6565
  kind,
6391
- capabilities: {
6392
- canPay: true,
6393
- canRequest: true,
6394
- canPayout: false
6395
- }
6396
- };
6397
- }
6398
- function resolvedTargetFromPayee(reference, payee) {
6399
- return {
6400
- reference,
6401
- label: payee.label,
6402
- kind: "payee",
6566
+ safeAddress: toAddress(resolution.safeAddress),
6567
+ isCapxulAccount: resolution.isCapxulAccount,
6568
+ ...resolution.partyId === void 0 ? {} : { partyId: toPartyId(resolution.partyId) },
6569
+ ...resolution.handle === void 0 ? {} : { handle: resolution.handle },
6570
+ ...resolution.requiresAcknowledgement === void 0 ? {} : { requiresAcknowledgement: resolution.requiresAcknowledgement },
6403
6571
  capabilities: {
6404
6572
  canPay: true,
6405
6573
  canRequest: true,
@@ -6457,10 +6625,6 @@ function destinationFromBackend(destination) {
6457
6625
  };
6458
6626
  }
6459
6627
  function normalizeDestinationRefForBackend(ref, field) {
6460
- if (typeof ref === "object" && ref !== null && "kind" in ref && ref.kind === "capxulUserId") return {
6461
- ok: false,
6462
- error: Errors.notImplemented("targets", "reference.capxulUserId")
6463
- };
6464
6628
  return normalizeRefForBackend(ref, field);
6465
6629
  }
6466
6630
  function normalizeRefForBackend(ref, field) {
@@ -6488,25 +6652,11 @@ function normalizeRefForBackend(ref, field) {
6488
6652
  email: nonEmptyRefValue(ref.email, "email")
6489
6653
  }
6490
6654
  };
6491
- case "orgHandle": return {
6492
- ok: true,
6493
- value: {
6494
- kind: "orgHandle",
6495
- orgHandle: nonEmptyRefValue(ref.orgHandle, "orgHandle")
6496
- }
6497
- };
6498
- case "capxulUserId": return {
6655
+ case "address": return {
6499
6656
  ok: true,
6500
6657
  value: {
6501
- kind: "capxulUserId",
6502
- capxulUserId: nonEmptyRefValue(ref.capxulUserId, "capxulUserId")
6503
- }
6504
- };
6505
- case "payeeId": return {
6506
- ok: true,
6507
- value: {
6508
- kind: "payeeId",
6509
- payeeId: nonEmptyRefValue(ref.payeeId, "payeeId")
6658
+ kind: "address",
6659
+ address: toAddress(ref.address)
6510
6660
  }
6511
6661
  };
6512
6662
  case "party": return {
@@ -7553,7 +7703,7 @@ function makeSmartAccountMethods(deps) {
7553
7703
  }
7554
7704
  //#endregion
7555
7705
  //#region src/contract/identity.ts
7556
- const usernameAvailableQuery = makeFunctionReference(CAPXUL_FUNCTIONS["identity/queries"].usernameAvailable);
7706
+ const handleAvailableQuery = makeFunctionReference(CAPXUL_FUNCTIONS["identity/queries"].handleAvailable);
7557
7707
  //#endregion
7558
7708
  //#region src/surface/identity-deps.ts
7559
7709
  /** The single Context tag the profile atom + `identity.loadCurrent` resolve. */
@@ -7597,19 +7747,19 @@ function makeIdentityMethods(deps) {
7597
7747
  ok: false,
7598
7748
  error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.identity.completeProfile })
7599
7749
  };
7600
- if (typeof profile !== "object" || profile === null || typeof profile.displayName !== "string" || typeof profile.country !== "string" || typeof profile.username !== "string") return {
7750
+ if (typeof profile !== "object" || profile === null || typeof profile.displayName !== "string" || typeof profile.country !== "string" || typeof profile.handle !== "string") return {
7601
7751
  ok: false,
7602
7752
  error: Errors.invalidInput("profile", "invalid profile")
7603
7753
  };
7604
7754
  const displayName = profile.displayName.trim();
7605
- const username = profile.username.trim();
7755
+ const handle = profile.handle.trim();
7606
7756
  if (displayName.length === 0) return {
7607
7757
  ok: false,
7608
7758
  error: Errors.invalidInput("displayName", "must not be empty")
7609
7759
  };
7610
- if (username.length === 0) return {
7760
+ if (handle.length === 0) return {
7611
7761
  ok: false,
7612
- error: Errors.invalidInput("username", "must not be empty")
7762
+ error: Errors.invalidInput("handle", "must not be empty")
7613
7763
  };
7614
7764
  let country;
7615
7765
  try {
@@ -7630,98 +7780,259 @@ function makeIdentityMethods(deps) {
7630
7780
  email: session.email,
7631
7781
  displayName,
7632
7782
  country,
7633
- username
7783
+ handle
7634
7784
  }), options, CAPXUL_OPERATIONS.identity.completeProfile);
7635
7785
  },
7636
- async usernameAvailable(username, options) {
7786
+ async handleAvailable(handle, options) {
7637
7787
  if (options?.signal?.aborted) return {
7638
7788
  ok: false,
7639
- error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.identity.usernameAvailable })
7789
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.identity.handleAvailable })
7640
7790
  };
7641
7791
  if (convexCall === void 0) return {
7642
7792
  ok: false,
7643
- error: Errors.notImplemented("identity", "usernameAvailable")
7793
+ error: Errors.notImplemented("identity", "handleAvailable")
7644
7794
  };
7645
- return runPortEffect(convexCall.query(usernameAvailableQuery, { username }));
7795
+ return runPortEffect(convexCall.query(handleAvailableQuery, { handle }));
7646
7796
  }
7647
7797
  };
7648
7798
  }
7649
7799
  //#endregion
7650
7800
  //#region src/surface/onboarding.ts
7651
- const USERNAME_PATTERN = /^[a-z0-9_]{3,30}$/;
7652
- function makeOnboardingMethods(deps) {
7653
- return { async completePerson(input, options) {
7654
- const isCancelled = () => options?.signal?.aborted === true;
7655
- if (typeof input !== "object" || input === null || typeof input.displayName !== "string" || typeof input.country !== "string" || typeof input.username !== "string" || !USERNAME_PATTERN.test(input.username.trim())) return {
7656
- ok: false,
7657
- error: Errors.invalidInput("username", "must be 3-30 characters of a-z, 0-9, or underscore")
7801
+ function normalizeHandleInput(input) {
7802
+ if (typeof input !== "string") return {
7803
+ ok: false,
7804
+ error: Errors.invalidInput("handle", "is required")
7805
+ };
7806
+ try {
7807
+ return {
7808
+ ok: true,
7809
+ value: validateHandle(input)
7658
7810
  };
7659
- const username = input.username.trim();
7660
- const session = await deps.restoreSession(options);
7661
- if (!session.ok) return session;
7662
- if (session.value === null) return {
7811
+ } catch (error) {
7812
+ if (isCapxulError(error)) return {
7663
7813
  ok: false,
7664
- error: Errors.notAuthenticated()
7814
+ error
7665
7815
  };
7666
- const available = await deps.usernameAvailable(username, options);
7667
- if (!available.ok) return available;
7668
- if (!available.value.available) return {
7816
+ return {
7669
7817
  ok: false,
7670
- error: Errors.invalidInput("username", "username is already taken")
7818
+ error: Errors.unknown(error)
7671
7819
  };
7672
- const completed = await deps.completeProfile({
7673
- ...input,
7674
- username: available.value.normalized
7675
- }, options);
7676
- if (!completed.ok) return completed;
7677
- const refreshed = await deps.refreshIdentity(options);
7678
- if (!refreshed.ok) return refreshed;
7679
- if (isCancelled()) return {
7820
+ }
7821
+ }
7822
+ function normalizeOrganization(input) {
7823
+ if (typeof input !== "object" || input === null) return {
7824
+ ok: false,
7825
+ error: Errors.invalidInput("organization", "is required")
7826
+ };
7827
+ const name = typeof input.name === "string" ? input.name.trim() : "";
7828
+ if (name.length === 0) return {
7829
+ ok: false,
7830
+ error: Errors.invalidInput("name", "is required")
7831
+ };
7832
+ const handle = normalizeHandleInput(input.handle);
7833
+ if (!handle.ok) return handle;
7834
+ if (input.bio !== void 0 && typeof input.bio !== "string") return {
7835
+ ok: false,
7836
+ error: Errors.invalidInput("bio", "must be text")
7837
+ };
7838
+ if (input.size !== void 0 && typeof input.size !== "string") return {
7839
+ ok: false,
7840
+ error: Errors.invalidInput("size", "must be text")
7841
+ };
7842
+ let country;
7843
+ try {
7844
+ country = toCountryCode(input.country);
7845
+ } catch {
7846
+ return {
7680
7847
  ok: false,
7681
- error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completePerson })
7848
+ error: Errors.invalidInput("country", "must be an ISO country code")
7682
7849
  };
7683
- const ensured = await deps.ensureAccount();
7850
+ }
7851
+ const bio = input.bio?.trim() ?? "";
7852
+ const size = input.size?.trim() ?? "";
7853
+ return {
7854
+ ok: true,
7855
+ value: {
7856
+ name,
7857
+ handle: handle.value,
7858
+ country,
7859
+ ...bio.length === 0 ? {} : { bio },
7860
+ ...size.length === 0 ? {} : { size }
7861
+ }
7862
+ };
7863
+ }
7864
+ function isClaimedIdentityState(state) {
7865
+ return state.phase === "authenticated" && state.account.at === "claimed";
7866
+ }
7867
+ function organizationWrongState(currentState, validStates) {
7868
+ return {
7869
+ ok: false,
7870
+ error: Errors.wrongState({
7871
+ method: CAPXUL_OPERATIONS.onboarding.completeOrganization,
7872
+ currentState,
7873
+ validStates: [...validStates]
7874
+ })
7875
+ };
7876
+ }
7877
+ function requestCancelled(options) {
7878
+ return options?.signal?.aborted === true;
7879
+ }
7880
+ async function reachClaimedAccount(deps, options) {
7881
+ let state = deps.snapshotIdentity();
7882
+ if (state.phase !== "authenticated" || state.account.at === "unknown") {
7883
+ const ensured = await deps.sendIdentity({ _tag: "EnsureAccount" }, options);
7684
7884
  if (!ensured.ok) return ensured;
7685
- if (isCancelled()) return {
7686
- ok: false,
7687
- error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completePerson })
7688
- };
7689
- const lifecycle = await deps.getLifecycle();
7690
- if (!lifecycle.ok) return lifecycle;
7691
- if (isCancelled()) return {
7692
- ok: false,
7693
- error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completePerson })
7694
- };
7695
- if (lifecycle.value.status !== "ready") return {
7696
- ok: false,
7697
- error: Errors.wrongState({
7698
- method: CAPXUL_OPERATIONS.onboarding.completePerson,
7699
- currentState: lifecycle.value.status,
7700
- validStates: ["ready"]
7701
- })
7702
- };
7703
- const profile = await deps.loadProfile(options);
7704
- if (!profile.ok) return profile;
7705
- if (profile.value === null || profile.value.displayName === null || profile.value.username !== available.value.normalized) return {
7706
- ok: false,
7707
- error: Errors.wrongState({
7708
- method: CAPXUL_OPERATIONS.onboarding.completePerson,
7709
- currentState: "profile-incomplete",
7710
- validStates: ["profile-complete"]
7711
- })
7712
- };
7713
- return {
7714
- ok: true,
7715
- value: {
7716
- profile: {
7717
- ...profile.value,
7718
- displayName: profile.value.displayName,
7719
- username: profile.value.username
7720
- },
7721
- account: lifecycle.value
7722
- }
7723
- };
7724
- } };
7885
+ state = ensured.value;
7886
+ }
7887
+ if (state.phase !== "authenticated") return organizationWrongState(state.phase, ["authenticated:claimed"]);
7888
+ if (state.account.at !== "claimed") {
7889
+ const event = state.account.at === "failed" ? { _tag: "RetryAccount" } : state.account.at === "counterfactual" ? { _tag: "ClaimAccount" } : { _tag: "EnsureAccount" };
7890
+ const claimed = await deps.sendIdentity(event, options);
7891
+ if (!claimed.ok) return claimed;
7892
+ state = claimed.value;
7893
+ }
7894
+ return isClaimedIdentityState(state) ? {
7895
+ ok: true,
7896
+ value: state
7897
+ } : organizationWrongState(state.phase === "authenticated" ? state.account.at : state.phase, ["claimed"]);
7898
+ }
7899
+ async function createOrResumeOrganization(deps, state, draft, options) {
7900
+ const active = state.account.org;
7901
+ if (active?.at === "ready") return {
7902
+ ok: true,
7903
+ value: { organizationId: active.orgId }
7904
+ };
7905
+ if (active?.at === "failed" && !active.retryable) return {
7906
+ ok: false,
7907
+ error: publicIdentityFailure(active.failure)
7908
+ };
7909
+ if (active?.at === "failed" && active.orgId === null) {
7910
+ const cleared = await deps.sendIdentity({ _tag: "LeaveOrganization" }, options);
7911
+ if (!cleared.ok) return cleared;
7912
+ }
7913
+ const event = active?.at === "failed" && active.orgId !== null ? { _tag: "RetryOrganization" } : {
7914
+ _tag: "CreateOrganization",
7915
+ draft
7916
+ };
7917
+ const created = await deps.sendIdentity(event, options);
7918
+ if (!created.ok) return created;
7919
+ const final = created.value;
7920
+ const organization = isClaimedIdentityState(final) ? final.account.org : null;
7921
+ return organization?.at === "ready" ? {
7922
+ ok: true,
7923
+ value: { organizationId: organization.orgId }
7924
+ } : organizationWrongState(organization?.at ?? "organization-missing", ["ready"]);
7925
+ }
7926
+ function makeOnboardingMethods(deps) {
7927
+ return {
7928
+ async completePerson(input, options) {
7929
+ const isCancelled = () => options?.signal?.aborted === true;
7930
+ if (typeof input !== "object" || input === null || typeof input.displayName !== "string" || typeof input.country !== "string") return {
7931
+ ok: false,
7932
+ error: Errors.invalidInput("profile", "displayName and country are required")
7933
+ };
7934
+ const handle = normalizeHandleInput(input.handle);
7935
+ if (!handle.ok) return handle;
7936
+ const session = await deps.restoreSession(options);
7937
+ if (!session.ok) return session;
7938
+ if (session.value === null) return {
7939
+ ok: false,
7940
+ error: Errors.notAuthenticated()
7941
+ };
7942
+ const available = await deps.handleAvailable(handle.value, options);
7943
+ if (!available.ok) return available;
7944
+ if (!available.value.available) return {
7945
+ ok: false,
7946
+ error: Errors.invalidInput("handle", "handle is already taken")
7947
+ };
7948
+ const completed = await deps.completeProfile({
7949
+ ...input,
7950
+ handle: available.value.normalized
7951
+ }, options);
7952
+ if (!completed.ok) return completed;
7953
+ const refreshed = await deps.refreshIdentity(options);
7954
+ if (!refreshed.ok) return refreshed;
7955
+ if (isCancelled()) return {
7956
+ ok: false,
7957
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completePerson })
7958
+ };
7959
+ const ensured = await deps.ensureAccount();
7960
+ if (!ensured.ok) return ensured;
7961
+ if (isCancelled()) return {
7962
+ ok: false,
7963
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completePerson })
7964
+ };
7965
+ const lifecycle = await deps.getLifecycle();
7966
+ if (!lifecycle.ok) return lifecycle;
7967
+ if (isCancelled()) return {
7968
+ ok: false,
7969
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completePerson })
7970
+ };
7971
+ if (lifecycle.value.status !== "ready") return {
7972
+ ok: false,
7973
+ error: Errors.wrongState({
7974
+ method: CAPXUL_OPERATIONS.onboarding.completePerson,
7975
+ currentState: lifecycle.value.status,
7976
+ validStates: ["ready"]
7977
+ })
7978
+ };
7979
+ const profile = await deps.loadProfile(options);
7980
+ if (!profile.ok) return profile;
7981
+ if (profile.value === null || profile.value.displayName === null || profile.value.handle !== available.value.normalized) return {
7982
+ ok: false,
7983
+ error: Errors.wrongState({
7984
+ method: CAPXUL_OPERATIONS.onboarding.completePerson,
7985
+ currentState: "profile-incomplete",
7986
+ validStates: ["profile-complete"]
7987
+ })
7988
+ };
7989
+ return {
7990
+ ok: true,
7991
+ value: {
7992
+ profile: {
7993
+ ...profile.value,
7994
+ displayName: profile.value.displayName,
7995
+ handle: profile.value.handle
7996
+ },
7997
+ account: lifecycle.value
7998
+ }
7999
+ };
8000
+ },
8001
+ async completeOrganization(input, options) {
8002
+ const operation = CAPXUL_OPERATIONS.onboarding.completeOrganization;
8003
+ const normalized = normalizeOrganization(input);
8004
+ if (!normalized.ok) return normalized;
8005
+ const session = await deps.restoreSession(options);
8006
+ if (!session.ok) return session;
8007
+ if (session.value === null) return {
8008
+ ok: false,
8009
+ error: Errors.notAuthenticated()
8010
+ };
8011
+ const profile = await deps.loadProfile(options);
8012
+ if (!profile.ok) return profile;
8013
+ if (profile.value === null || profile.value.displayName === null || profile.value.handle === null) return {
8014
+ ok: false,
8015
+ error: Errors.wrongState({
8016
+ method: operation,
8017
+ currentState: "profile-incomplete",
8018
+ validStates: ["profile-complete"]
8019
+ })
8020
+ };
8021
+ const refreshed = await deps.refreshIdentity(options);
8022
+ if (!refreshed.ok) return refreshed;
8023
+ if (requestCancelled(options)) return {
8024
+ ok: false,
8025
+ error: Errors.cancelled({ operation })
8026
+ };
8027
+ const claimed = await reachClaimedAccount(deps, options);
8028
+ if (!claimed.ok) return claimed;
8029
+ if (requestCancelled(options)) return {
8030
+ ok: false,
8031
+ error: Errors.cancelled({ operation })
8032
+ };
8033
+ return createOrResumeOrganization(deps, claimed.value, normalized.value, options);
8034
+ }
8035
+ };
7725
8036
  }
7726
8037
  //#endregion
7727
8038
  //#region src/surface/accounts-deps.ts
@@ -8024,7 +8335,8 @@ function executionDependencies$1(input) {
8024
8335
  chainId: input.chainId,
8025
8336
  convexCall: input.convexCall,
8026
8337
  functions: moneyExecutionContract,
8027
- signer: input.signer
8338
+ signer: input.signer,
8339
+ ...input.telemetry === void 0 ? {} : { telemetry: input.telemetry }
8028
8340
  };
8029
8341
  }
8030
8342
  function makeOrganizationPaymentsMethods(deps, orgId) {
@@ -8056,16 +8368,18 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
8056
8368
  let flight = inFlightOrganizationPayments.get(flightKey);
8057
8369
  if (flight === void 0) {
8058
8370
  const controller = new AbortController();
8371
+ const requestState = { resolved: false };
8059
8372
  const submission = executeOrganizationPayment(execution, {
8060
8373
  orgId,
8061
8374
  permissionId: input.permissionId,
8062
8375
  requestKey: requestKey.key,
8063
8376
  items: input.items,
8064
8377
  ...input.lineage === void 0 ? {} : { lineage: input.lineage }
8065
- }, controller.signal);
8378
+ }, controller.signal, () => requestState.resolved = true);
8066
8379
  flight = {
8067
8380
  controller,
8068
8381
  promise: submission,
8382
+ requestState,
8069
8383
  waiters: 0,
8070
8384
  settled: false
8071
8385
  };
@@ -8103,11 +8417,29 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
8103
8417
  }
8104
8418
  release(false);
8105
8419
  try {
8106
- await requestKey.finish(result.ok);
8420
+ await requestKey.finish(result.ok || flight.requestState.resolved);
8107
8421
  } catch {}
8108
- return mapOk(result, (value) => value.payments.map((payment) => normalizePaymentTiming(payment)));
8422
+ const normalized = mapOk(result, (value) => value.payments.map((payment) => normalizePaymentTiming(payment)));
8423
+ if (!normalized.ok) return normalized;
8424
+ return normalized;
8109
8425
  };
8110
8426
  return {
8427
+ retry: async (paymentId, options) => {
8428
+ const execution = executionDependencies$1(deps);
8429
+ if (execution === null) return {
8430
+ ok: false,
8431
+ error: Errors.notImplemented("organizationPayments", "executionComposition")
8432
+ };
8433
+ const result = await executePaymentLifecycle(execution, {
8434
+ kind: "retry",
8435
+ paymentId
8436
+ }, options?.signal);
8437
+ if (!result.ok) return result;
8438
+ return {
8439
+ ok: true,
8440
+ value: result.value.payments.map((payment) => normalizePaymentTiming(payment))
8441
+ };
8442
+ },
8111
8443
  pay: async (input, options) => {
8112
8444
  const { permissionId, requestKey: providedRequestKey, lineage, ...item } = input;
8113
8445
  const result = await execute({
@@ -8239,6 +8571,7 @@ function makePayrollMethods(deps, orgId) {
8239
8571
  input
8240
8572
  }, input.requestKey);
8241
8573
  let authorized;
8574
+ let preparedClosed = false;
8242
8575
  const submitted = await executePrepared(execution, async (signerAddress) => {
8243
8576
  const prepared = await runIfActive(signal, AUTHORIZE_RUN, () => deps.convexCall.action(payrollContract.authorizeRun, { input: {
8244
8577
  orgId,
@@ -8260,9 +8593,9 @@ function makePayrollMethods(deps, orgId) {
8260
8593
  requestKey: requestKey.key,
8261
8594
  runId: authorized.id,
8262
8595
  items: input.items
8263
- })(request), signal);
8596
+ })(request), true, () => preparedClosed = true, signal);
8264
8597
  try {
8265
- await requestKey.finish(submitted.ok);
8598
+ await requestKey.finish(submitted.ok || preparedClosed);
8266
8599
  } catch {}
8267
8600
  if (!submitted.ok) return submitted;
8268
8601
  return authorized === void 0 ? {
@@ -8883,7 +9216,8 @@ function makeOrgMethods(deps) {
8883
9216
  ...deps.requestKeyScope === void 0 ? {} : { requestKeyScope: deps.requestKeyScope },
8884
9217
  ...deps.actor === void 0 ? {} : { actor: deps.actor },
8885
9218
  ...deps.chainId === void 0 ? {} : { chainId: Number(deps.chainId) },
8886
- ...deps.signer === void 0 ? {} : { signer: deps.signer }
9219
+ ...deps.signer === void 0 ? {} : { signer: deps.signer },
9220
+ ...deps.telemetry === void 0 ? {} : { telemetry: deps.telemetry }
8887
9221
  }, String(orgId)),
8888
9222
  payroll: convexCall === void 0 ? makeUnavailablePayrollMethods() : makePayrollMethods({
8889
9223
  convexCall,
@@ -8910,7 +9244,8 @@ function makeNotImplementedPermissionMethods() {
8910
9244
  function makeNotImplementedOrganizationPaymentsMethods() {
8911
9245
  return {
8912
9246
  pay: organizationPaymentExecutionUnavailable,
8913
- payBatch: organizationPaymentExecutionUnavailable
9247
+ payBatch: organizationPaymentExecutionUnavailable,
9248
+ retry: organizationPaymentExecutionUnavailable
8914
9249
  };
8915
9250
  }
8916
9251
  const orgMeUnavailable = () => Promise.resolve({
@@ -9245,11 +9580,13 @@ function assembleCapxulClient(input) {
9245
9580
  const onboarding = makeOnboardingMethods({
9246
9581
  restoreSession: auth.getSession,
9247
9582
  refreshIdentity: (options) => runCapxulEffect(askIdentity(actor, { _tag: "ReadSession" }, options).pipe(Effect.asVoid), options, CAPXUL_OPERATIONS.identity.readSession, effectRunner.runPromise),
9248
- usernameAvailable: identity.usernameAvailable,
9583
+ handleAvailable: identity.handleAvailable,
9249
9584
  completeProfile: identity.completeProfile,
9250
9585
  loadProfile: identity.loadCurrent,
9251
9586
  ensureAccount: account._internal.ensureReady,
9252
- getLifecycle: account.getLifecycle
9587
+ getLifecycle: account.getLifecycle,
9588
+ snapshotIdentity: actor.snapshot,
9589
+ sendIdentity: (event, options) => runCapxulEffect(askIdentity(actor, event, options), options, CAPXUL_OPERATIONS._internal.identity.send, effectRunner.runPromise)
9253
9590
  });
9254
9591
  const system = makeSystemMethods({ convexCall: input.ports.convexCall });
9255
9592
  const media = makeMediaMethods({ convexCall: input.ports.convexCall });
@@ -9308,7 +9645,7 @@ function assembleCapxulClient(input) {
9308
9645
  }
9309
9646
  },
9310
9647
  async completeProfile(profile, controls) {
9311
- if (typeof profile !== "object" || profile === null || typeof profile.displayName !== "string" || typeof profile.country !== "string" || profile.username !== void 0 && typeof profile.username !== "string") return {
9648
+ if (typeof profile !== "object" || profile === null || typeof profile.displayName !== "string" || typeof profile.country !== "string" || typeof profile.handle !== "string") return {
9312
9649
  ok: false,
9313
9650
  reason: "INVALID_INPUT"
9314
9651
  };
@@ -9326,8 +9663,8 @@ function assembleCapxulClient(input) {
9326
9663
  reason: "INVALID_INPUT"
9327
9664
  };
9328
9665
  }
9329
- const username = profile.username?.trim();
9330
- if (profile.username !== void 0 && username?.length === 0) return {
9666
+ const handle = profile.handle.trim();
9667
+ if (handle.length === 0) return {
9331
9668
  ok: false,
9332
9669
  reason: "INVALID_INPUT"
9333
9670
  };
@@ -9341,7 +9678,7 @@ function assembleCapxulClient(input) {
9341
9678
  email: session.email,
9342
9679
  displayName,
9343
9680
  country,
9344
- ...username === void 0 ? {} : { username }
9681
+ handle
9345
9682
  }), controls, CAPXUL_OPERATIONS.identity.completeProfile, effectRunner.runPromise);
9346
9683
  return result.ok ? { ok: true } : {
9347
9684
  ok: false,
@@ -9360,8 +9697,6 @@ function assembleCapxulClient(input) {
9360
9697
  accounts,
9361
9698
  currentUser,
9362
9699
  me: financialOps.me,
9363
- handles: financialOps.handles,
9364
- payees: financialOps.payees,
9365
9700
  targets: financialOps.targets,
9366
9701
  destinations: financialOps.destinations,
9367
9702
  payments: financialOps.payments,
@@ -9380,6 +9715,20 @@ function assembleCapxulClient(input) {
9380
9715
  accounts: { fund: accounts.fund },
9381
9716
  organizationSetup: { getProofReceipt: (orgId) => runPortEffect(input.ports.convexCall.query(organizationSetupProofReceiptQuery, { orgId })) },
9382
9717
  telemetry: input.ports.telemetry,
9718
+ captureExternalAddressAcknowledged: (address, organizationId) => {
9719
+ const telemetry = input.ports.telemetry;
9720
+ if (telemetry === void 0) return;
9721
+ Effect.runPromise(Effect.suspend(() => telemetry.emit({
9722
+ name: "quick_pay_external_address_acknowledged",
9723
+ props: {
9724
+ recipient_locator_kind: "address",
9725
+ recipient_resolution_status: "external_address",
9726
+ recipient_address: address,
9727
+ external_address_acknowledged: true,
9728
+ ...organizationId === void 0 ? {} : { organization_id: organizationId }
9729
+ }
9730
+ })).pipe(Effect.catchCause(() => Effect.void)));
9731
+ },
9383
9732
  close: stopActor
9384
9733
  }
9385
9734
  }, observation.failureObservation, observation.hostObservationSnapshot);