@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 +153 -0
- package/dist/cjs/core/documentBuilder.js +76 -31
- package/dist/cjs/core/endorsement-chain/useEndorsementChain.js +22 -3
- package/dist/esm/core/documentBuilder.js +77 -32
- package/dist/esm/core/endorsement-chain/useEndorsementChain.js +22 -3
- package/dist/types/core/documentBuilder.d.ts +17 -6
- package/dist/types/core/endorsement-chain/useEndorsementChain.d.ts +3 -1
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/{index-Bc5NlE8f.d.ts → index-1ws_BWZW.d.ts} +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/w3c/index.d.ts +1 -1
- package/package.json +4 -4
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
|
-
//
|
|
42
|
-
|
|
43
|
-
if (this.
|
|
44
|
-
|
|
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
|
-
//
|
|
59
|
-
|
|
60
|
-
if (this.
|
|
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:
|
|
55
|
+
"Configuration Error: Do not mix transferable records and verifiable document properties."
|
|
63
56
|
);
|
|
64
57
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
40
|
-
|
|
41
|
-
if (this.
|
|
42
|
-
|
|
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
|
-
//
|
|
57
|
-
|
|
58
|
-
if (this.
|
|
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:
|
|
53
|
+
"Configuration Error: Do not mix transferable records and verifiable document properties."
|
|
61
54
|
);
|
|
62
55
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
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
|
|
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
|
-
}, [
|
|
20
|
+
}, [w3cVc]);
|
|
21
21
|
|
|
22
22
|
export { index as i };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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-
|
|
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-
|
|
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
|
+
"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.
|
|
120
|
-
"@trustvc/w3c-credential-status": "^1.2.
|
|
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.
|
|
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",
|