@conto_finance/sdk 0.6.2-beta.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -40,6 +40,48 @@ interface PurchaseGroceryItem {
40
40
  interface PurchaseGroceryList {
41
41
  items: PurchaseGroceryItem[];
42
42
  }
43
+ /** A grocery list purchase's items, delivery and fees at the store. */
44
+ interface PurchaseGrocery {
45
+ /** Each list item that has settled so far, by its position in the list. */
46
+ items: ({
47
+ index: number;
48
+ label: string;
49
+ status: 'added';
50
+ /** The store's product name. */
51
+ name: string;
52
+ quantity: number;
53
+ /** The line's price for that quantity. */
54
+ price: PurchaseMoney;
55
+ } | {
56
+ index: number;
57
+ label: string;
58
+ status: 'skipped';
59
+ reason: 'no_match' | 'size_unavailable' | 'brand_unavailable' | 'excluded';
60
+ })[];
61
+ /** The delivery time chosen at checkout. */
62
+ delivery: {
63
+ title: string;
64
+ window: string;
65
+ kind: 'priority' | 'standard' | 'scheduled' | 'other';
66
+ windowStart: string | null;
67
+ windowEnd: string | null;
68
+ price: PurchaseMoney | null;
69
+ } | null;
70
+ /** The store checkout's totals and fees, as it showed them. */
71
+ summary: {
72
+ itemsSubtotal: PurchaseMoney | null;
73
+ deliveryFee: PurchaseMoney | null;
74
+ serviceFee: PurchaseMoney | null;
75
+ bagFee: PurchaseMoney | null;
76
+ tax: PurchaseMoney | null;
77
+ tip: PurchaseMoney | null;
78
+ otherFees: {
79
+ label: string;
80
+ amount: PurchaseMoney;
81
+ }[];
82
+ total: PurchaseMoney | null;
83
+ } | null;
84
+ }
43
85
  interface PurchaseRequest {
44
86
  url: string;
45
87
  task?: string;
@@ -66,6 +108,15 @@ interface PurchaseAction {
66
108
  maximum: PurchaseMoney;
67
109
  maxCost: PurchaseMoney;
68
110
  };
111
+ /**
112
+ * For a merchant_signin you answer: the store sign-in step. Answer `email`
113
+ * with `{ email }` (or `{ email, createAccount: true, agreedToStoreTerms: true }`)
114
+ * and `code` with `{ code }`, the 6-digit code the store sent the buyer.
115
+ */
116
+ signin?: {
117
+ store: 'instacart';
118
+ step: 'email' | 'code';
119
+ };
69
120
  /**
70
121
  * For buyer, cardholder and reviewer actions: the Conto page that completes
71
122
  * it. It works only inside a hosted buyer session or the dashboard, so it is
@@ -119,7 +170,15 @@ interface Purchase {
119
170
  result: {
120
171
  outcome: 'merchant_confirmed' | 'checkout_reported' | 'credential_unused' | 'not_completed' | 'denied' | 'cancelled';
121
172
  merchantReference: string | null;
173
+ /** merchant_confirmed: the store's order number, when shown. */
174
+ orderNumber?: string | null;
175
+ /** merchant_confirmed: the store's receipt or order page, when shown. */
176
+ receiptUrl?: string | null;
177
+ /** merchant_confirmed: the amount the store charged, when shown. */
178
+ charged?: PurchaseMoney | null;
122
179
  } | null;
180
+ /** Present for a grocery list purchase. */
181
+ grocery?: PurchaseGrocery;
123
182
  paymentEvidence: PurchaseEvidence;
124
183
  progress: {
125
184
  steps: number;
@@ -190,8 +249,8 @@ interface CreatePurchaseInput {
190
249
  delegationId: string;
191
250
  };
192
251
  /**
193
- * The buyer's saved delivery details answer the store's delivery form when
194
- * the buyer has them. Leave out to use them when present, pass the buyer id
252
+ * New purchases snapshot saved delivery details at creation for the store's
253
+ * delivery form. Leave out to use them when present, pass the buyer id
195
254
  * to require them, or null to never use them.
196
255
  */
197
256
  buyerProfileId?: string | null;
@@ -1294,6 +1353,29 @@ interface RefreshBalanceResult {
1294
1353
  balances: WalletChainBalanceSnapshot[];
1295
1354
  lastRefreshed: string;
1296
1355
  }
1356
+ /** A one-time message for a self-custody wallet's address to sign. */
1357
+ interface WalletOwnershipChallenge {
1358
+ walletId: string;
1359
+ address: string;
1360
+ chainType: ChainType;
1361
+ chainId: string;
1362
+ /** Sign exactly this text: EIP-191 personal_sign on EVM, Ed25519 on Solana. */
1363
+ message: string;
1364
+ expiresAt: string;
1365
+ /** When the wallet was last proven, or null if never. */
1366
+ provenAt: string | null;
1367
+ }
1368
+ interface ProveWalletOwnershipInput {
1369
+ /** The challenge message, unchanged. */
1370
+ message: string;
1371
+ /** EVM: 0x-prefixed hex signature. Solana: base58 or base64 signature. */
1372
+ signature: string;
1373
+ }
1374
+ interface WalletOwnershipProof {
1375
+ walletId: string;
1376
+ proven: true;
1377
+ provenAt: string;
1378
+ }
1297
1379
  interface PolicyRule {
1298
1380
  id: string;
1299
1381
  policyId: string;
@@ -1583,6 +1665,13 @@ declare class WalletsClient {
1583
1665
  provision(walletId: string): Promise<ProvisionWalletResult>;
1584
1666
  /** Refresh a wallet's balance from the chain */
1585
1667
  refreshBalance(walletId: string): Promise<RefreshBalanceResult>;
1668
+ /**
1669
+ * Get a one-time message for a self-custody wallet's address to sign. It
1670
+ * expires after 10 minutes and replaces any earlier challenge.
1671
+ */
1672
+ createOwnershipChallenge(walletId: string): Promise<WalletOwnershipChallenge>;
1673
+ /** Prove your organization controls a self-custody wallet's address. */
1674
+ proveOwnership(walletId: string, input: ProveWalletOwnershipInput): Promise<WalletOwnershipProof>;
1586
1675
  }
1587
1676
  declare class PoliciesClient {
1588
1677
  private client;
@@ -2554,6 +2643,33 @@ interface WaitForCheckoutApprovalOptions {
2554
2643
  signal?: AbortSignal;
2555
2644
  }
2556
2645
 
2646
+ /**
2647
+ * The Link card request is waiting for the person. Conto has already approved
2648
+ * the purchase, and Link has created the request.
2649
+ */
2650
+ interface LinkApprovalEvent {
2651
+ /** The checkpoint Conto approved. */
2652
+ checkpoint: CheckoutCheckpoint;
2653
+ /** The Link spend request id, such as lsrq_... */
2654
+ linkRequestId: string;
2655
+ /**
2656
+ * The Stripe Link page where the person can approve on the web while signed
2657
+ * in to Link, so they do not need the Link app. Only an HTTPS link.com address
2658
+ * is passed. Absent when Link gave none or it did not pass that check. The
2659
+ * person can still approve in the Link app.
2660
+ */
2661
+ approvalUrl?: string;
2662
+ /** When Link stops accepting approval, as an ISO 8601 time, when Link reports it. */
2663
+ approvalExpiresAt?: string;
2664
+ }
2665
+ /**
2666
+ * Called once when the Link card request is waiting for the person, after
2667
+ * Conto approved the purchase and before the SDK starts waiting. Show
2668
+ * approvalUrl to the person. The SDK does not wait for it to finish, and an
2669
+ * error it throws or rejects with does not affect the purchase. A retry that
2670
+ * resumes a waiting request calls it again with the same URL.
2671
+ */
2672
+ type LinkApprovalCallback = (event: LinkApprovalEvent) => void | Promise<void>;
2557
2673
  /**
2558
2674
  * A Link card for one purchase: the checkpoint begin input plus the Link
2559
2675
  * wallet that runs in your environment. The checkout method is always LINK.
@@ -2565,6 +2681,8 @@ interface GetLinkCardInput extends Omit<BeginCheckoutCheckpointInput, 'checkoutM
2565
2681
  ownerApprovalTimeoutMs?: number;
2566
2682
  /** How long to wait for the person to approve in Link. Defaults to 10 minutes. */
2567
2683
  linkApprovalTimeoutMs?: number;
2684
+ /** Called once with the Link approval page when the person needs to approve in Link. */
2685
+ onLinkApproval?: LinkApprovalCallback;
2568
2686
  signal?: AbortSignal;
2569
2687
  }
2570
2688
  /** A new Link card for a changed final total. */
@@ -2578,6 +2696,8 @@ interface ReplaceLinkCardInput {
2578
2696
  totals?: CommerceTotalInput[];
2579
2697
  ownerApprovalTimeoutMs?: number;
2580
2698
  linkApprovalTimeoutMs?: number;
2699
+ /** Called once with the Link approval page when the person needs to approve in Link. */
2700
+ onLinkApproval?: LinkApprovalCallback;
2581
2701
  signal?: AbortSignal;
2582
2702
  }
2583
2703
  interface LinkCardResult {
@@ -3291,6 +3411,13 @@ declare class CheckoutApprovalTimeoutError extends ContoError {
3291
3411
  declare class LinkCardError extends ContoError {
3292
3412
  readonly checkpoint: CheckoutCheckpoint;
3293
3413
  readonly linkRequestId?: string;
3414
+ /**
3415
+ * The Stripe Link page where the person could approve the request, set when
3416
+ * the SDK stopped while the request was waiting for them. It works only while
3417
+ * the request is still open in Link. When holdReleased is true, Conto has
3418
+ * already cancelled the request.
3419
+ */
3420
+ readonly approvalUrl?: string;
3294
3421
  /** True when Conto cancelled the checkpoint and released the held spend. */
3295
3422
  readonly holdReleased: boolean;
3296
3423
  constructor(input: {
@@ -3298,6 +3425,7 @@ declare class LinkCardError extends ContoError {
3298
3425
  code: string;
3299
3426
  checkpoint: CheckoutCheckpoint;
3300
3427
  linkRequestId?: string;
3428
+ approvalUrl?: string;
3301
3429
  holdReleased: boolean;
3302
3430
  retryGuidance?: string;
3303
3431
  });
@@ -3765,7 +3893,9 @@ declare class CheckoutClient {
3765
3893
  * 1. Conto runs checkpoint 1 and holds the spend. When a rule requires the
3766
3894
  * owner's approval, this waits for it.
3767
3895
  * 2. Only then does the wallet ask Link for a card for exactly the approved
3768
- * amount at this merchant. The person approves it in their Link app.
3896
+ * amount at this merchant. The person approves it in Link. Pass
3897
+ * onLinkApproval to get Link's approval page, so they can approve on the
3898
+ * web without the Link app.
3769
3899
  * 3. The card is returned. It never reaches Conto.
3770
3900
  *
3771
3901
  * Then fill in the card, call confirm(result.checkpoint, { amountMinor,
@@ -3790,4 +3920,5 @@ declare class CheckoutClient {
3790
3920
  replaceLinkCard(previous: LinkCardResult, input: ReplaceLinkCardInput): Promise<LinkCardResult>;
3791
3921
  }
3792
3922
 
3793
- export { type AdminExternalCardOverlayEnforcement, AdminPurchasingClient, type Agent, type AgentCheckoutAction, type AgentCheckoutActionKind, type AgentExternalCard, type AgentSetupResult, type AgentStatus, type AgentType, type AgentWalletLink, type ApprovedExternalCardExecution, type AssignExternalCardInput, type AssignedPolicy, type AuthorizeCheckoutActionResult, type BeginCheckoutCheckpointInput, type BeginCommerceExecutionInput, type BrowserActionClaimResult, type BrowserActionDispatchObservationInput, BrowserActionFinalizationPendingError, type BrowserActionFinalizeResult, type BrowserCheckoutAction, type BrowserCheckoutTargetResolver, type BrowserCheckoutTargetSnapshot, type BrowserCheckoutTargetVerificationCode, BrowserCheckoutTargetVerificationError, type CancellationOutcome, type CanonicalBrowserCheckoutTargetSnapshot, CardsClient, type ChainType, type CheckoutActionAuthorization, CheckoutApprovalDeniedError, CheckoutApprovalExpiredError, CheckoutApprovalPendingError, CheckoutApprovalTimeoutError, type CheckoutCheckpoint, type CheckoutCheckpointApproval, CheckoutCheckpointClosedError, type CheckoutCheckpointMethod, type CheckoutCheckpointNextAction, type CheckoutCheckpointStage, CheckoutClient, type CheckoutOutcome, type CheckoutPaymentReference, type CommerceCheckoutMethod, type CommerceContextRequirement, type CommerceExecution, type CommerceExecutionAdapterKind, type CommerceExecutionArtifactKind, type CommerceExecutionChannel, type CommerceExecutionConstraint, type CommerceExecutionConstraintCoverage, type CommerceExecutionConstraintCoverageLevel, type CommerceExecutionDeliveryMode, type CommerceExecutionEvidence, type CommerceExecutionProvider, type CommerceExecutionResult, type CommerceExecutionSourceKind, type CommerceExecutionStatus, type CommerceFactConfidence, type CommerceFactProvenanceInput, type CommerceFactSource, type CommerceFulfillmentInput, type CommerceLineItemInput, type CommerceProposalFactKey, type CommerceProposalMissingFact, type CommerceProposalResolution, type CommerceProposalState, type CommerceSettlementRail, type CommerceTotalInput, type CommerceTotalType, type ComparePolicyVersionsResponse, type ConfirmCheckoutCheckpointInput, type ConnectedCardBrief, type ConnectedCardCredential, type ConnectedCardDrawInput, type ConnectedCardDrawMerchant, type ConnectedCardDrawResult, type ConnectedCardDrawable, type ConnectedCardListResult, type ConnectedCardMandate, type ConnectedCardMandateMerchant, type ConnectedCardOutcomeReport, type ConnectedCardOutcomeReportResult, type ConnectedCardReference, ConnectedCardsClient, Conto, ContoAdmin, type ContoAdminConfig, ContoAdminError, type ContoConfig, ContoError, type ContoRequestOptions, type ControlledExternalCardPaymentResult, ControlledExternalCardPaymentTool, type CreateAgentInput, type CreatePolicyInput, type CreatePolicyRuleInput, type CreatePurchaseInput, type CreateSdkKeyInput, type CreateSdkKeyResult, type CreateWalletInput, type CustodyType, type CustomerCustodyMode, type CustomerWalletControlModel, type CustomerWalletKeyAccess, type DelegationType, type ExecuteCommerceExecutionResult, type ExternalCard, type ExternalCardApprovalInput, type ExternalCardApprovalResult, type ExternalCardConfirmationInput, ExternalCardConfirmationPendingError, type ExternalCardConfirmationResult, type ExternalCardExecutionClaimResult, type ExternalCardExecutionResult, type ExternalCardExecutor, type ExternalCardOverlayEnforcement, type ExternalCardRequestStatusResult, type ExternalWalletApprovalInput, type ExternalWalletApprovalResult, type ExternalWalletConfirmationInput, type ExternalWalletConfirmationResult, type FreezeAgentInput, type GetLinkCardInput, Conto as Giro, type ContoConfig as GiroConfig, ContoError as GiroError, type GuardCheckoutResult, type GuardedBrowserDispatchResult, type GuardedCheckoutInput, LinkCardCredential, LinkCardDeniedError, LinkCardError, LinkCardExpiredError, type LinkCardResult, LinkCardTimeoutError, LinkWallet, type LinkWalletInput, LinkWalletUnavailableError, type ListAgentsParams, type ListAgentsResponse, type ListPoliciesParams, type ListPoliciesResponse, type ListPolicyVersionsResponse, type ListWalletsParams, type ListWalletsResponse, type MppBudgetResult, type MppPreAuthorizeInput, type MppPreAuthorizeResult, type MppRecordInput, type MppRecordResult, type NormalizeCommerceProposalInput, type OrganizationMember, OrganizationPurchasesClient, OrganizationRecurringPurchasesClient, type PaginatedResponse, type PaginationParams, type PauseExternalCardAssignmentResult, type PaymentExecuteResult, type PaymentRequestInput, type PaymentRequestResult, type PaymentStatusResult, type Policy, type PolicyRule, type PolicyType, type PolicyVersionChangeType, type PolicyVersionDetail, type PolicyVersionDiff, type PolicyVersionFieldChange, type PolicyVersionSnapshot, type PolicyVersionSnapshotRule, type PolicyVersionSummary, type PrivilegedBrowserCheckoutDriver, type ProtocolBudgetResult, type ProtocolPreAuthorizeResult, type ProtocolRecordGrant, type ProtocolRecordGrantResult, type ProtocolServiceSummary, type ProtocolServicesResult, type ProvisionWalletResult, type Purchase, type PurchaseAction, type PurchaseActionAuthority, type PurchaseActionKind, type PurchaseAllowance, type PurchaseBuyer, type PurchaseBuyerCompanyCard, type PurchaseBuyerCompanyCardLimits, type PurchaseBuyerKitchenContext, type PurchaseCompanyCard, type PurchaseDelegation, type PurchaseEvent, type PurchaseEventPage, type PurchaseEvidence, type PurchaseGroceryItem, type PurchaseGroceryList, type PurchaseHostedLink, type PurchaseItem, type PurchaseKitchenContext, type PurchaseKitchenInventoryItem, type PurchaseKitchenListItem, type PurchaseKitchenPreferences, type PurchaseKitchenRecipe, type PurchaseKitchenUsual, type PurchaseList, type PurchaseMoney, type PurchasePaymentMethod, type PurchasePhase, type PurchaseRequest, type PurchaseResponseAck, type PurchaseStatus, PurchasesClient, type PurchasingCapabilities, type PurchasingSettings, type RecurringPurchase, type RecurringPurchaseCycleResult, type RecurringPurchaseCycleStatus, RecurringPurchasesClient, type RefreshBalanceResult, type RegisterExternalCardInput, type ReplaceLinkCardInput, type ReportCheckoutOutcomeInput, type RollbackPolicyVersionResponse, type RuleAction, type RuleOperator, type RuleType, type RunGuardedCheckoutResult, type SdkKey, type SdkKeyType, type SetupCapabilityState, type SetupCardDiagnostics, type SetupDiagnosticAction, type SetupDiagnosticIssue, type SetupDiagnosticIssueCode, type SetupDiagnostics, type SetupWalletDiagnostics, type TestCardCredential, type TestCardDrawResult, type TestCardDrawable, type TestCardListResult, type TestCardReceipt, TestCardsClient, type TestCheckoutInput, type TestCheckoutResult, type TestMerchant, type TestMerchantProduct, type UnfreezeAgentInput, type UpdateAgentInput, type UpdateExternalCardAssignmentInput, type UpdatePolicyInput, type UpdatePolicyRuleInput, type UpdateWalletInput, type VerifiedBrowserCheckoutTarget, type WaitForCheckoutApprovalOptions, type Wallet, type WalletChainBalanceSnapshot, type WalletStatus, type WalletType, type WatchPurchaseOptions, type X402Authorization, type X402BudgetResult, type X402PayInput, type X402PayResult, type X402PaymentRequirements, type X402PreAuthorizeInput, type X402PreAuthorizeResult, type X402RecordInput, type X402RecordResult, canonicalizeBrowserCheckoutTarget, createVerifiedBrowserCheckoutDriver, Conto as default, fingerprintBrowserCheckoutTarget, isFinalPurchaseStatus, parseServerSentEvents, verifyPurchaseWebhook };
3923
+ export { AdminPurchasingClient, BrowserActionFinalizationPendingError, BrowserCheckoutTargetVerificationError, CardsClient, CheckoutApprovalDeniedError, CheckoutApprovalExpiredError, CheckoutApprovalPendingError, CheckoutApprovalTimeoutError, CheckoutCheckpointClosedError, CheckoutClient, ConnectedCardsClient, Conto, ContoAdmin, ContoAdminError, ContoError, ControlledExternalCardPaymentTool, ExternalCardConfirmationPendingError, Conto as Giro, ContoError as GiroError, LinkCardCredential, LinkCardDeniedError, LinkCardError, LinkCardExpiredError, LinkCardTimeoutError, LinkWallet, LinkWalletUnavailableError, OrganizationPurchasesClient, OrganizationRecurringPurchasesClient, PurchasesClient, RecurringPurchasesClient, TestCardsClient, canonicalizeBrowserCheckoutTarget, createVerifiedBrowserCheckoutDriver, Conto as default, fingerprintBrowserCheckoutTarget, isFinalPurchaseStatus, parseServerSentEvents, verifyPurchaseWebhook };
3924
+ export type { AdminExternalCardOverlayEnforcement, Agent, AgentCheckoutAction, AgentCheckoutActionKind, AgentExternalCard, AgentSetupResult, AgentStatus, AgentType, AgentWalletLink, ApprovedExternalCardExecution, AssignExternalCardInput, AssignedPolicy, AuthorizeCheckoutActionResult, BeginCheckoutCheckpointInput, BeginCommerceExecutionInput, BrowserActionClaimResult, BrowserActionDispatchObservationInput, BrowserActionFinalizeResult, BrowserCheckoutAction, BrowserCheckoutTargetResolver, BrowserCheckoutTargetSnapshot, BrowserCheckoutTargetVerificationCode, CancellationOutcome, CanonicalBrowserCheckoutTargetSnapshot, ChainType, CheckoutActionAuthorization, CheckoutCheckpoint, CheckoutCheckpointApproval, CheckoutCheckpointMethod, CheckoutCheckpointNextAction, CheckoutCheckpointStage, CheckoutOutcome, CheckoutPaymentReference, CommerceCheckoutMethod, CommerceContextRequirement, CommerceExecution, CommerceExecutionAdapterKind, CommerceExecutionArtifactKind, CommerceExecutionChannel, CommerceExecutionConstraint, CommerceExecutionConstraintCoverage, CommerceExecutionConstraintCoverageLevel, CommerceExecutionDeliveryMode, CommerceExecutionEvidence, CommerceExecutionProvider, CommerceExecutionResult, CommerceExecutionSourceKind, CommerceExecutionStatus, CommerceFactConfidence, CommerceFactProvenanceInput, CommerceFactSource, CommerceFulfillmentInput, CommerceLineItemInput, CommerceProposalFactKey, CommerceProposalMissingFact, CommerceProposalResolution, CommerceProposalState, CommerceSettlementRail, CommerceTotalInput, CommerceTotalType, ComparePolicyVersionsResponse, ConfirmCheckoutCheckpointInput, ConnectedCardBrief, ConnectedCardCredential, ConnectedCardDrawInput, ConnectedCardDrawMerchant, ConnectedCardDrawResult, ConnectedCardDrawable, ConnectedCardListResult, ConnectedCardMandate, ConnectedCardMandateMerchant, ConnectedCardOutcomeReport, ConnectedCardOutcomeReportResult, ConnectedCardReference, ContoAdminConfig, ContoConfig, ContoRequestOptions, ControlledExternalCardPaymentResult, CreateAgentInput, CreatePolicyInput, CreatePolicyRuleInput, CreatePurchaseInput, CreateSdkKeyInput, CreateSdkKeyResult, CreateWalletInput, CustodyType, CustomerCustodyMode, CustomerWalletControlModel, CustomerWalletKeyAccess, DelegationType, ExecuteCommerceExecutionResult, ExternalCard, ExternalCardApprovalInput, ExternalCardApprovalResult, ExternalCardConfirmationInput, ExternalCardConfirmationResult, ExternalCardExecutionClaimResult, ExternalCardExecutionResult, ExternalCardExecutor, ExternalCardOverlayEnforcement, ExternalCardRequestStatusResult, ExternalWalletApprovalInput, ExternalWalletApprovalResult, ExternalWalletConfirmationInput, ExternalWalletConfirmationResult, FreezeAgentInput, GetLinkCardInput, ContoConfig as GiroConfig, GuardCheckoutResult, GuardedBrowserDispatchResult, GuardedCheckoutInput, LinkApprovalCallback, LinkApprovalEvent, LinkCardResult, LinkWalletInput, ListAgentsParams, ListAgentsResponse, ListPoliciesParams, ListPoliciesResponse, ListPolicyVersionsResponse, ListWalletsParams, ListWalletsResponse, MppBudgetResult, MppPreAuthorizeInput, MppPreAuthorizeResult, MppRecordInput, MppRecordResult, NormalizeCommerceProposalInput, OrganizationMember, PaginatedResponse, PaginationParams, PauseExternalCardAssignmentResult, PaymentExecuteResult, PaymentRequestInput, PaymentRequestResult, PaymentStatusResult, Policy, PolicyRule, PolicyType, PolicyVersionChangeType, PolicyVersionDetail, PolicyVersionDiff, PolicyVersionFieldChange, PolicyVersionSnapshot, PolicyVersionSnapshotRule, PolicyVersionSummary, PrivilegedBrowserCheckoutDriver, ProtocolBudgetResult, ProtocolPreAuthorizeResult, ProtocolRecordGrant, ProtocolRecordGrantResult, ProtocolServiceSummary, ProtocolServicesResult, ProveWalletOwnershipInput, ProvisionWalletResult, Purchase, PurchaseAction, PurchaseActionAuthority, PurchaseActionKind, PurchaseAllowance, PurchaseBuyer, PurchaseBuyerCompanyCard, PurchaseBuyerCompanyCardLimits, PurchaseBuyerKitchenContext, PurchaseCompanyCard, PurchaseDelegation, PurchaseEvent, PurchaseEventPage, PurchaseEvidence, PurchaseGrocery, PurchaseGroceryItem, PurchaseGroceryList, PurchaseHostedLink, PurchaseItem, PurchaseKitchenContext, PurchaseKitchenInventoryItem, PurchaseKitchenListItem, PurchaseKitchenPreferences, PurchaseKitchenRecipe, PurchaseKitchenUsual, PurchaseList, PurchaseMoney, PurchasePaymentMethod, PurchasePhase, PurchaseRequest, PurchaseResponseAck, PurchaseStatus, PurchasingCapabilities, PurchasingSettings, RecurringPurchase, RecurringPurchaseCycleResult, RecurringPurchaseCycleStatus, RefreshBalanceResult, RegisterExternalCardInput, ReplaceLinkCardInput, ReportCheckoutOutcomeInput, RollbackPolicyVersionResponse, RuleAction, RuleOperator, RuleType, RunGuardedCheckoutResult, SdkKey, SdkKeyType, SetupCapabilityState, SetupCardDiagnostics, SetupDiagnosticAction, SetupDiagnosticIssue, SetupDiagnosticIssueCode, SetupDiagnostics, SetupWalletDiagnostics, TestCardCredential, TestCardDrawResult, TestCardDrawable, TestCardListResult, TestCardReceipt, TestCheckoutInput, TestCheckoutResult, TestMerchant, TestMerchantProduct, UnfreezeAgentInput, UpdateAgentInput, UpdateExternalCardAssignmentInput, UpdatePolicyInput, UpdatePolicyRuleInput, UpdateWalletInput, VerifiedBrowserCheckoutTarget, WaitForCheckoutApprovalOptions, Wallet, WalletChainBalanceSnapshot, WalletOwnershipChallenge, WalletOwnershipProof, WalletStatus, WalletType, WatchPurchaseOptions, X402Authorization, X402BudgetResult, X402PayInput, X402PayResult, X402PaymentRequirements, X402PreAuthorizeInput, X402PreAuthorizeResult, X402RecordInput, X402RecordResult };
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ var require_package = __commonJS({
47
47
  "package.json"(exports2, module2) {
48
48
  module2.exports = {
49
49
  name: "@conto_finance/sdk",
50
- version: "0.6.2-beta.1",
50
+ version: "0.7.1",
51
51
  description: "Conto SDK for AI agent payment authorization",
52
52
  main: "./dist/index.js",
53
53
  module: "./dist/index.mjs",
@@ -80,8 +80,7 @@ var require_package = __commonJS({
80
80
  }
81
81
  },
82
82
  publishConfig: {
83
- access: "public",
84
- tag: "beta"
83
+ access: "public"
85
84
  },
86
85
  engines: {
87
86
  node: ">=20.19.0"
@@ -119,7 +118,7 @@ var require_package = __commonJS({
119
118
  email: "support@conto.finance"
120
119
  },
121
120
  dependencies: {
122
- "@sentry/node": "^10.73.0"
121
+ "@sentry/node": "^11.8.0"
123
122
  },
124
123
  peerDependencies: {
125
124
  "playwright-core": ">=1.50.0"
@@ -133,10 +132,10 @@ var require_package = __commonJS({
133
132
  esbuild: "0.28.1"
134
133
  },
135
134
  devDependencies: {
136
- "@types/node": "22.19.18",
135
+ "@types/node": "26.6.5",
137
136
  "playwright-core": "1.61.0",
138
- tsup: "^8.5.1",
139
- typescript: "^5.9.3"
137
+ tsup: "^9.0.0",
138
+ typescript: "^6.0.3"
140
139
  }
141
140
  };
142
141
  }
@@ -198,6 +197,32 @@ var Sentry2 = __toESM(require("@sentry/node"));
198
197
  var import_node_crypto3 = require("crypto");
199
198
  var import_package_version2 = __toESM(require_package_version());
200
199
 
200
+ // src/link-approval.ts
201
+ function safeLinkApprovalUrl(value) {
202
+ if (typeof value !== "string" || value.length === 0 || value.length > 2048) return void 0;
203
+ let url;
204
+ try {
205
+ url = new URL(value);
206
+ } catch {
207
+ return void 0;
208
+ }
209
+ if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.port !== "" || !(url.hostname === "link.com" || url.hostname.endsWith(".link.com"))) {
210
+ return void 0;
211
+ }
212
+ url.hash = "";
213
+ return url.toString();
214
+ }
215
+ function linkTime(value) {
216
+ let ms = Number.NaN;
217
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
218
+ ms = value < 1e12 ? value * 1e3 : value;
219
+ } else if (typeof value === "string" && value.length > 0 && value.length <= 64) {
220
+ ms = Date.parse(value);
221
+ }
222
+ const date = new Date(ms);
223
+ return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
224
+ }
225
+
201
226
  // src/purchases.ts
202
227
  var import_node_crypto = require("crypto");
203
228
  var TERMINAL = /* @__PURE__ */ new Set(["succeeded", "blocked", "failed", "cancelled"]);
@@ -1414,6 +1439,25 @@ var WalletsClient = class {
1414
1439
  {}
1415
1440
  );
1416
1441
  }
1442
+ /**
1443
+ * Get a one-time message for a self-custody wallet's address to sign. It
1444
+ * expires after 10 minutes and replaces any earlier challenge.
1445
+ */
1446
+ async createOwnershipChallenge(walletId) {
1447
+ return this.client.request(
1448
+ "POST",
1449
+ `/api/wallets/${encodeURIComponent(walletId)}/ownership-proof/challenge`,
1450
+ {}
1451
+ );
1452
+ }
1453
+ /** Prove your organization controls a self-custody wallet's address. */
1454
+ async proveOwnership(walletId, input) {
1455
+ return this.client.request(
1456
+ "POST",
1457
+ `/api/wallets/${encodeURIComponent(walletId)}/ownership-proof`,
1458
+ input
1459
+ );
1460
+ }
1417
1461
  };
1418
1462
  var PoliciesClient = class {
1419
1463
  constructor(client) {
@@ -1666,6 +1710,8 @@ var LinkCardError = class extends ContoError {
1666
1710
  this.name = "LinkCardError";
1667
1711
  this.checkpoint = input.checkpoint;
1668
1712
  if (input.linkRequestId) this.linkRequestId = input.linkRequestId;
1713
+ const approvalUrl = safeLinkApprovalUrl(input.approvalUrl);
1714
+ if (approvalUrl) this.approvalUrl = approvalUrl;
1669
1715
  this.holdReleased = input.holdReleased;
1670
1716
  }
1671
1717
  };
@@ -2973,6 +3019,11 @@ async function closeLinkRequest(wallet, id) {
2973
3019
  return status !== void 0 && LINK_CLOSED_STATUSES.has(status);
2974
3020
  }
2975
3021
  }
3022
+ function assertLinkApprovalCallback(callback) {
3023
+ if (callback !== void 0 && typeof callback !== "function") {
3024
+ throw checkoutError("onLinkApproval must be a function");
3025
+ }
3026
+ }
2976
3027
  function linkCreatedNothing(error) {
2977
3028
  return errorCode(error) === "LINK_WALLET_UNAVAILABLE" || errorReason(error) === "invalid_input";
2978
3029
  }
@@ -2982,6 +3033,23 @@ var LinkFailureSignal = class extends Error {
2982
3033
  this.failure = failure;
2983
3034
  }
2984
3035
  };
3036
+ function linkApprovalDetails(request) {
3037
+ const approvalUrl = safeLinkApprovalUrl(request.approvalUrl);
3038
+ const approvalExpiresAt = linkTime(request.approvalExpiresAt);
3039
+ return {
3040
+ ...approvalUrl ? { approvalUrl } : {},
3041
+ ...approvalExpiresAt ? { approvalExpiresAt } : {}
3042
+ };
3043
+ }
3044
+ function notifyLinkApproval(callback, event) {
3045
+ try {
3046
+ const result = callback(Object.freeze(event));
3047
+ if (result !== null && typeof result === "object" && "then" in result) {
3048
+ Promise.resolve(result).catch(() => void 0);
3049
+ }
3050
+ } catch {
3051
+ }
3052
+ }
2985
3053
  var _client4, _CheckoutClient_instances, linkCardFor_fn;
2986
3054
  var CheckoutClient = class {
2987
3055
  constructor(client) {
@@ -3167,7 +3235,9 @@ var CheckoutClient = class {
3167
3235
  * 1. Conto runs checkpoint 1 and holds the spend. When a rule requires the
3168
3236
  * owner's approval, this waits for it.
3169
3237
  * 2. Only then does the wallet ask Link for a card for exactly the approved
3170
- * amount at this merchant. The person approves it in their Link app.
3238
+ * amount at this merchant. The person approves it in Link. Pass
3239
+ * onLinkApproval to get Link's approval page, so they can approve on the
3240
+ * web without the Link app.
3171
3241
  * 3. The card is returned. It never reaches Conto.
3172
3242
  *
3173
3243
  * Then fill in the card, call confirm(result.checkpoint, { amountMinor,
@@ -3183,10 +3253,18 @@ var CheckoutClient = class {
3183
3253
  * Link request.
3184
3254
  */
3185
3255
  async getLinkCard(input) {
3186
- const { wallet, ownerApprovalTimeoutMs, linkApprovalTimeoutMs, signal, ...beginInput } = input;
3256
+ const {
3257
+ wallet,
3258
+ ownerApprovalTimeoutMs,
3259
+ linkApprovalTimeoutMs,
3260
+ onLinkApproval,
3261
+ signal,
3262
+ ...beginInput
3263
+ } = input;
3187
3264
  if (!wallet || typeof wallet.createCardRequest !== "function") {
3188
3265
  throw checkoutError("wallet must be a LinkWallet, such as linkCliWallet()");
3189
3266
  }
3267
+ assertLinkApprovalCallback(onLinkApproval);
3190
3268
  let checkpoint = await this.begin({ ...beginInput, checkoutMethod: "LINK" });
3191
3269
  if (checkpoint.stage === "AWAITING_APPROVAL") {
3192
3270
  checkpoint = await this.waitForApproval(checkpoint, {
@@ -3194,7 +3272,11 @@ var CheckoutClient = class {
3194
3272
  ...signal ? { signal } : {}
3195
3273
  });
3196
3274
  }
3197
- return __privateMethod(this, _CheckoutClient_instances, linkCardFor_fn).call(this, checkpoint, wallet, linkApprovalTimeoutMs, signal);
3275
+ return __privateMethod(this, _CheckoutClient_instances, linkCardFor_fn).call(this, checkpoint, wallet, {
3276
+ linkApprovalTimeoutMs,
3277
+ signal,
3278
+ onLinkApproval
3279
+ });
3198
3280
  }
3199
3281
  /**
3200
3282
  * The final total differs from the one the Link card covers. This cancels
@@ -3203,10 +3285,18 @@ var CheckoutClient = class {
3203
3285
  * for it. Confirm the returned checkpoint with the same total.
3204
3286
  */
3205
3287
  async replaceLinkCard(previous, input) {
3206
- const { wallet, amountMinor, ownerApprovalTimeoutMs, linkApprovalTimeoutMs, signal } = input;
3288
+ const {
3289
+ wallet,
3290
+ amountMinor,
3291
+ ownerApprovalTimeoutMs,
3292
+ linkApprovalTimeoutMs,
3293
+ onLinkApproval,
3294
+ signal
3295
+ } = input;
3207
3296
  if (!Number.isSafeInteger(amountMinor) || amountMinor <= 0) {
3208
3297
  throw checkoutError("amountMinor must be a positive integer number of cents");
3209
3298
  }
3299
+ assertLinkApprovalCallback(onLinkApproval);
3210
3300
  if (amountMinor === previous.checkpoint.amountMinor) return previous;
3211
3301
  const old = previous.checkpoint;
3212
3302
  if (!await closeLinkRequest(wallet, previous.linkRequestId)) {
@@ -3245,12 +3335,17 @@ var CheckoutClient = class {
3245
3335
  ...signal ? { signal } : {}
3246
3336
  });
3247
3337
  }
3248
- return __privateMethod(this, _CheckoutClient_instances, linkCardFor_fn).call(this, checkpoint, wallet, linkApprovalTimeoutMs, signal);
3338
+ return __privateMethod(this, _CheckoutClient_instances, linkCardFor_fn).call(this, checkpoint, wallet, {
3339
+ linkApprovalTimeoutMs,
3340
+ signal,
3341
+ onLinkApproval
3342
+ });
3249
3343
  }
3250
3344
  };
3251
3345
  _client4 = new WeakMap();
3252
3346
  _CheckoutClient_instances = new WeakSet();
3253
- linkCardFor_fn = async function(checkpoint, wallet, linkApprovalTimeoutMs = 10 * 6e4, signal) {
3347
+ linkCardFor_fn = async function(checkpoint, wallet, options) {
3348
+ const { linkApprovalTimeoutMs = 10 * 6e4, signal, onLinkApproval } = options;
3254
3349
  if (checkpoint.stage !== "APPROVED") {
3255
3350
  throw checkoutError(
3256
3351
  `Conto has not approved a card for this checkpoint (stage ${checkpoint.stage}). Do not pay.`,
@@ -3260,6 +3355,7 @@ linkCardFor_fn = async function(checkpoint, wallet, linkApprovalTimeoutMs = 10 *
3260
3355
  const deadline = Date.now() + linkApprovalTimeoutMs;
3261
3356
  const call = signal ? { signal } : {};
3262
3357
  let linkRequestId;
3358
+ let approvalUrl;
3263
3359
  let createStarted = false;
3264
3360
  try {
3265
3361
  const cardRequest = linkCardRequest(checkpoint);
@@ -3280,6 +3376,13 @@ linkCardFor_fn = async function(checkpoint, wallet, linkApprovalTimeoutMs = 10 *
3280
3376
  message: "Link returned a request for a different amount."
3281
3377
  });
3282
3378
  }
3379
+ if (LINK_WAITING_STATUSES.has(request.status)) {
3380
+ const details = linkApprovalDetails(request);
3381
+ approvalUrl = details.approvalUrl;
3382
+ if (onLinkApproval) {
3383
+ notifyLinkApproval(onLinkApproval, { checkpoint, linkRequestId: request.id, ...details });
3384
+ }
3385
+ }
3283
3386
  while (linkRequestWaiting(request)) {
3284
3387
  const remainingSeconds = Math.floor((deadline - Date.now()) / 1e3);
3285
3388
  if (remainingSeconds <= 0) {
@@ -3294,6 +3397,7 @@ linkCardFor_fn = async function(checkpoint, wallet, linkApprovalTimeoutMs = 10 *
3294
3397
  ...call,
3295
3398
  timeoutSeconds: remainingSeconds
3296
3399
  });
3400
+ approvalUrl = LINK_WAITING_STATUSES.has(request.status) ? linkApprovalDetails(request).approvalUrl ?? approvalUrl : void 0;
3297
3401
  if (linkRequestWaiting(request) && Date.now() - started < 1e3) {
3298
3402
  await sleep2(1e3, signal);
3299
3403
  }
@@ -3325,6 +3429,7 @@ linkCardFor_fn = async function(checkpoint, wallet, linkApprovalTimeoutMs = 10 *
3325
3429
  code: "LINK_CARD_NOT_CANCELLED",
3326
3430
  checkpoint,
3327
3431
  linkRequestId,
3432
+ ...approvalUrl ? { approvalUrl } : {},
3328
3433
  holdReleased: false,
3329
3434
  retryGuidance: "Retry with the same input to resume this Link request, or cancel it with wallet.cancel(error.linkRequestId) and then call checkout.cancel(error.checkpoint.id)."
3330
3435
  });
@@ -3338,6 +3443,7 @@ linkCardFor_fn = async function(checkpoint, wallet, linkApprovalTimeoutMs = 10 *
3338
3443
  code: failure.code,
3339
3444
  checkpoint,
3340
3445
  ...linkRequestId ? { linkRequestId } : {},
3446
+ ...linkRequestId && approvalUrl ? { approvalUrl } : {},
3341
3447
  holdReleased
3342
3448
  });
3343
3449
  }