@trustvc/trustvc 1.3.0 → 1.4.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/README.md CHANGED
@@ -24,6 +24,7 @@ TrustVC is a comprehensive wrapper library designed to simplify the signing and
24
24
  - [TradeTrustToken](#tradetrusttoken)
25
25
  - [a) Token Registry v4](#a-token-registry-v4)
26
26
  - [b) Token Registry V5](#b-token-registry-v5)
27
+ - [7. **Document Builder**](#7-document-builder)
27
28
 
28
29
  ## Installation
29
30
 
@@ -587,3 +588,155 @@ function rejectTransferOwners(bytes calldata _remark) external;
587
588
  ```
588
589
 
589
590
  For more information on Token Registry and Title Escrow contracts **version v5**, please visit the readme of [TradeTrust Token Registry V5](https://github.com/TradeTrust/token-registry/blob/master/README.md)
591
+
592
+ ### 7. **Document Builder**
593
+ > The `DocumentBuilder` class helps build and manage W3C Verifiable Credentials (VCs) with credential status features. It supports creating documents with two types of credential statuses: `transferableRecords` and `verifiableDocument`. It can sign the document using a private key, verify its signature, and serialize the document to a JSON format. Additionally, it allows for configuration of document rendering methods and expiration dates.
594
+
595
+ #### Usage
596
+
597
+ ##### Create a new DocumentBuilder instance
598
+ To create a new document, instantiate the `DocumentBuilder` with the base document (Verifiable Credential) that you want to build.
599
+
600
+ To learn more about defining custom contexts, check out the [Credential Subject - Custom Contexts guide](https://docs.tradetrust.io/docs/how-tos/credential-subject).
601
+
602
+ ```ts
603
+ // Adds a custom vocabulary used to define terms in the `credentialSubject`.
604
+ // Users can define their own context if they have domain-specific fields or custom data structures.
605
+ const builder = new DocumentBuilder({
606
+ '@context': 'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v1.jsonld'
607
+ });
608
+ ```
609
+
610
+ ##### Set Credential Subject
611
+ Set the subject of the Verifiable Credential, which typically contains information about the entity the credential is issued to.
612
+
613
+ ```ts
614
+ builder.credentialSubject({
615
+ id: 'did:example:123',
616
+ name: 'John Doe',
617
+ });
618
+ ```
619
+
620
+ ##### Configure Credential Status
621
+ You can configure the credential status as either `transferableRecords` or `verifiableDocument`.
622
+
623
+ **Transferable Records**
624
+ ```ts
625
+ builder.credentialStatus({
626
+ // Refers to the supported network.
627
+ // See: https://docs.tradetrust.io/docs/introduction/key-components-of-tradetrust/blockchain/supported-network
628
+ chain: 'Ethereum',
629
+ chainId: 1,
630
+ tokenRegistry: '0x1234567890abcdef...',
631
+ rpcProviderUrl: 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID',
632
+ });
633
+ ```
634
+
635
+ > ⚠️ **Disclaimer:**
636
+ > This builder **does not mint** documents on-chain. If you're using `transferableRecords`, you'll need to mint the document.
637
+ > [See the minting guide here](https://docs.tradetrust.io/docs/how-tos/credential-status#2-minting-the-credential)
638
+
639
+
640
+ **Verifiable Document**
641
+ ```ts
642
+ builder.credentialStatus({
643
+ url: 'https://example.com/status-list',
644
+ // `index: <placeholder>` refers to the bit position in the status list that will be set for revocation.
645
+ // Note: A document with the specific index must be marked as not revoked in the status list.
646
+ index: <placeholder>,
647
+ purpose: 'revocation',
648
+ });
649
+ ```
650
+
651
+ ##### Set Expiration Date
652
+ You can set an expiration date for the document.
653
+
654
+ ```ts
655
+ builder.expirationDate('2026-01-01T00:00:00Z');
656
+ ```
657
+
658
+ ##### Define Rendering Method
659
+ Set the rendering method to be used for the document.
660
+
661
+ ```ts
662
+ builder.renderMethod({
663
+ id: 'https://example.com/rendering-method',
664
+ type: 'EMBEDDED_RENDERER',
665
+ templateName: 'BILL_OF_LADING',
666
+ });
667
+ ```
668
+
669
+ ##### Sign the Document
670
+ To sign the document, provide a `PrivateKeyPair` from `@trustvc/trustvc`.
671
+
672
+ ```ts
673
+ const privateKey: PrivateKeyPair = {
674
+ id: 'did:example:456#key1',
675
+ controller: 'did:example:456',
676
+ type: VerificationType.Bls12381G2Key2020,
677
+ publicKeyBase58: 'your-public-key-base58',
678
+ privateKeyBase58: 'your-private-key-base58',
679
+ };
680
+
681
+ const signedDocument = await builder.sign(privateKey);
682
+ console.log(signedDocument);
683
+ ```
684
+
685
+ Example Output After Signing
686
+ ```json
687
+ {
688
+ "@context": [
689
+ "https://www.w3.org/2018/credentials/v1",
690
+ "https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v1.jsonld",
691
+ "https://w3id.org/vc/status-list/2021/v1",
692
+ "https://trustvc.io/context/render-method-context.json",
693
+ "https://w3id.org/security/bbs/v1"
694
+ ],
695
+ "type": ["VerifiableCredential"],
696
+ "credentialSubject": {
697
+ "id": "did:example:123",
698
+ "name": "John Doe"
699
+ },
700
+ "expirationDate": "2026-01-01T00:00:00Z",
701
+ "renderMethod": [
702
+ {
703
+ "id": "https://example.com/rendering-method",
704
+ "type": "EMBEDDED_RENDERER",
705
+ "templateName": "BILL_OF_LADING"
706
+ }
707
+ ],
708
+ "credentialStatus": {
709
+ "id": "https://example.com/status-list#<placeholder>",
710
+ "type": "StatusList2021Entry",
711
+ "statusPurpose": "revocation",
712
+ "statusListIndex": "<placeholder>",
713
+ "statusListCredential": "https://example.com/status-list"
714
+ },
715
+ "issuer": "did:example:456",
716
+ "issuanceDate": "2025-01-01T00:00:00Z",
717
+ "id": "urn:bnid:_:0195fec2-4ae1-7cca-9182-03fd7da5142b",
718
+ "proof": {
719
+ "type": "BbsBlsSignature2020",
720
+ "created": "2025-01-01T00:00:01Z",
721
+ "proofPurpose": "assertionMethod",
722
+ "proofValue": "rV56L+QYozATRy3GOVLomzUo99sXtw2x0Cy9dEkHJ15wi4cS12cQJRIwzONVi3YscdhaSKoqD1jWmwb5A/khLZnDq5eo3QzDgTVClYuV86opL3HJyoS4+t2rRt3wl+chnATy2jqr5zMEvcVJ3gdXpQ==",
723
+ "verificationMethod": "did:example:456#key1"
724
+ }
725
+ }
726
+ ```
727
+
728
+ ##### Verify the Document
729
+ To verify the signature of the signed document:
730
+
731
+ ```ts
732
+ const isVerified = await builder.verify();
733
+ console.log(isVerified); // true or false
734
+ ```
735
+
736
+ ##### Convert Document to JSON String
737
+ To get the current state of the document as a JSON string:
738
+
739
+ ```ts
740
+ const documentJson = builder.toString();
741
+ console.log(documentJson);
742
+ ```
@@ -28,57 +28,78 @@ class DocumentBuilder {
28
28
  // Holds the RPC provider URL for verifying token registry.
29
29
  requiredFields = ["credentialSubject"];
30
30
  // Required fields that must be present in the document.
31
+ isSigned = false;
32
+ // Tracks if a document is signed
31
33
  /**
32
34
  * Constructor to initialize the document builder.
33
35
  * @param {Partial<VerifiableCredential>} input - The input document.
34
36
  * @param {string} [documentType] - The type of the document (default is "w3c").
35
37
  */
36
38
  constructor(input, documentType = "w3c") {
37
- this.validateRequiredFields(input);
38
39
  this.document = this.initializeDocument(input);
39
40
  this.documentType = documentType;
40
41
  }
41
- // Public method to configure the document for transferable records. Sets up the token network and token registry.
42
- transferableRecords(config) {
43
- if (this.selectedStatusType) {
44
- throw new Error(
45
- "Configuration Error: You can only call either .transferableRecords() or .verifiableDocument(), not both."
46
- );
47
- }
48
- this.selectedStatusType = "transferableRecords";
49
- this.addContext("https://trustvc.io/context/transferable-records-context.json");
50
- this.statusConfig = {
51
- type: "TransferableRecords",
52
- tokenNetwork: { chain: config.chain, chainId: config.chainId },
53
- tokenRegistry: config.tokenRegistry
54
- };
55
- this.rpcProviderUrl = config.rpcProviderUrl;
42
+ // Sets the credential subject of the document.
43
+ credentialSubject(subject) {
44
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
45
+ this.document.credentialSubject = subject;
56
46
  return this;
57
47
  }
58
- // Public method to configure the document for verifiable credentials. Sets up the status list and revocation information.
59
- verifiableDocument(config) {
60
- if (this.selectedStatusType) {
48
+ // Configures the credential status of the document based on the provided type (Transferable Records or Verifiable Document).
49
+ credentialStatus(config) {
50
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
51
+ const isTransferable = this.isTransferableRecordsConfig(config);
52
+ const isVerifiable = this.isVerifiableDocumentConfig(config);
53
+ if (isTransferable && isVerifiable) {
61
54
  throw new Error(
62
- "Configuration Error: You can only call either .transferableRecords() or .verifiableDocument(), not both."
55
+ "Configuration Error: Do not mix transferable records and verifiable document properties."
63
56
  );
64
57
  }
65
- this.selectedStatusType = "verifiableDocument";
66
- this.addContext("https://w3id.org/vc/status-list/2021/v1");
67
- this.statusConfig = {
68
- id: `${config.url}#${config.index}`,
69
- type: "StatusList2021Entry",
70
- statusPurpose: config.purpose || "revocation",
71
- // Set status purpose to "revocation" by default.
72
- statusListIndex: config.index,
73
- statusListCredential: config.url
74
- };
58
+ if (isTransferable) {
59
+ this.selectedStatusType = "transferableRecords";
60
+ this.statusConfig = {
61
+ type: "TransferableRecords",
62
+ tokenNetwork: { chain: config.chain, chainId: config.chainId },
63
+ tokenRegistry: config.tokenRegistry
64
+ };
65
+ this.rpcProviderUrl = config.rpcProviderUrl;
66
+ this.addContext("https://trustvc.io/context/transferable-records-context.json");
67
+ } else if (isVerifiable) {
68
+ this.selectedStatusType = "verifiableDocument";
69
+ this.statusConfig = {
70
+ id: `${config.url}#${config.index}`,
71
+ type: "StatusList2021Entry",
72
+ statusPurpose: config.purpose || "revocation",
73
+ // Set status purpose to "revocation" by default.
74
+ statusListIndex: config.index,
75
+ statusListCredential: config.url
76
+ };
77
+ this.addContext("https://w3id.org/vc/status-list/2021/v1");
78
+ } else {
79
+ throw new Error("Configuration Error: Missing required fields for credential status.");
80
+ }
75
81
  return this;
76
82
  }
77
- // Public method to sign the document using the provided private key and an optional cryptographic suite.
83
+ // Sets the expiration date of the document.
84
+ expirationDate(date) {
85
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
86
+ this.document.expirationDate = typeof date === "string" ? date : date.toISOString();
87
+ return this;
88
+ }
89
+ // Defines the rendering method for the document.
90
+ renderMethod(method) {
91
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
92
+ this.document.renderMethod = [method];
93
+ this.addContext("https://trustvc.io/context/render-method-context.json");
94
+ return this;
95
+ }
96
+ // Sign the document using the provided private key and an optional cryptographic suite.
78
97
  async sign(privateKey, cryptoSuite) {
98
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
79
99
  if (this.selectedStatusType) {
80
100
  this.document.credentialStatus = this.statusConfig;
81
101
  }
102
+ this.validateRequiredFields(this.document);
82
103
  if (this.selectedStatusType === "verifiableDocument") {
83
104
  w3cCredentialStatus.assertCredentialStatus(this.document.credentialStatus);
84
105
  const verificationResult = await w3cVc.verifyCredentialStatus(this.document.credentialStatus);
@@ -95,8 +116,31 @@ class DocumentBuilder {
95
116
  this.addContext("https://w3id.org/security/bbs/v1");
96
117
  const signedVC = await w3c.signW3C(this.document, privateKey, cryptoSuite);
97
118
  if (signedVC.error) throw new Error(`Signing Error: ${signedVC.error}`);
119
+ this.isSigned = true;
98
120
  return signedVC.signed;
99
121
  }
122
+ // Verify the document.
123
+ async verify() {
124
+ if (!this.isSigned) throw new Error("Verification Error: Document is not signed yet.");
125
+ const verificationResult = await w3c.verifyW3CSignature(
126
+ this.document
127
+ );
128
+ if (verificationResult.error)
129
+ throw new Error(`Verification Error: ${verificationResult.error}`);
130
+ return verificationResult.verified;
131
+ }
132
+ // Returns the current state of the document as a JSON string.
133
+ toString() {
134
+ return JSON.stringify(this.document, null, 2);
135
+ }
136
+ // Type guard for transferable records configuration
137
+ isTransferableRecordsConfig(config) {
138
+ return config && typeof config.tokenRegistry === "string" && typeof config.chain === "string" && typeof config.chainId === "number" && typeof config.rpcProviderUrl === "string";
139
+ }
140
+ // Type guard for verifiable document configuration
141
+ isVerifiableDocumentConfig(config) {
142
+ return config && typeof config.url === "string" && typeof config.index === "number";
143
+ }
100
144
  // Private helper method to validate that the required fields are present in the input document.
101
145
  validateRequiredFields(input) {
102
146
  this.requiredFields.forEach((field) => {
@@ -107,6 +151,7 @@ class DocumentBuilder {
107
151
  }
108
152
  // Private helper method to initialize the document with required context and type, adding the necessary context URL.
109
153
  initializeDocument(input) {
154
+ if (input.proof) throw new Error("Configuration Error: Document is already signed.");
110
155
  return {
111
156
  ...input,
112
157
  "@context": this.buildContext(input["@context"]),
@@ -29,8 +29,17 @@ const calldata = /* @__PURE__ */ __name(async (provider, functionSignature, cont
29
29
  });
30
30
  return ethers$1.ethers.utils.getAddress(ethers$1.ethers.utils.hexDataSlice(result, 12));
31
31
  }, "calldata");
32
- const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleEscrowFactoryAddress, tokenRegistryAddress, tokenId) => {
32
+ const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleEscrowFactoryAddress, tokenRegistryAddress, tokenId, options) => {
33
33
  try {
34
+ if (options?.titleEscrowVersion === "v4") {
35
+ return await calldata(
36
+ provider,
37
+ "getAddress(address,uint256)",
38
+ titleEscrowFactoryAddress,
39
+ ["address", "uint256"],
40
+ [tokenRegistryAddress, tokenId]
41
+ );
42
+ }
34
43
  return await calldata(
35
44
  provider,
36
45
  "getEscrowAddress(address,uint256)",
@@ -39,6 +48,15 @@ const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleE
39
48
  [tokenRegistryAddress, tokenId]
40
49
  );
41
50
  } catch {
51
+ if (options?.titleEscrowVersion === "v4") {
52
+ return await calldata(
53
+ provider,
54
+ "getEscrowAddress(address,uint256)",
55
+ titleEscrowFactoryAddress,
56
+ ["address", "uint256"],
57
+ [tokenRegistryAddress, tokenId]
58
+ );
59
+ }
42
60
  return await calldata(
43
61
  provider,
44
62
  "getAddress(address,uint256)",
@@ -48,7 +66,7 @@ const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleE
48
66
  );
49
67
  }
50
68
  }, "resolveTitleEscrowAddress");
51
- const getTitleEscrowAddress = /* @__PURE__ */ __name(async (tokenRegistryAddress, tokenId, provider) => {
69
+ const getTitleEscrowAddress = /* @__PURE__ */ __name(async (tokenRegistryAddress, tokenId, provider, options) => {
52
70
  const Contract = ethers.getEthersContractFromProvider(provider);
53
71
  const tokenRegistryAbi = [
54
72
  "function titleEscrowFactory() external view returns (address)",
@@ -64,7 +82,8 @@ const getTitleEscrowAddress = /* @__PURE__ */ __name(async (tokenRegistryAddress
64
82
  provider,
65
83
  titleEscrowFactoryAddress,
66
84
  tokenRegistryAddress,
67
- tokenId
85
+ tokenId,
86
+ options
68
87
  );
69
88
  }, "getTitleEscrowAddress");
70
89
  const checkSupportsInterface = /* @__PURE__ */ __name(async (titleEscrowAddress, interfaceId, provider) => {
@@ -1,4 +1,4 @@
1
- import { signW3C } from '../w3c';
1
+ import { signW3C, verifyW3CSignature } from '../w3c';
2
2
  import { assertCredentialStatus, assertTransferableRecords } from '@trustvc/w3c-credential-status';
3
3
  import { verifyCredentialStatus } from '@trustvc/w3c-vc';
4
4
  import { ethers } from 'ethers';
@@ -26,57 +26,78 @@ class DocumentBuilder {
26
26
  // Holds the RPC provider URL for verifying token registry.
27
27
  requiredFields = ["credentialSubject"];
28
28
  // Required fields that must be present in the document.
29
+ isSigned = false;
30
+ // Tracks if a document is signed
29
31
  /**
30
32
  * Constructor to initialize the document builder.
31
33
  * @param {Partial<VerifiableCredential>} input - The input document.
32
34
  * @param {string} [documentType] - The type of the document (default is "w3c").
33
35
  */
34
36
  constructor(input, documentType = "w3c") {
35
- this.validateRequiredFields(input);
36
37
  this.document = this.initializeDocument(input);
37
38
  this.documentType = documentType;
38
39
  }
39
- // Public method to configure the document for transferable records. Sets up the token network and token registry.
40
- transferableRecords(config) {
41
- if (this.selectedStatusType) {
42
- throw new Error(
43
- "Configuration Error: You can only call either .transferableRecords() or .verifiableDocument(), not both."
44
- );
45
- }
46
- this.selectedStatusType = "transferableRecords";
47
- this.addContext("https://trustvc.io/context/transferable-records-context.json");
48
- this.statusConfig = {
49
- type: "TransferableRecords",
50
- tokenNetwork: { chain: config.chain, chainId: config.chainId },
51
- tokenRegistry: config.tokenRegistry
52
- };
53
- this.rpcProviderUrl = config.rpcProviderUrl;
40
+ // Sets the credential subject of the document.
41
+ credentialSubject(subject) {
42
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
43
+ this.document.credentialSubject = subject;
54
44
  return this;
55
45
  }
56
- // Public method to configure the document for verifiable credentials. Sets up the status list and revocation information.
57
- verifiableDocument(config) {
58
- if (this.selectedStatusType) {
46
+ // Configures the credential status of the document based on the provided type (Transferable Records or Verifiable Document).
47
+ credentialStatus(config) {
48
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
49
+ const isTransferable = this.isTransferableRecordsConfig(config);
50
+ const isVerifiable = this.isVerifiableDocumentConfig(config);
51
+ if (isTransferable && isVerifiable) {
59
52
  throw new Error(
60
- "Configuration Error: You can only call either .transferableRecords() or .verifiableDocument(), not both."
53
+ "Configuration Error: Do not mix transferable records and verifiable document properties."
61
54
  );
62
55
  }
63
- this.selectedStatusType = "verifiableDocument";
64
- this.addContext("https://w3id.org/vc/status-list/2021/v1");
65
- this.statusConfig = {
66
- id: `${config.url}#${config.index}`,
67
- type: "StatusList2021Entry",
68
- statusPurpose: config.purpose || "revocation",
69
- // Set status purpose to "revocation" by default.
70
- statusListIndex: config.index,
71
- statusListCredential: config.url
72
- };
56
+ if (isTransferable) {
57
+ this.selectedStatusType = "transferableRecords";
58
+ this.statusConfig = {
59
+ type: "TransferableRecords",
60
+ tokenNetwork: { chain: config.chain, chainId: config.chainId },
61
+ tokenRegistry: config.tokenRegistry
62
+ };
63
+ this.rpcProviderUrl = config.rpcProviderUrl;
64
+ this.addContext("https://trustvc.io/context/transferable-records-context.json");
65
+ } else if (isVerifiable) {
66
+ this.selectedStatusType = "verifiableDocument";
67
+ this.statusConfig = {
68
+ id: `${config.url}#${config.index}`,
69
+ type: "StatusList2021Entry",
70
+ statusPurpose: config.purpose || "revocation",
71
+ // Set status purpose to "revocation" by default.
72
+ statusListIndex: config.index,
73
+ statusListCredential: config.url
74
+ };
75
+ this.addContext("https://w3id.org/vc/status-list/2021/v1");
76
+ } else {
77
+ throw new Error("Configuration Error: Missing required fields for credential status.");
78
+ }
73
79
  return this;
74
80
  }
75
- // Public method to sign the document using the provided private key and an optional cryptographic suite.
81
+ // Sets the expiration date of the document.
82
+ expirationDate(date) {
83
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
84
+ this.document.expirationDate = typeof date === "string" ? date : date.toISOString();
85
+ return this;
86
+ }
87
+ // Defines the rendering method for the document.
88
+ renderMethod(method) {
89
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
90
+ this.document.renderMethod = [method];
91
+ this.addContext("https://trustvc.io/context/render-method-context.json");
92
+ return this;
93
+ }
94
+ // Sign the document using the provided private key and an optional cryptographic suite.
76
95
  async sign(privateKey, cryptoSuite) {
96
+ if (this.isSigned) throw new Error("Configuration Error: Document is already signed.");
77
97
  if (this.selectedStatusType) {
78
98
  this.document.credentialStatus = this.statusConfig;
79
99
  }
100
+ this.validateRequiredFields(this.document);
80
101
  if (this.selectedStatusType === "verifiableDocument") {
81
102
  assertCredentialStatus(this.document.credentialStatus);
82
103
  const verificationResult = await verifyCredentialStatus(this.document.credentialStatus);
@@ -93,8 +114,31 @@ class DocumentBuilder {
93
114
  this.addContext("https://w3id.org/security/bbs/v1");
94
115
  const signedVC = await signW3C(this.document, privateKey, cryptoSuite);
95
116
  if (signedVC.error) throw new Error(`Signing Error: ${signedVC.error}`);
117
+ this.isSigned = true;
96
118
  return signedVC.signed;
97
119
  }
120
+ // Verify the document.
121
+ async verify() {
122
+ if (!this.isSigned) throw new Error("Verification Error: Document is not signed yet.");
123
+ const verificationResult = await verifyW3CSignature(
124
+ this.document
125
+ );
126
+ if (verificationResult.error)
127
+ throw new Error(`Verification Error: ${verificationResult.error}`);
128
+ return verificationResult.verified;
129
+ }
130
+ // Returns the current state of the document as a JSON string.
131
+ toString() {
132
+ return JSON.stringify(this.document, null, 2);
133
+ }
134
+ // Type guard for transferable records configuration
135
+ isTransferableRecordsConfig(config) {
136
+ return config && typeof config.tokenRegistry === "string" && typeof config.chain === "string" && typeof config.chainId === "number" && typeof config.rpcProviderUrl === "string";
137
+ }
138
+ // Type guard for verifiable document configuration
139
+ isVerifiableDocumentConfig(config) {
140
+ return config && typeof config.url === "string" && typeof config.index === "number";
141
+ }
98
142
  // Private helper method to validate that the required fields are present in the input document.
99
143
  validateRequiredFields(input) {
100
144
  this.requiredFields.forEach((field) => {
@@ -105,6 +149,7 @@ class DocumentBuilder {
105
149
  }
106
150
  // Private helper method to initialize the document with required context and type, adding the necessary context URL.
107
151
  initializeDocument(input) {
152
+ if (input.proof) throw new Error("Configuration Error: Document is already signed.");
108
153
  return {
109
154
  ...input,
110
155
  "@context": this.buildContext(input["@context"]),
@@ -27,8 +27,17 @@ const calldata = /* @__PURE__ */ __name(async (provider, functionSignature, cont
27
27
  });
28
28
  return ethers.utils.getAddress(ethers.utils.hexDataSlice(result, 12));
29
29
  }, "calldata");
30
- const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleEscrowFactoryAddress, tokenRegistryAddress, tokenId) => {
30
+ const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleEscrowFactoryAddress, tokenRegistryAddress, tokenId, options) => {
31
31
  try {
32
+ if (options?.titleEscrowVersion === "v4") {
33
+ return await calldata(
34
+ provider,
35
+ "getAddress(address,uint256)",
36
+ titleEscrowFactoryAddress,
37
+ ["address", "uint256"],
38
+ [tokenRegistryAddress, tokenId]
39
+ );
40
+ }
32
41
  return await calldata(
33
42
  provider,
34
43
  "getEscrowAddress(address,uint256)",
@@ -37,6 +46,15 @@ const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleE
37
46
  [tokenRegistryAddress, tokenId]
38
47
  );
39
48
  } catch {
49
+ if (options?.titleEscrowVersion === "v4") {
50
+ return await calldata(
51
+ provider,
52
+ "getEscrowAddress(address,uint256)",
53
+ titleEscrowFactoryAddress,
54
+ ["address", "uint256"],
55
+ [tokenRegistryAddress, tokenId]
56
+ );
57
+ }
40
58
  return await calldata(
41
59
  provider,
42
60
  "getAddress(address,uint256)",
@@ -46,7 +64,7 @@ const resolveTitleEscrowAddress = /* @__PURE__ */ __name(async (provider, titleE
46
64
  );
47
65
  }
48
66
  }, "resolveTitleEscrowAddress");
49
- const getTitleEscrowAddress = /* @__PURE__ */ __name(async (tokenRegistryAddress, tokenId, provider) => {
67
+ const getTitleEscrowAddress = /* @__PURE__ */ __name(async (tokenRegistryAddress, tokenId, provider, options) => {
50
68
  const Contract = getEthersContractFromProvider(provider);
51
69
  const tokenRegistryAbi = [
52
70
  "function titleEscrowFactory() external view returns (address)",
@@ -62,7 +80,8 @@ const getTitleEscrowAddress = /* @__PURE__ */ __name(async (tokenRegistryAddress
62
80
  provider,
63
81
  titleEscrowFactoryAddress,
64
82
  tokenRegistryAddress,
65
- tokenId
83
+ tokenId,
84
+ options
66
85
  );
67
86
  }, "getTitleEscrowAddress");
68
87
  const checkSupportsInterface = /* @__PURE__ */ __name(async (titleEscrowAddress, interfaceId, provider) => {
@@ -1,6 +1,5 @@
1
- import * as _trustvc_w3c_vc from '@trustvc/w3c-vc';
2
- import { VerifiableCredential } from '@trustvc/w3c-vc';
3
1
  import { PrivateKeyPair } from '@trustvc/w3c-issuer';
2
+ import { VerifiableCredential, SignedVerifiableCredential } from '@trustvc/w3c-vc';
4
3
 
5
4
  interface W3CVerifiableDocumentConfig {
6
5
  url: string;
@@ -13,6 +12,11 @@ interface W3CTransferableRecordsConfig {
13
12
  tokenRegistry: string;
14
13
  rpcProviderUrl: string;
15
14
  }
15
+ interface RenderMethod {
16
+ id: string;
17
+ type: string;
18
+ templateName: string;
19
+ }
16
20
  declare class DocumentBuilder {
17
21
  private document;
18
22
  private documentType;
@@ -20,10 +24,17 @@ declare class DocumentBuilder {
20
24
  private statusConfig;
21
25
  private rpcProviderUrl;
22
26
  private requiredFields;
27
+ private isSigned;
23
28
  constructor(input: Partial<VerifiableCredential>, documentType?: string);
24
- transferableRecords(config: W3CTransferableRecordsConfig): this;
25
- verifiableDocument(config: W3CVerifiableDocumentConfig): this;
26
- sign(privateKey: PrivateKeyPair, cryptoSuite?: string): Promise<_trustvc_w3c_vc.SignedVerifiableCredential>;
29
+ credentialSubject(subject: Partial<VerifiableCredential>): this;
30
+ credentialStatus(config: W3CTransferableRecordsConfig | W3CVerifiableDocumentConfig): this;
31
+ expirationDate(date: string | Date): this;
32
+ renderMethod(method: RenderMethod): this;
33
+ sign(privateKey: PrivateKeyPair, cryptoSuite?: string): Promise<SignedVerifiableCredential>;
34
+ verify(): Promise<boolean>;
35
+ toString(): string;
36
+ private isTransferableRecordsConfig;
37
+ private isVerifiableDocumentConfig;
27
38
  private validateRequiredFields;
28
39
  private initializeDocument;
29
40
  private buildContext;
@@ -32,4 +43,4 @@ declare class DocumentBuilder {
32
43
  private supportsInterface;
33
44
  }
34
45
 
35
- export { DocumentBuilder, type W3CTransferableRecordsConfig, type W3CVerifiableDocumentConfig };
46
+ export { DocumentBuilder, type RenderMethod, type W3CTransferableRecordsConfig, type W3CVerifiableDocumentConfig };
@@ -8,7 +8,9 @@ declare const TitleEscrowInterface: {
8
8
  V4: string;
9
9
  V5: string;
10
10
  };
11
- declare const getTitleEscrowAddress: (tokenRegistryAddress: string, tokenId: string, provider: Provider | ethers.Provider) => Promise<string>;
11
+ declare const getTitleEscrowAddress: (tokenRegistryAddress: string, tokenId: string, provider: Provider | ethers.Provider, options?: {
12
+ titleEscrowVersion?: "v4" | "v5";
13
+ }) => Promise<string>;
12
14
  interface TitleEscrowVersionParams {
13
15
  tokenRegistryAddress?: string;
14
16
  tokenId?: string;
@@ -7,7 +7,7 @@ export { fetchEventTime, mergeTransfersV4, mergeTransfersV5, sortLogChain } from
7
7
  export { getEndorsementChain } from './endorsement-chain/retrieveEndorsementChain.js';
8
8
  export { EndorsementChain, ParsedLog, TitleEscrowTransferEvent, TitleEscrowTransferEventType, TokenTransferEvent, TokenTransferEventType, TradeTrustTokenEventType, TransferBaseEvent, TransferEvent, TransferEventType, TypedEvent } from './endorsement-chain/types.js';
9
9
  export { TitleEscrowInterface, fetchEndorsementChain, getTitleEscrowAddress, isTitleEscrowVersion } from './endorsement-chain/useEndorsementChain.js';
10
- export { DocumentBuilder, W3CTransferableRecordsConfig, W3CVerifiableDocumentConfig } from './documentBuilder.js';
10
+ export { DocumentBuilder, RenderMethod, W3CTransferableRecordsConfig, W3CVerifiableDocumentConfig } from './documentBuilder.js';
11
11
  import '@trustvc/w3c-vc';
12
12
  import '@tradetrust-tt/tt-verify/dist/types/src/types/core';
13
13
  import 'ethersV6';
@@ -1,4 +1,4 @@
1
- import * as _trustvc_w3c_vc from '@trustvc/w3c-vc';
1
+ import * as w3cVc from '@trustvc/w3c-vc';
2
2
 
3
3
  function _mergeNamespaces(n, m) {
4
4
  m.forEach(function (e) {
@@ -17,6 +17,6 @@ function _mergeNamespaces(n, m) {
17
17
 
18
18
  var index = /*#__PURE__*/_mergeNamespaces({
19
19
  __proto__: null
20
- }, [_trustvc_w3c_vc]);
20
+ }, [w3cVc]);
21
21
 
22
22
  export { index as i };
@@ -19,7 +19,7 @@ export { fetchEventTime, mergeTransfersV4, mergeTransfersV5, sortLogChain } from
19
19
  export { getEndorsementChain } from './core/endorsement-chain/retrieveEndorsementChain.js';
20
20
  export { EndorsementChain, ParsedLog, TitleEscrowTransferEvent, TitleEscrowTransferEventType, TokenTransferEvent, TokenTransferEventType, TradeTrustTokenEventType, TransferBaseEvent, TransferEvent, TransferEventType, TypedEvent } from './core/endorsement-chain/types.js';
21
21
  export { TitleEscrowInterface, fetchEndorsementChain, getTitleEscrowAddress, isTitleEscrowVersion } from './core/endorsement-chain/useEndorsementChain.js';
22
- export { DocumentBuilder, W3CTransferableRecordsConfig, W3CVerifiableDocumentConfig } from './core/documentBuilder.js';
22
+ export { DocumentBuilder, RenderMethod, W3CTransferableRecordsConfig, W3CVerifiableDocumentConfig } from './core/documentBuilder.js';
23
23
  export { signOA } from './open-attestation/sign.js';
24
24
  export { KeyPair } from './open-attestation/types.js';
25
25
  export { diagnose, getAssetId, getDocumentData, getIssuerAddress, getTemplateURL, isObfuscated, isRawV2Document, isRawV3Document, isSignedWrappedV2Document, isSignedWrappedV3Document, isTransferableAsset, isWrappedV2Document, isWrappedV3Document } from './open-attestation/utils.js';
@@ -33,7 +33,7 @@ export { i as isser } from './index-ClF4_Nqk.js';
33
33
  export { signW3C } from './w3c/sign.js';
34
34
  export { RawVerifiableCredential, SignedVerifiableCredential, SigningResult, VerificationResult } from '@trustvc/w3c-vc';
35
35
  export { PrivateKeyPair } from '@trustvc/w3c-issuer';
36
- export { i as vc } from './index-Bc5NlE8f.js';
36
+ export { i as vc } from './index-1ws_BWZW.js';
37
37
  export { verifyW3CSignature } from './w3c/verify.js';
38
38
  export { errorMessageHandling, CONSTANTS as errorMessages, interpretFragments } from '@tradetrust-tt/tradetrust-utils';
39
39
  export * from '@tradetrust-tt/tradetrust-utils/constants/network';
@@ -4,7 +4,7 @@ export { i as isser } from '../index-ClF4_Nqk.js';
4
4
  export { signW3C } from './sign.js';
5
5
  export { RawVerifiableCredential, SignedVerifiableCredential, SigningResult, VerificationResult } from '@trustvc/w3c-vc';
6
6
  export { PrivateKeyPair } from '@trustvc/w3c-issuer';
7
- export { i as vc } from '../index-Bc5NlE8f.js';
7
+ export { i as vc } from '../index-1ws_BWZW.js';
8
8
  export { verifyW3CSignature } from './verify.js';
9
9
  import '@trustvc/w3c-context';
10
10
  import '@trustvc/w3c-credential-status';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trustvc/trustvc",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "TrustVC library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -116,10 +116,10 @@
116
116
  "@tradetrust-tt/tradetrust": "^6.10.1",
117
117
  "@tradetrust-tt/tradetrust-utils": "^2.2.1",
118
118
  "@tradetrust-tt/tt-verify": "^9.3.1",
119
- "@trustvc/w3c-context": "^1.2.1",
120
- "@trustvc/w3c-credential-status": "^1.2.1",
119
+ "@trustvc/w3c-context": "^1.2.2",
120
+ "@trustvc/w3c-credential-status": "^1.2.2",
121
121
  "@trustvc/w3c-issuer": "^1.2.1",
122
- "@trustvc/w3c-vc": "^1.2.3",
122
+ "@trustvc/w3c-vc": "^1.2.4",
123
123
  "did-resolver": "^4.1.0",
124
124
  "ethers": "^5.7.2",
125
125
  "ethersV6": "npm:ethers@^6.13.5",