@zkp2p/sdk 0.14.8-rc.0 → 0.15.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,7 +40,7 @@ For partner cash-out integrations, prefer stable `@zkp2p/cash@0.7.2` and its
40
40
  It selects the matching environment and keeps linking separate from cash-out.
41
41
  The direct SDK helpers below require `@zkp2p/sdk@0.14.2` or later.
42
42
 
43
- Open Peer's **Link your Venmo** popup for an already-registered account.
43
+ Open Peer's **Verify your Venmo** popup for an already-registered account.
44
44
  The host passes the selected account hash; the user picks Gmail or Outlook,
45
45
  which opens that provider's consent, or iCloud Mail, which takes an Apple
46
46
  app-specific password on the Peer page.
@@ -398,7 +398,7 @@ const onchain = await client.getStakeVaultState({
398
398
  const indexed = await client.indexer.getStakingState({
399
399
  chainId: 8453,
400
400
  environment: 'base',
401
- vaultAddress: client.getStakeVaultContract().address,
401
+ vaultAddress: (await client.getActiveStakeVaultContract()).address,
402
402
  disputeProtectionPolicyAddress: client.getDisputeProtectionPolicyContract().address,
403
403
  taker: takerAddress,
404
404
  // Always supply the effective owner from the fresh on-chain read.
@@ -409,7 +409,7 @@ const indexed = await client.indexer.getStakingState({
409
409
 
410
410
  const locks = await client.indexer.getStakeLocks({
411
411
  chainId: 8453,
412
- vaultAddress: client.getStakeVaultContract().address,
412
+ vaultAddress: (await client.getActiveStakeVaultContract()).address,
413
413
  stakeOwner: onchain.stakeOwner,
414
414
  status: 'ACTIVE',
415
415
  limit: 50,
@@ -417,7 +417,7 @@ const locks = await client.indexer.getStakeLocks({
417
417
 
418
418
  const activity = await client.indexer.getStakeActivity({
419
419
  chainId: 8453,
420
- vaultAddress: client.getStakeVaultContract().address,
420
+ vaultAddress: (await client.getActiveStakeVaultContract()).address,
421
421
  merchant: takerAddress,
422
422
  orderDirection: 'desc', // Newest first; defaults to asc for chronological ingestion.
423
423
  limit: 50,
@@ -429,7 +429,7 @@ const activity = await client.indexer.getStakeActivity({
429
429
 
430
430
  const totals = await client.indexer.getStakeTotals({
431
431
  chainId: 8453,
432
- vaultAddress: client.getStakeVaultContract().address,
432
+ vaultAddress: (await client.getActiveStakeVaultContract()).address,
433
433
  });
434
434
  // totals.totalStaked and totals.totalLocked are decimal strings in token base units.
435
435
  // totals.stakerCount counts owners whose stake balance is greater than zero.
@@ -451,6 +451,29 @@ withdraws the complete claimable balance. Chargebackable capacity is exactly
451
451
  the effective owner's free stake (1:1); never sum a taker's self-stake with a
452
452
  sponsor's stake.
453
453
 
454
+ `getActiveDisputeProtectionStack()` reads the live OrchestratorV3 hook, policy,
455
+ and vault. It returns `null` for a zero hook, rejects unknown policies or vaults,
456
+ and caches discovery per client for 30 seconds; failures are never cached.
457
+ `getActiveStakeVaultContract()` returns that vault (canonical when the hook is zero).
458
+ `getKnownStakeVaults()` lists canonical, Bypass, and any exported MethodScoped
459
+ predecessor vault, deduplicated by address. `isNoStakeAvailable()` is true only
460
+ when the live policy is the resolved payment-validation policy.
461
+
462
+ Pass `stakeVaultAddress?: Address` to `getStakeVaultContract(options?)`,
463
+ `getStakeVaultState({ staker, taker?, stakeVaultAddress? })`, every vault write,
464
+ and `ensureStakeAllowance`. Single-value vault reads accept a trailing optional
465
+ `options?: { stakeVaultAddress?: Address }`. Unknown vaults throw; reads, writes,
466
+ and allowance default to the active vault (canonical only for a zero hook).
467
+ The synchronous `getStakeVaultContract()` getter still returns bundle/canonical
468
+ coordinates when no address is given; use `getActiveStakeVaultContract()` for
469
+ the vault the live policy locks from. Each vault-state call resolves one vault
470
+ for all accounting reads and its stake token; `admissionsPaused` comes from
471
+ that vault's controller.
472
+ The standalone `getAdmissionsPaused`, `getRiskWindow`, and
473
+ `isDisputeProtectionEnabled` reads follow the live policy, using canonical only
474
+ when the live hook is zero. `setDisputeProtectionEnabled` follows the same live
475
+ policy unless `disputeProtectionPolicyAddress` is supplied.
476
+
454
477
  The vault's controller is the `DisputeProtectionPolicy` contract. It owns
455
478
  per-payment-method risk windows (`getRiskWindow(paymentMethodHash)`),
456
479
  per-deposit chargeback enablement (`isDisputeProtectionEnabled(escrow, depositId)`),
@@ -501,7 +524,7 @@ same finalized cutoff for every cursor in one ingestion pass. Follow
501
524
  empty page.
502
525
 
503
526
  Before enabling dispute-protected admission, prove that the live Base contracts
504
- still match the deployment manifest embedded in the exact SDK artifact:
527
+ match the packaged manifest or verified Bypass successor records:
505
528
 
506
529
  ```ts
507
530
  const readiness = await client.getDisputeProtectionReadiness();
@@ -511,7 +534,15 @@ if (readiness.state !== 'active_successor_verified' || !readiness.readyForDisput
511
534
  }
512
535
  ```
513
536
 
514
- The reader pins every code and state read to one `asOfBlock`, including exact
537
+ Known results expose `verifiedStack`: `manifest` for the manifest path or
538
+ `bypass_records` for an active Bypass hook distinct from the manifest hook. The
539
+ Bypass path proves code presence and the specified hook/registry/policy/vault
540
+ relations at one block; it does not claim manifest runtime-hash or governance
541
+ verification for those new deployments. Missing records leave this path off.
542
+ On Base staging the manifest now names the Bypass stack, so its Bypass records
543
+ equal the manifest identities and readiness runs the full manifest path there.
544
+
545
+ The manifest reader pins every code and state read to one `asOfBlock`, including exact
515
546
  governance owners, authorization sets, attestation witnesses, and signature
516
547
  thresholds. It distinguishes
517
548
  `recognized_predecessor`, `passive_successor`, `active_successor_verified`,
@@ -523,6 +554,15 @@ verified while `orchestratorPaused`, `allowMultipleIntents`, and
523
554
  traffic. Unknown hooks, misconfigured successors, runtime-code changes,
524
555
  dependency mismatches, and RPC failures return `mismatch` and fail closed.
525
556
 
557
+ An activated successor may keep its recognized predecessor policy as a
558
+ `DisputeNullifierRegistry` writer while that predecessor's intents drain. The
559
+ active state therefore requires every active writer and accepts the
560
+ manifest's `RecognizedPredecessorPolicy` as the only additional writer, after
561
+ verifying its packaged runtime hash at `asOfBlock`. Any other writer, or a
562
+ missing active writer, is a `mismatch`. The passive state keeps its exact
563
+ writer set, and an orchestrator the manifest does not list is always a
564
+ `mismatch`.
565
+
526
566
  Dispute evidence callers should read the current attestation trust roots before
527
567
  requesting evidence and again before submitting it:
528
568
 
@@ -531,6 +571,7 @@ const attestationConfig = await readDisputeAttestationConfig({
531
571
  publicClient,
532
572
  chainId: 8453,
533
573
  environment: 'production',
574
+ // policyAddress: found.policyAddress, // optional known historical policy
534
575
  });
535
576
 
536
577
  if (attestationConfig.requiredSignatures !== 1) {
@@ -547,6 +588,8 @@ selection hashes. A local build has the deterministic `development` identity
547
588
  and is deliberately non-distributable, so its readiness reader returns
548
589
  `mismatch` before making RPC calls.
549
590
 
591
+ Quote and orderbook requests accept `includeNoStakeCompatible?: boolean` to opt in to protected rows a taker may signal without stake (Venmo only today). Only `true` is sent; false and omitted values leave the field absent.
592
+
550
593
  For table-style liquidity UIs, the low-level `apiGetOrderbookTable()` adapter exposes curator's paginated public/private orderbook rows and row-level privacy metadata.
551
594
 
552
595
  ## Seller Credential Status
@@ -590,8 +633,6 @@ await client.uploadICloudMailSellerCredential({
590
633
 
591
634
  The password is encrypted to the attested enclave and posted directly to the attestor paired with `baseApiUrl`. The returned bundle is verified against the pinned enclave signer, platform and maker before it is stored unchanged; the maker is not re-registered. React Native callers pass `{ attestationRuntime: { subtle, getRandomValues } }`. Failures reject with `ICloudMailCredentialError`, whose `reason` names the condition (`payee_mismatch`, `payee_not_found`, `receipt_not_found`, `app_password_rejected`, `rate_limited` with `retryAfterMs`, and so on). The method never retries; one connection per mailbox runs at a time. `isMailboxSellerCredentialType` recognizes Gmail, Outlook and iCloud Mail credentials.
592
635
 
593
- To store the bundle through another Curator route, such as an App Clip's request-scoped SAR connection, call `client.attestICloudMailSellerCredential` with the same arguments. It runs the same checks, enclave upload and verification, then returns the verified `SellerCredentialBundleUpload` without storing it, so it needs no Curator session. Walletless callers use the exported `attestICloudMailSellerCredential(params, { attestationServiceUrl, baseApiUrl, timeoutMs, attestationRuntime })` and name the attestor themselves. Errors, the mailbox lock and rate-limit delays match the upload.
594
-
595
636
  ```ts
596
637
  const status = await client.getSellerCredentialStatus({
597
638
  processorName: 'venmo',
@@ -634,6 +675,91 @@ await client.releaseFundsToPayer({
634
675
 
635
676
  Use `referralFees[]` for multi-recipient fee distribution on OrchestratorV2 and V3.
636
677
 
678
+ ### Signal intent stake mode
679
+
680
+ `signalIntent`, `signalIntent.prepare`, `prepareSignalIntent`, and the React
681
+ `useSignalIntent` hook accept `noStake?: boolean` (default `false`). Use `true`
682
+ only for Venmo Friends & Family payments funded from Venmo balance. Any other
683
+ payment method, by name or hash, throws `ValidationError` with field `noStake`
684
+ before `/v3/sign` is called. The SDK sends
685
+ `abi.encode(paymentValidationPolicy, abi.encode(noStake))` to both `/v3/sign`
686
+ and OrchestratorV3 whenever the selected deployment has a payment-validation
687
+ policy. This target comes from the bundle, independently of the live hook.
688
+
689
+ The installed `@zkp2p/contracts-v2@0.4.4-rc.5` bundle records the fresh Bypass trio
690
+ redeployed on Base staging on 2026-10-13 as active: the staging canonical aliases
691
+ (`StakeVault`, `DisputeProtectionPolicy`, `IntentLifecycleHookV1`) and the staging
692
+ dispute-stack manifest name the same addresses as the Bypass records, staging
693
+ selects UPV4, and staging signals carry the policy envelope. The predecessor
694
+ staging vault stays exported as `StakeVaultMethodScoped`, so its stake remains
695
+ readable and withdrawable. Base (production and preproduction) exports zero
696
+ placeholders that the resolvers ignore: signals keep `0x`, UPV3 remains
697
+ selected, and `noStake: true` throws `ValidationError` with field `noStake`.
698
+ Base canonical aliases and its dispute-stack manifest are unchanged. No-stake
699
+ availability still follows the live chain: the live lifecycle hook's policy
700
+ must be the resolved payment-validation policy.
701
+
702
+ **Breaking migration:** caller `data` is removed from signal parameters. UPV4
703
+ interprets every non-empty V3 data value as a payment-validation envelope.
704
+ Pass `noStake` instead; supply post-intent hook inputs as `postIntentHookData`
705
+ at fulfillment. Legacy JavaScript calls with `data: '0x'` or `undefined`
706
+ are accepted; other values throw `ValidationError` with field `data`.
707
+
708
+ ### Read or change an intent's stake mode
709
+
710
+ `client.getPaymentValidationPolicyContract()` returns `{ address, abi }` or
711
+ `undefined`. The standalone `getPaymentValidationPolicyContract(chainId, env)`
712
+ resolves only the named Bypass policy record or its staging override. Bypass
713
+ records remain exported by name after canonical aliases move to their addresses;
714
+ without a Bypass address, resolution fails closed.
715
+ The returned ABI merges the bundle with `NO_STAKE_DISPUTE_PROTECTION_POLICY_ABI`.
716
+
717
+ For a deployment with that policy, the taker can change a pending intent's mode:
718
+
719
+ ```ts
720
+ const policy = client.getPaymentValidationPolicyContract();
721
+ if (!policy) throw new Error('No payment-validation policy in this deployment');
722
+
723
+ const prepared = await client.setIntentNoStake.prepare({
724
+ intentHash,
725
+ noStake: true,
726
+ });
727
+ // Or execute using client.setIntentNoStake({ intentHash, noStake: true }).
728
+
729
+ const noStake = await client.isIntentNoStake(intentHash);
730
+ const intent = await client.getDisputeProtectionIntent(intentHash, {
731
+ disputeProtectionPolicyAddress: policy.address,
732
+ blockNumber: 123456n, // Optional historical read
733
+ });
734
+ ```
735
+
736
+ `setIntentNoStake` accepts optional `orchestratorAddress`,
737
+ `disputeProtectionPolicyAddress`, and `txOverrides`. The default orchestrator
738
+ is configured OrchestratorV3; an override must be a configured orchestrator.
739
+ The policy defaults to the payment-validation policy and throws if neither
740
+ resolution nor an explicit address supplies one. The contract enforces taker
741
+ ownership, pending status, and sufficient free stake when switching back to
742
+ staked mode.
743
+
744
+ `isIntentNoStake(intentHash, { disputeProtectionPolicyAddress? })` uses the same
745
+ policy default. `getDisputeProtectionIntent(intentHash, options?)` also accepts
746
+ `blockNumber` and falls back to the canonical policy: its eight-field tuple is
747
+ identical on the old deployment. Pin the original policy when reading historical
748
+ intents; this API does not discover which policy owns an intent.
749
+
750
+ `DisputeProtectionIntent` contains `taker`, `stakeOwner`, `depositor`,
751
+ `paymentMethod`, `status`, `riskWindow`, `releaseEligibleAt`, and
752
+ `releaseAmount`. Its exported `DisputeProtectionIntentStatus` enum is
753
+ `None=0, Pending=1, Cancelled=2, Settled=3, Released=4, Disputed=5`.
754
+ `parseDisputeProtectionIntent(value: unknown)` accepts a named object or
755
+ positional tuple and returns `null` for malformed values. The client getter
756
+ throws for malformed results.
757
+
758
+ `encodePaymentValidationHookData(policy: Address, noStake: boolean): Hex` and
759
+ `decodePaymentValidationHookData(data: Hex): { policy: Address; noStake: boolean } | null`
760
+ are exported for integrations validating envelopes; decoding rejects malformed
761
+ or noncanonical data.
762
+
637
763
  ## Extend an Intent Lifetime
638
764
 
639
765
  The standalone `IntentGuardian` lets any payer buy more time for a live intent.
@@ -1195,3 +1321,17 @@ pnpm docs
1195
1321
  Use `platform: 'upi'` with `callerAddress` and `sessionMaterial: { sessionCookie, userAgent }` in the private extension runtime. Omit `payeeId` and `offchainId` when creating the bundle: the attestor derives the receiving VPA from Amazon's current QR. `getAmazonPaySellerIdentity(bundle)` reads that returned identity; storage registers that exact VPA and checks its maker hash against the sealed bundle. Never expose session material to the requesting page.
1196
1322
 
1197
1323
  Amazon capture requires extension 0.6.8 or later. Staging SAR uses the trusted staging attestor and staging provider templates; production requires its Amazon template and backend rollout. This source change does not publish either package or extension.
1324
+
1325
+ ### Historical dispute policy lookup
1326
+
1327
+ `findDisputeProtectionIntent({ publicClient, chainId, environment, intentHash,
1328
+ blockNumber? })` queries the payment-validation, canonical, manifest, and
1329
+ recognized predecessor policies in that order, deduplicated. The first intent
1330
+ whose status is not `None` wins. It returns `null` only when every intent read
1331
+ parses as `None`; an unreadable intent throws. The result contains
1332
+ `policyAddress`, the parsed `intent`, and `noStake` (false if that getter reverts).
1333
+ All calls share a block. Use the returned policy for dispute submission and
1334
+ `readDisputeAttestationConfig({ publicClient, chainId, environment, policyAddress })`.
1335
+ For a known non-manifest policy, the latter follows `disputeVerifier()` and
1336
+ `attestationVerifier()` before reading witnesses and threshold at one block.
1337
+ Unknown policies throw. Omitting `policyAddress` preserves manifest behavior.
@@ -2,12 +2,12 @@
2
2
  "schemaVersion": 2,
3
3
  "source": {
4
4
  "repository": "zkp2p/zkp2p-clients",
5
- "commitSha": "959ea2fdca3a9938c97be98f96f66f1e74ec144d",
5
+ "commitSha": "471e50cadb04d41b35fe48316aa94c56dec4d4a7",
6
6
  "kind": "github",
7
7
  "distributable": true
8
8
  },
9
- "sdkPackageVersion": "0.14.8-rc.0",
10
- "contractsPackageVersion": "0.4.4-rc.2",
9
+ "sdkPackageVersion": "0.15.0-rc.0",
10
+ "contractsPackageVersion": "0.4.4-rc.5",
11
11
  "indexerSchemaPackageVersion": "0.22.0",
12
12
  "activeDisputeStack": {
13
13
  "base": {
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "baseStaging": {
18
18
  "version": 2,
19
- "selectionHash": "6c49c1ce51eec594a22385c4efcab08aa9926b6b63a725e14a0027ec5d2f4fc9"
19
+ "selectionHash": "e3b360a09c2f541052ab7519987862e1f59c0efc9bc25daea09937e9ea59b783"
20
20
  }
21
21
  }
22
22
  }
@@ -5,8 +5,8 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // <define:__ZKP2P_SDK_BUILD_METADATA__>
8
- var define_ZKP2P_SDK_BUILD_METADATA_default = { schemaVersion: 2, source: { repository: "zkp2p/zkp2p-clients", commitSha: "959ea2fdca3a9938c97be98f96f66f1e74ec144d", kind: "github", distributable: true }, sdkPackageVersion: "0.14.8-rc.0", contractsPackageVersion: "0.4.4-rc.2", indexerSchemaPackageVersion: "0.22.0", activeDisputeStack: { base: { version: 2, selectionHash: "ba40c2954b408d0c658881a8d28e5bfcc9bade5cc3d953fd17eae1eca69d841c" }, baseStaging: { version: 2, selectionHash: "6c49c1ce51eec594a22385c4efcab08aa9926b6b63a725e14a0027ec5d2f4fc9" } } };
8
+ var define_ZKP2P_SDK_BUILD_METADATA_default = { schemaVersion: 2, source: { repository: "zkp2p/zkp2p-clients", commitSha: "471e50cadb04d41b35fe48316aa94c56dec4d4a7", kind: "github", distributable: true }, sdkPackageVersion: "0.15.0-rc.0", contractsPackageVersion: "0.4.4-rc.5", indexerSchemaPackageVersion: "0.22.0", activeDisputeStack: { base: { version: 2, selectionHash: "ba40c2954b408d0c658881a8d28e5bfcc9bade5cc3d953fd17eae1eca69d841c" }, baseStaging: { version: 2, selectionHash: "e3b360a09c2f541052ab7519987862e1f59c0efc9bc25daea09937e9ea59b783" } } };
9
9
 
10
10
  export { __export, define_ZKP2P_SDK_BUILD_METADATA_default };
11
- //# sourceMappingURL=chunk-KQT4XYPO.mjs.map
12
- //# sourceMappingURL=chunk-KQT4XYPO.mjs.map
11
+ //# sourceMappingURL=chunk-6K2RTFER.mjs.map
12
+ //# sourceMappingURL=chunk-6K2RTFER.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["%3Cdefine:__ZKP2P_SDK_BUILD_METADATA__%3E"],"names":[],"mappings":";;;;;;;AAAA,IAAA,uCAAA,GAAA,EAAC,aAAA,EAAgB,CAAA,EAAE,MAAA,EAAS,EAAC,YAAa,qBAAA,EAAsB,SAAA,EAAY,0CAAA,EAA2C,IAAA,EAAO,UAAS,aAAA,EAAgB,IAAA,EAAI,EAAE,iBAAA,EAAoB,eAAc,uBAAA,EAA0B,YAAA,EAAa,2BAAA,EAA8B,QAAA,EAAS,oBAAqB,EAAC,IAAA,EAAO,EAAC,OAAA,EAAU,GAAE,aAAA,EAAgB,kEAAA,EAAkE,EAAE,WAAA,EAAc,EAAC,OAAA,EAAU,CAAA,EAAE,aAAA,EAAgB,kEAAA,IAAmE","file":"chunk-KQT4XYPO.mjs","sourcesContent":["{\"schemaVersion\":2,\"source\":{\"repository\":\"zkp2p/zkp2p-clients\",\"commitSha\":\"959ea2fdca3a9938c97be98f96f66f1e74ec144d\",\"kind\":\"github\",\"distributable\":true},\"sdkPackageVersion\":\"0.14.8-rc.0\",\"contractsPackageVersion\":\"0.4.4-rc.2\",\"indexerSchemaPackageVersion\":\"0.22.0\",\"activeDisputeStack\":{\"base\":{\"version\":2,\"selectionHash\":\"ba40c2954b408d0c658881a8d28e5bfcc9bade5cc3d953fd17eae1eca69d841c\"},\"baseStaging\":{\"version\":2,\"selectionHash\":\"6c49c1ce51eec594a22385c4efcab08aa9926b6b63a725e14a0027ec5d2f4fc9\"}}}"]}
1
+ {"version":3,"sources":["%3Cdefine:__ZKP2P_SDK_BUILD_METADATA__%3E"],"names":[],"mappings":";;;;;;;AAAA,IAAA,uCAAA,GAAA,EAAC,aAAA,EAAgB,CAAA,EAAE,MAAA,EAAS,EAAC,YAAa,qBAAA,EAAsB,SAAA,EAAY,0CAAA,EAA2C,IAAA,EAAO,UAAS,aAAA,EAAgB,IAAA,EAAI,EAAE,iBAAA,EAAoB,eAAc,uBAAA,EAA0B,YAAA,EAAa,2BAAA,EAA8B,QAAA,EAAS,oBAAqB,EAAC,IAAA,EAAO,EAAC,OAAA,EAAU,GAAE,aAAA,EAAgB,kEAAA,EAAkE,EAAE,WAAA,EAAc,EAAC,OAAA,EAAU,CAAA,EAAE,aAAA,EAAgB,kEAAA,IAAmE","file":"chunk-6K2RTFER.mjs","sourcesContent":["{\"schemaVersion\":2,\"source\":{\"repository\":\"zkp2p/zkp2p-clients\",\"commitSha\":\"471e50cadb04d41b35fe48316aa94c56dec4d4a7\",\"kind\":\"github\",\"distributable\":true},\"sdkPackageVersion\":\"0.15.0-rc.0\",\"contractsPackageVersion\":\"0.4.4-rc.5\",\"indexerSchemaPackageVersion\":\"0.22.0\",\"activeDisputeStack\":{\"base\":{\"version\":2,\"selectionHash\":\"ba40c2954b408d0c658881a8d28e5bfcc9bade5cc3d953fd17eae1eca69d841c\"},\"baseStaging\":{\"version\":2,\"selectionHash\":\"e3b360a09c2f541052ab7519987862e1f59c0efc9bc25daea09937e9ea59b783\"}}}"]}