-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e292fc6
commit 85d3cd1
Showing
5 changed files
with
166 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,160 @@ | ||
import { Issuer } from "@govtechsg/open-attestation/dist/types/__generated__/schema.2.0"; | ||
import { Issuer, RevocationType } from "@govtechsg/open-attestation/dist/types/__generated__/schema.2.0"; | ||
import fs from "fs"; | ||
import path from "path"; | ||
import { info } from "signale"; | ||
import { info, success } from "signale"; | ||
import { highlight } from "../../utils"; | ||
import { readFile } from "../../implementations/utils/disk"; | ||
import { handler as createTemporaryDns } from "../../commands/dns/txt-record/create"; | ||
import { CreateConfigCommand } from "../../commands/config/config.type"; | ||
import { ConfigFile, TypesOfForms } from "./types"; | ||
import { ConfigFile, Form } from "./types"; | ||
import { Wallet } from "ethers"; | ||
import { getDocumentStoreOrTokenRegistryAddress, updateConfigFile, updateForms, getConfigFile } from "./helpers"; | ||
import tradetrustConfig from "./templates/tradetrust.json"; | ||
import { deployDocumentStore } from "../../implementations/deploy/document-store"; | ||
import { deployTokenRegistry } from "../../implementations/deploy/token-registry"; | ||
|
||
const sandboxEndpointUrl = "https://sandbox.fyntech.io"; | ||
const SANDBOX_ENDPOINT_URL = "https://sandbox.fyntech.io"; | ||
|
||
const getConfigFile = async (configType: string, configTemplatePath: string): Promise<ConfigFile> => { | ||
switch (configType) { | ||
case "tradetrust": | ||
return tradetrustConfig as ConfigFile; | ||
default: | ||
return JSON.parse(await readFile(configTemplatePath)); | ||
} | ||
}; | ||
|
||
const getTokenRegistryAddress = async (encryptedWalletPath: string): Promise<string> => { | ||
info(`Enter password to continue deployment of Token Registry`); | ||
const tokenRegistry = await deployTokenRegistry({ | ||
encryptedWalletPath, | ||
network: "ropsten", | ||
gasPriceScale: 1, | ||
dryRun: false, | ||
registryName: "Token Registry", | ||
registrySymbol: "TR", | ||
}); | ||
const { contractAddress } = tokenRegistry; | ||
success(`Token registry deployed, address: ${highlight(contractAddress)}`); | ||
return contractAddress; | ||
}; | ||
|
||
const getDocumentStoreAddress = async (encryptedWalletPath: string): Promise<string> => { | ||
info(`Enter password to continue deployment of Document Store`); | ||
const documentStore = await deployDocumentStore({ | ||
encryptedWalletPath, | ||
network: "ropsten", | ||
gasPriceScale: 1, | ||
dryRun: false, | ||
storeName: "Document Store", | ||
}); | ||
const { contractAddress } = documentStore; | ||
success(`Document store deployed, address: ${highlight(contractAddress)}`); | ||
return contractAddress; | ||
}; | ||
|
||
const validate = (forms: Form[]): boolean => { | ||
const isValidForm = forms.some((form: Form) => { | ||
const isValidFormType = form.type === "TRANSFERABLE_RECORD" && "VERIFIABLE_DOCUMENT"; | ||
const isValidIdentityProofType = form.defaults.issuers.some( | ||
(issuer: any) => issuer.identityProof?.type === "DNS-TXT" && "DNS-DID" && "DID" | ||
); | ||
|
||
return isValidFormType && isValidIdentityProofType; | ||
}); | ||
|
||
return isValidForm; | ||
}; | ||
|
||
export const create = async ({ | ||
encryptedWalletPath, | ||
outputDir, | ||
configType, | ||
configTemplatePath, | ||
}: CreateConfigCommand): Promise<string | undefined> => { | ||
}: CreateConfigCommand): Promise<string> => { | ||
const wallet = await readFile(encryptedWalletPath); | ||
const walletObject = JSON.parse(wallet) as Wallet; | ||
|
||
info(`Wallet detected at ${encryptedWalletPath}`); | ||
|
||
const configFile: ConfigFile = await getConfigFile(configType, configTemplatePath); | ||
|
||
const configFile = await getConfigFile(configType, configTemplatePath); | ||
const { forms } = configFile; | ||
|
||
const getContractAddress = async ( | ||
typesOfForms: TypesOfForms[], | ||
formType: "VERIFIABLE_DOCUMENT" | "TRANSFERABLE_RECORD", | ||
identityProofType: "DNS-DID" | "DNS-TXT" | ||
): Promise<string> => { | ||
const isValidForm = typesOfForms.some( | ||
(item: TypesOfForms) => | ||
item.type === formType && (<any>Object).values(item.identityProofTypes).includes(identityProofType) | ||
); | ||
if (!validate(forms)) { | ||
throw new Error("Invalid form detected in config file, please update the form before proceeding."); | ||
} | ||
|
||
if (!isValidForm) | ||
throw new Error("Invalid form detected in config file, please update the form before proceeding."); | ||
|
||
switch (true) { | ||
case formType === "TRANSFERABLE_RECORD": | ||
case formType === "VERIFIABLE_DOCUMENT" && identityProofType === "DNS-TXT": | ||
return await getDocumentStoreOrTokenRegistryAddress(encryptedWalletPath, formType); | ||
|
||
case formType === "VERIFIABLE_DOCUMENT" && identityProofType === "DNS-DID": | ||
info(`Creating temporary DNS for DID`); | ||
return ( | ||
(await createTemporaryDns({ | ||
networkId: 3, | ||
publicKey: `did:ethr:0x${walletObject.address}#controller`, | ||
sandboxEndpoint: sandboxEndpointUrl, | ||
})) || "" | ||
); | ||
|
||
default: | ||
throw new Error("Invalid form detected in config file, please update the form before proceeding."); | ||
} | ||
}; | ||
const hasTransferableRecord = forms.some((form) => form.type === "TRANSFERABLE_RECORD"); | ||
const hasDocumentStore = forms.some((form) => form.type === "VERIFIABLE_DOCUMENT"); | ||
const hasDid = forms.some((form) => | ||
form.defaults.issuers.some((issuer) => issuer.identityProof?.type.includes("DID")) | ||
); | ||
|
||
// loop through the form template to check the type of forms | ||
const typesOfForms: TypesOfForms[] = forms.map((form) => { | ||
const identityProofTypes = form.defaults.issuers.map((issuer: Issuer) => issuer.identityProof?.type); | ||
return { | ||
type: form.type, | ||
identityProofTypes: identityProofTypes, | ||
}; | ||
}); | ||
let tokenRegistryAddress = ""; | ||
let documentStoreAddress = ""; | ||
let dnsNameTransferableRecord: string | undefined = ""; | ||
let dnsNameVerifiable: string | undefined = ""; | ||
let dnsNameDid: string | undefined = ""; | ||
|
||
// generate doc store, token registry and DNS based on the form type in the form template | ||
const documentStoreAddress = await getContractAddress(typesOfForms, "VERIFIABLE_DOCUMENT", "DNS-TXT"); | ||
const verifiableDocumentDnsTxtName = documentStoreAddress | ||
? await createTemporaryDns({ networkId: 3, address: documentStoreAddress, sandboxEndpoint: sandboxEndpointUrl }) | ||
: ""; | ||
const verifiableDocumentDnsDidName = await getContractAddress(typesOfForms, "VERIFIABLE_DOCUMENT", "DNS-DID"); | ||
const tokenRegistryAddress = await getContractAddress(typesOfForms, "TRANSFERABLE_RECORD", "DNS-TXT"); | ||
const tokenRegistryDnsName = tokenRegistryAddress | ||
? await createTemporaryDns({ networkId: 3, address: tokenRegistryAddress, sandboxEndpoint: sandboxEndpointUrl }) | ||
: ""; | ||
|
||
const updatedForms = updateForms( | ||
forms, | ||
documentStoreAddress, | ||
tokenRegistryAddress, | ||
walletObject, | ||
verifiableDocumentDnsTxtName || "", | ||
verifiableDocumentDnsDidName, | ||
tokenRegistryDnsName || "" | ||
); | ||
if (hasTransferableRecord) { | ||
tokenRegistryAddress = await getTokenRegistryAddress(encryptedWalletPath); | ||
dnsNameTransferableRecord = await createTemporaryDns({ | ||
networkId: 3, | ||
address: tokenRegistryAddress, | ||
sandboxEndpoint: SANDBOX_ENDPOINT_URL, | ||
}); | ||
} | ||
|
||
const updatedConfigFile = updateConfigFile(configFile, wallet, updatedForms); | ||
if (hasDocumentStore) { | ||
documentStoreAddress = await getDocumentStoreAddress(encryptedWalletPath); | ||
dnsNameVerifiable = await createTemporaryDns({ | ||
networkId: 3, | ||
address: documentStoreAddress, | ||
sandboxEndpoint: SANDBOX_ENDPOINT_URL, | ||
}); | ||
} | ||
|
||
const configFileName = "config.json"; | ||
const outputPath = path.join(outputDir, configFileName); | ||
if (hasDid) { | ||
// DID no need deploy any | ||
dnsNameDid = await createTemporaryDns({ | ||
networkId: 3, | ||
publicKey: `did:ethr:0x${walletObject.address}#controller`, | ||
sandboxEndpoint: SANDBOX_ENDPOINT_URL, | ||
}); | ||
} | ||
|
||
const updatedForms = forms.map((form) => { | ||
if (form.type === "VERIFIABLE_DOCUMENT") { | ||
const updatedIssuers = form.defaults.issuers.map((issuer: Issuer) => { | ||
if (issuer.identityProof?.type === "DNS-TXT") { | ||
issuer.documentStore = documentStoreAddress; | ||
if (issuer.identityProof?.location) issuer.identityProof.location = dnsNameVerifiable; | ||
} else if (issuer.identityProof?.type.includes("DID")) { | ||
issuer.id = `did:ethr:0x${walletObject.address}`; | ||
if (issuer.revocation?.type) issuer.revocation.type = "NONE" as RevocationType; | ||
if (issuer.identityProof?.location) issuer.identityProof.location = dnsNameDid; | ||
if (issuer.identityProof?.key) issuer.identityProof.key = `did:ethr:0x${walletObject.address}#controller`; | ||
} | ||
return issuer; | ||
}); | ||
form.defaults.issuers = updatedIssuers; | ||
} | ||
if (form.type === "TRANSFERABLE_RECORD") { | ||
const updatedIssuers = form.defaults.issuers.map((issuer: Issuer) => { | ||
issuer.tokenRegistry = tokenRegistryAddress; | ||
if (issuer.identityProof?.location) issuer.identityProof.location = dnsNameTransferableRecord; | ||
return issuer; | ||
}); | ||
form.defaults.issuers = updatedIssuers; | ||
} | ||
return form; | ||
}); | ||
|
||
const updatedConfigFile = { | ||
...configFile, | ||
wallet: { ...configFile.wallet, encryptedJson: wallet }, | ||
forms: updatedForms, | ||
}; | ||
const outputPath = path.join(outputDir, "config.json"); | ||
fs.writeFileSync(outputPath, JSON.stringify(updatedConfigFile, null, 2)); | ||
|
||
return outputPath; | ||
}; |
Oops, something went wrong.