vet-sdk-core-ts 0.4.16 → 0.4.18

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
@@ -1,11 +1,28 @@
1
1
  # VetChain Core SDK
2
2
 
3
+ Development and releases follow the mandatory
4
+ [`local-first TDD and release contract`](docs/LOCAL_FIRST_RELEASE_CONTRACT.md).
5
+
3
6
  Browser-safe VetChain domain contracts. This repository is independent from
4
7
  UHC SDK packages and must not import them.
5
8
 
6
9
  The SDK consumes governed browser-safe values from `vet-data-utils-ts` and
7
10
  owns gateway request construction. GW VET remains the policy authority.
8
11
 
12
+ ## USDC payment quotes
13
+
14
+ `vet-sdk-core-ts/payment` separates the payment provider, asset and EVM network
15
+ instead of treating every token named USDC as equivalent. It pins Circle USDC
16
+ on Base Sepolia and Base mainnet, validates the server-authored recipient,
17
+ integer six-decimal amount and expiry, and keeps mainnet disabled unless the
18
+ caller supplies a separately approved release policy. Local Anvil deployments
19
+ provide their deployed mock-token contract through the same network contract;
20
+ they never reuse a production address.
21
+
22
+ The quote authorizes no payment by itself. A server payment adapter must still
23
+ verify the receipt, Transfer log, payer, recipient, amount, confirmation depth,
24
+ invoice state and transaction-hash idempotency before reconciling the payment.
25
+
9
26
  ## Research studies
10
27
 
11
28
  `buildVeterinaryResearchStudyCreateWorkflowIds` accepts a client-generated
package/dist/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export * from "./card-issuance.js";
5
5
  export * from "./animal-onboarding.js";
6
6
  export * from "./reusable-bff.js";
7
7
  export * from "./research-study.js";
8
+ export * from "./payment.js";
8
9
  export * from "vet-data-utils-ts";
package/dist/index.js CHANGED
@@ -5,4 +5,5 @@ export * from "./card-issuance.js";
5
5
  export * from "./animal-onboarding.js";
6
6
  export * from "./reusable-bff.js";
7
7
  export * from "./research-study.js";
8
+ export * from "./payment.js";
8
9
  export * from "vet-data-utils-ts";
@@ -0,0 +1,10 @@
1
+ import { type EvmPaymentNetworkId, type UsdcEvmNetwork, type UsdcPaymentQuote } from 'vet-data-utils-ts/payment';
2
+ export { EvmPaymentNetworkIds, PaymentAssetIds, PaymentCurrencyCodes, PaymentProviderIds, USDC_BASE_NETWORKS, USDC_DECIMALS, VET_PAYMENT_TEST_DATA, type EvmPaymentNetworkId, type PaymentProviderId, type UsdcEvmNetwork, type UsdcPaymentQuote, usdOfferToUsdcMinor, } from 'vet-data-utils-ts/payment';
3
+ export type UsdcPaymentQuotePolicy = Readonly<{
4
+ now: Date;
5
+ recipient: `0x${string}`;
6
+ allowMainnet: boolean;
7
+ networks?: Readonly<Partial<Record<EvmPaymentNetworkId, UsdcEvmNetwork>>>;
8
+ }>;
9
+ /** Validates a server-authored quote without trusting browser network fields. */
10
+ export declare function validateUsdcPaymentQuote(value: unknown, policy: UsdcPaymentQuotePolicy): UsdcPaymentQuote;
@@ -0,0 +1,42 @@
1
+ import { PaymentProviderIds, USDC_DECIMALS, USDC_BASE_NETWORKS, } from 'vet-data-utils-ts/payment';
2
+ export { EvmPaymentNetworkIds, PaymentAssetIds, PaymentCurrencyCodes, PaymentProviderIds, USDC_BASE_NETWORKS, USDC_DECIMALS, VET_PAYMENT_TEST_DATA, usdOfferToUsdcMinor, } from 'vet-data-utils-ts/payment';
3
+ const EVM_ADDRESS_PATTERN = /^0x[0-9a-fA-F]{40}$/;
4
+ const POSITIVE_INTEGER_PATTERN = /^[1-9][0-9]*$/;
5
+ function paymentContractError(code) {
6
+ throw new Error(code);
7
+ }
8
+ /** Validates a server-authored quote without trusting browser network fields. */
9
+ export function validateUsdcPaymentQuote(value, policy) {
10
+ if (!value || typeof value !== "object")
11
+ paymentContractError("payment_quote_invalid");
12
+ const quote = value;
13
+ if (quote.version !== 1 || quote.provider !== PaymentProviderIds.UsdcEvm) {
14
+ paymentContractError("payment_quote_invalid");
15
+ }
16
+ const networks = policy.networks || USDC_BASE_NETWORKS;
17
+ const network = quote.network ? networks[quote.network] : undefined;
18
+ if (!network || quote.chainId !== network.chainId)
19
+ paymentContractError("payment_network_not_allowed");
20
+ if (network.mainnet && !policy.allowMainnet)
21
+ paymentContractError("payment_mainnet_not_enabled");
22
+ if (!EVM_ADDRESS_PATTERN.test(String(quote.tokenContract || ""))
23
+ || quote.tokenContract?.toLowerCase() !== network.usdcContract.toLowerCase()) {
24
+ paymentContractError("payment_token_contract_not_allowed");
25
+ }
26
+ if (!EVM_ADDRESS_PATTERN.test(String(quote.recipient || ""))
27
+ || quote.recipient?.toLowerCase() !== policy.recipient.toLowerCase()) {
28
+ paymentContractError("payment_recipient_mismatch");
29
+ }
30
+ if (!POSITIVE_INTEGER_PATTERN.test(String(quote.amountMinor || "")) || quote.decimals !== USDC_DECIMALS) {
31
+ paymentContractError("payment_amount_invalid");
32
+ }
33
+ if (!String(quote.paymentReference || "").trim() || !String(quote.invoiceId || "").trim()) {
34
+ paymentContractError("payment_reference_invalid");
35
+ }
36
+ const expiresAt = Date.parse(String(quote.expiresAt || ""));
37
+ if (!Number.isFinite(expiresAt))
38
+ paymentContractError("payment_quote_invalid");
39
+ if (expiresAt <= policy.now.getTime())
40
+ paymentContractError("payment_quote_expired");
41
+ return quote;
42
+ }
@@ -0,0 +1,91 @@
1
+ # Local-first TDD and release contract
2
+
3
+ This contract is mandatory for behavior changes, shared packages, gateways and
4
+ portals. Repository skills and release-continuity tests enforce it.
5
+
6
+ ## 1. Canonical types and reusable test data
7
+
8
+ Before inventing a type, enum, code, identifier, claim, vocabulary or test
9
+ literal, search the applicable standards and the owning shared packages.
10
+
11
+ Use the canonical type or terminology from HL7/FHIR, LOINC, SNOMED CT, ICD-10,
12
+ WHO ATC, Schema.org or the applicable governed standard. Then reuse the
13
+ exported type, builder or fixture from the versioned domain data package
14
+ (`<version>-data` or `<version>-data-utils`) or `common-utils`.
15
+
16
+ If it does not exist, add it first to the owning shared package with its own
17
+ red-green test and export it. Consumers import that export. They must not copy
18
+ or locally recreate governed strings, object shapes or identifiers.
19
+
20
+ ## 2. TDD contract
21
+
22
+ Every new or modified test file starts on its first line with a
23
+ `// Flow contract:` comment that links this document and names the production
24
+ journey, authorization boundary and persistence invariant under proof.
25
+
26
+ Apply strict `red -> green -> refactor`:
27
+
28
+ 1. Write the smallest executable contract and run it red.
29
+ 2. The red result must fail because the required production behavior is absent
30
+ or wrong, not because the test is malformed or setup is missing.
31
+ 3. Implement only enough production code to make that contract green.
32
+ 4. Run the smallest affected integration and real-boundary gate.
33
+ 5. Refactor while keeping the focused contract green.
34
+
35
+ A skip, accepted error, placeholder, pending setup, fixture-only UI or mock that
36
+ replaces the real boundary is never a green result. Unit mocks may isolate code,
37
+ but local service and Playwright proof must exercise the real UI -> BFF ->
38
+ high-level SDK -> GW/DataConv boundary when that journey is affected.
39
+
40
+ ## 3. Local-first gates and failure continuation
41
+
42
+ Promotion order is cumulative:
43
+
44
+ `test -> local-network -> test-network/staging -> network/production`
45
+
46
+ The `test` stage includes every affected unit, integration, local service,
47
+ real UI and Playwright gate without blockchain. After a failure, resume only
48
+ the smallest failed gate. Do not repeat a green gate unless the fix changed its
49
+ boundary, it creates required state, or the environment is no longer
50
+ trustworthy. Run the complete affected local matrix once at branch closure.
51
+
52
+ ## 4. Unpublished package iteration
53
+
54
+ Keep all participating repositories on pushed but unmerged branches while the
55
+ local matrix is still being corrected. Build an immutable tarball with
56
+ `npm pack` and install it in downstream branches with `--no-save`.
57
+
58
+ The tarball is temporary test input. Never commit a `file:`, Git, workspace or
59
+ vendored tarball dependency or its generated lockfile state. An npm
60
+ authorization or publication failure must never stop the local `test` stage.
61
+
62
+ Do not attempt `npm publish` until every affected local gate in section 3 is
63
+ green.
64
+
65
+ ## 5. Publication and merge order
66
+
67
+ After all local gates are green:
68
+
69
+ 1. Publish and verify immutable npm packages from the lowest changed dependency
70
+ upward.
71
+ 2. In gateway consumers, replace the temporary tarball with the exact published
72
+ registry version; commit the registry dependency and lockfile.
73
+ 3. Run only the minimal clean-install, import/export and startup smoke needed to
74
+ prove the registry artifact matches the tested tarball. Do not repeat the
75
+ green local matrix unless the artifact differs or invalidates prior evidence.
76
+ 4. Merge and push package repositories to `main`.
77
+ 5. Merge and push gateway consumers to `main` only with exact registry
78
+ versions installed, then build immutable GW images and run `local-network`.
79
+ 6. Portal consumers remain on pushed, unmerged branches with the immutable
80
+ tarball during `local-network`; do not reinstall or repeat their already-green
81
+ local matrix.
82
+ 7. After `local-network` is green, install the exact registry version in each
83
+ affected portal, commit its registry dependency and lockfile, and run only
84
+ the minimal artifact smoke.
85
+ 8. Merge portal consumers to `main`, continue to `test-network`/staging and
86
+ finally `network`/production. No tarball or local dependency may reach
87
+ `main`.
88
+
89
+ Missing exact registry publication blocks consumer merge, image build and
90
+ environment promotion. It does not block continued local testing with the
91
+ immutable tarball.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vet-sdk-core-ts",
3
- "version": "0.4.16",
3
+ "version": "0.4.18",
4
4
  "description": "Browser-safe VetChain core contracts and governed animal species identifiers",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Connecting Solution & Applications Ltd",
@@ -39,6 +39,10 @@
39
39
  "./research-study": {
40
40
  "types": "./dist/research-study.d.ts",
41
41
  "default": "./dist/research-study.js"
42
+ },
43
+ "./payment": {
44
+ "types": "./dist/payment.d.ts",
45
+ "default": "./dist/payment.js"
42
46
  }
43
47
  },
44
48
  "files": [
@@ -64,6 +68,6 @@
64
68
  "dependencies": {
65
69
  "@noble/hashes": "^2.2.0",
66
70
  "gdc-common-utils-ts": "2.9.4",
67
- "vet-data-utils-ts": "0.5.2"
71
+ "vet-data-utils-ts": "0.5.4"
68
72
  }
69
73
  }