@vlayer/sdk 0.1.0-nightly-20250127-5ee6ca8 → 0.1.0-nightly-20250128-0a32cfc
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/package.json +2 -1
- package/src/api/email/dnsResolver.test.ts +19 -0
- package/src/api/email/dnsResolver.ts +87 -0
- package/src/api/email/parseEmail.test.ts +133 -0
- package/src/api/email/parseEmail.ts +55 -0
- package/src/api/email/preverify.test.ts +201 -0
- package/src/api/email/preverify.ts +70 -0
- package/src/api/email/testdata/test_email.txt +21 -0
- package/src/api/email/testdata/test_email_multiple_dkims.txt +28 -0
- package/src/api/email/testdata/test_email_subdomain.txt +21 -0
- package/src/api/email/testdata/test_email_unknown_domain.txt +21 -0
- package/src/api/lib/client.test.ts +261 -0
- package/src/api/lib/client.ts +191 -0
- package/src/api/lib/errors.ts +19 -0
- package/src/api/lib/types/ethereum.ts +45 -0
- package/src/api/lib/types/index.ts +3 -0
- package/src/api/lib/types/viem.ts +26 -0
- package/src/api/lib/types/vlayer.ts +156 -0
- package/src/api/lib/types/webProofProvider.ts +68 -0
- package/src/api/prover.ts +120 -0
- package/src/api/utils/prefixAllButNthSubstring.test.ts +24 -0
- package/src/api/utils/prefixAllButNthSubstring.ts +13 -0
- package/src/api/utils/versions.test.ts +52 -0
- package/src/api/utils/versions.ts +31 -0
- package/src/api/v_call.ts +58 -0
- package/src/api/v_getProofReceipt.ts +48 -0
- package/src/api/v_versions.ts +68 -0
- package/src/api/webProof/createWebProofRequest.ts +15 -0
- package/src/api/webProof/index.ts +3 -0
- package/src/api/webProof/providers/extension.test.ts +122 -0
- package/src/api/webProof/providers/extension.ts +197 -0
- package/src/api/webProof/providers/index.ts +1 -0
- package/src/api/webProof/steps/expectUrl.ts +12 -0
- package/src/api/webProof/steps/index.ts +11 -0
- package/src/api/webProof/steps/notarize.ts +20 -0
- package/src/api/webProof/steps/startPage.ts +12 -0
- package/src/config/createContext.ts +69 -0
- package/src/config/deploy.ts +108 -0
- package/src/config/getChainConfirmations.ts +6 -0
- package/src/config/getConfig.ts +71 -0
- package/src/config/index.ts +5 -0
- package/src/config/types.ts +26 -0
- package/src/config/writeEnvVariables.ts +28 -0
- package/src/index.ts +7 -0
- package/src/testHelpers/readFile.ts +3 -0
- package/src/web-proof-commons/index.ts +3 -0
- package/src/web-proof-commons/types/message.ts +176 -0
- package/src/web-proof-commons/types/redaction.test.ts +97 -0
- package/src/web-proof-commons/types/redaction.ts +201 -0
- package/src/web-proof-commons/utils.ts +11 -0
@@ -0,0 +1,197 @@
|
|
1
|
+
import {
|
2
|
+
type WebProofProvider,
|
3
|
+
type WebProofProviderSetup,
|
4
|
+
type WebProofRequestInput,
|
5
|
+
} from "../../lib/types/webProofProvider";
|
6
|
+
|
7
|
+
import {
|
8
|
+
EXTENSION_STEP,
|
9
|
+
ExtensionAction,
|
10
|
+
type ExtensionMessage,
|
11
|
+
ExtensionMessageType,
|
12
|
+
type WebProofStep,
|
13
|
+
type PresentationJSON,
|
14
|
+
ZkProvingStatus,
|
15
|
+
assertUrl,
|
16
|
+
assertUrlPattern,
|
17
|
+
type RedactionConfig,
|
18
|
+
RedactionItemsArray,
|
19
|
+
type MessageToExtension,
|
20
|
+
} from "../../../web-proof-commons";
|
21
|
+
|
22
|
+
import debug from "debug";
|
23
|
+
|
24
|
+
const log = debug("vlayer:WebProof:provider");
|
25
|
+
|
26
|
+
const EXTENSION_ID = "jbchhcgphfokabmfacnkafoeeeppjmpl";
|
27
|
+
|
28
|
+
declare let chrome: {
|
29
|
+
runtime: {
|
30
|
+
sendMessage: (
|
31
|
+
extensionId: string | undefined,
|
32
|
+
message: MessageToExtension,
|
33
|
+
) => void;
|
34
|
+
connect: (extensionId: string) => {
|
35
|
+
onMessage: {
|
36
|
+
addListener: (message: unknown) => void;
|
37
|
+
};
|
38
|
+
postMessage: (message: MessageToExtension) => void;
|
39
|
+
onDisconnect: {
|
40
|
+
addListener: (callback: () => void) => void;
|
41
|
+
};
|
42
|
+
};
|
43
|
+
};
|
44
|
+
};
|
45
|
+
|
46
|
+
class ExtensionWebProofProvider implements WebProofProvider {
|
47
|
+
private port: ReturnType<typeof chrome.runtime.connect> | null = null;
|
48
|
+
|
49
|
+
private listeners: Partial<
|
50
|
+
Record<
|
51
|
+
ExtensionMessageType,
|
52
|
+
((
|
53
|
+
args: Extract<ExtensionMessage, { type: ExtensionMessageType }>,
|
54
|
+
) => void)[]
|
55
|
+
>
|
56
|
+
> = {};
|
57
|
+
|
58
|
+
constructor(
|
59
|
+
private notaryUrl: string,
|
60
|
+
private wsProxyUrl: string,
|
61
|
+
) {}
|
62
|
+
|
63
|
+
public notifyZkProvingStatus(status: ZkProvingStatus) {
|
64
|
+
if (typeof chrome !== "undefined") {
|
65
|
+
// Chrome does not provide reliable api to check if given extension is installed
|
66
|
+
// what we could do is to use management api but
|
67
|
+
// 1) this will need to provided extra permission
|
68
|
+
// 2) still is not reliable because this api becomes defined when first extension that uses it is installed
|
69
|
+
// so still will need to try catch
|
70
|
+
try {
|
71
|
+
chrome.runtime.sendMessage(EXTENSION_ID, {
|
72
|
+
action: ExtensionAction.NotifyZkProvingStatus,
|
73
|
+
payload: { status },
|
74
|
+
});
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
76
|
+
} catch (e) {
|
77
|
+
log("Cant send message", "look that extension is not installed ");
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
private connectToExtension() {
|
83
|
+
if (!this.port) {
|
84
|
+
this.port = chrome.runtime.connect(EXTENSION_ID);
|
85
|
+
this.port.onDisconnect.addListener(() => {
|
86
|
+
this.port = null;
|
87
|
+
this.connectToExtension();
|
88
|
+
});
|
89
|
+
this.port.onMessage.addListener((message: ExtensionMessage) => {
|
90
|
+
if (message.type === ExtensionMessageType.ProofDone) {
|
91
|
+
this.listeners[ExtensionMessageType.ProofDone]?.forEach((cb) => {
|
92
|
+
cb(message);
|
93
|
+
});
|
94
|
+
}
|
95
|
+
if (message.type === ExtensionMessageType.ProofError) {
|
96
|
+
this.listeners[ExtensionMessageType.ProofError]?.forEach((cb) => {
|
97
|
+
cb(message);
|
98
|
+
});
|
99
|
+
}
|
100
|
+
});
|
101
|
+
}
|
102
|
+
return this.port;
|
103
|
+
}
|
104
|
+
|
105
|
+
public addEventListeners<T extends ExtensionMessageType>(
|
106
|
+
messageType: T,
|
107
|
+
listener: (args: Extract<ExtensionMessage, { type: T }>) => void,
|
108
|
+
) {
|
109
|
+
this.connectToExtension();
|
110
|
+
if (!this.listeners[messageType]) {
|
111
|
+
this.listeners[messageType] = [];
|
112
|
+
}
|
113
|
+
this.listeners[messageType].push(
|
114
|
+
listener as (args: ExtensionMessage) => void,
|
115
|
+
);
|
116
|
+
}
|
117
|
+
|
118
|
+
public requestWebProof(webProofRequest: WebProofRequestInput) {
|
119
|
+
validateWebProofRequest(webProofRequest);
|
120
|
+
this.connectToExtension().postMessage({
|
121
|
+
action: ExtensionAction.RequestWebProof,
|
122
|
+
payload: {
|
123
|
+
notaryUrl: this.notaryUrl,
|
124
|
+
wsProxyUrl: this.wsProxyUrl,
|
125
|
+
logoUrl: webProofRequest.logoUrl,
|
126
|
+
steps: webProofRequest.steps,
|
127
|
+
},
|
128
|
+
});
|
129
|
+
}
|
130
|
+
|
131
|
+
public async getWebProof(webProofRequest: WebProofRequestInput): Promise<{
|
132
|
+
presentationJSON: PresentationJSON;
|
133
|
+
decodedTranscript: {
|
134
|
+
sent: string;
|
135
|
+
recv: string;
|
136
|
+
};
|
137
|
+
}> {
|
138
|
+
return new Promise<{
|
139
|
+
presentationJSON: PresentationJSON;
|
140
|
+
decodedTranscript: {
|
141
|
+
sent: string;
|
142
|
+
recv: string;
|
143
|
+
};
|
144
|
+
}>((resolve, reject) => {
|
145
|
+
chrome.runtime.sendMessage(EXTENSION_ID, {
|
146
|
+
action: ExtensionAction.RequestWebProof,
|
147
|
+
payload: {
|
148
|
+
notaryUrl: this.notaryUrl,
|
149
|
+
wsProxyUrl: this.wsProxyUrl,
|
150
|
+
logoUrl: webProofRequest.logoUrl,
|
151
|
+
steps: webProofRequest.steps,
|
152
|
+
},
|
153
|
+
});
|
154
|
+
|
155
|
+
this.connectToExtension().onMessage.addListener(
|
156
|
+
(message: ExtensionMessage) => {
|
157
|
+
if (message.type === ExtensionMessageType.ProofDone) {
|
158
|
+
resolve(message.payload);
|
159
|
+
}
|
160
|
+
if (message.type === ExtensionMessageType.ProofError) {
|
161
|
+
reject(new Error(message.payload.error));
|
162
|
+
}
|
163
|
+
},
|
164
|
+
);
|
165
|
+
});
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
const validateSteps = (steps: WebProofStep[]) => {
|
170
|
+
steps.forEach((step) => {
|
171
|
+
if (step.step === EXTENSION_STEP.startPage) {
|
172
|
+
assertUrl(step.url);
|
173
|
+
} else {
|
174
|
+
assertUrlPattern(step.url);
|
175
|
+
}
|
176
|
+
if (step.step === EXTENSION_STEP.notarize) {
|
177
|
+
validateRedaction(step.redact ?? []);
|
178
|
+
}
|
179
|
+
});
|
180
|
+
};
|
181
|
+
|
182
|
+
const validateRedaction = (redaction: RedactionConfig) => {
|
183
|
+
RedactionItemsArray.parse(redaction);
|
184
|
+
};
|
185
|
+
|
186
|
+
export const validateWebProofRequest = (
|
187
|
+
webProofRequest: WebProofRequestInput,
|
188
|
+
) => {
|
189
|
+
validateSteps(webProofRequest.steps);
|
190
|
+
};
|
191
|
+
|
192
|
+
export const createExtensionWebProofProvider = ({
|
193
|
+
notaryUrl = "https://notary.pse.dev/v0.1.0-alpha.7",
|
194
|
+
wsProxyUrl = "wss://notary.pse.dev/proxy",
|
195
|
+
}: WebProofProviderSetup = {}): WebProofProvider => {
|
196
|
+
return new ExtensionWebProofProvider(notaryUrl, wsProxyUrl);
|
197
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from "./extension";
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import {
|
2
|
+
EXTENSION_STEP,
|
3
|
+
type WebProofStepExpectUrl,
|
4
|
+
} from "../../../web-proof-commons";
|
5
|
+
|
6
|
+
export const expectUrl = (url: string, label: string) => {
|
7
|
+
return {
|
8
|
+
url,
|
9
|
+
label,
|
10
|
+
step: EXTENSION_STEP.expectUrl,
|
11
|
+
} as WebProofStepExpectUrl;
|
12
|
+
};
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import {
|
2
|
+
EXTENSION_STEP,
|
3
|
+
type WebProofStepNotarize,
|
4
|
+
type RedactionConfig,
|
5
|
+
} from "../../../web-proof-commons";
|
6
|
+
|
7
|
+
export const notarize = (
|
8
|
+
url: string,
|
9
|
+
method: string = "GET",
|
10
|
+
label: string,
|
11
|
+
redact?: RedactionConfig,
|
12
|
+
) => {
|
13
|
+
return {
|
14
|
+
url,
|
15
|
+
method,
|
16
|
+
label,
|
17
|
+
redact: redact ?? [],
|
18
|
+
step: EXTENSION_STEP.notarize,
|
19
|
+
} as WebProofStepNotarize;
|
20
|
+
};
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import {
|
2
|
+
EXTENSION_STEP,
|
3
|
+
type WebProofStepStartPage,
|
4
|
+
} from "../../../web-proof-commons";
|
5
|
+
|
6
|
+
export const startPage = (url: string, label: string) => {
|
7
|
+
return {
|
8
|
+
url,
|
9
|
+
label,
|
10
|
+
step: EXTENSION_STEP.startPage,
|
11
|
+
} as WebProofStepStartPage;
|
12
|
+
};
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import {
|
2
|
+
type Chain,
|
3
|
+
createWalletClient,
|
4
|
+
http,
|
5
|
+
publicActions,
|
6
|
+
type CustomTransport,
|
7
|
+
custom,
|
8
|
+
type PrivateKeyAccount,
|
9
|
+
} from "viem";
|
10
|
+
import { privateKeyToAccount } from "viem/accounts";
|
11
|
+
import { getChainConfirmations } from "./getChainConfirmations";
|
12
|
+
import * as chains from "viem/chains";
|
13
|
+
import type { EnvConfig, VlayerContextConfig } from "./types";
|
14
|
+
|
15
|
+
const getChainSpecs = (chainName: string): Chain => {
|
16
|
+
try {
|
17
|
+
return chains[chainName as keyof typeof chains] as Chain;
|
18
|
+
} catch {
|
19
|
+
throw Error(`Cannot import ${chainName} from viem/chains`);
|
20
|
+
}
|
21
|
+
};
|
22
|
+
|
23
|
+
export const customTransport = custom;
|
24
|
+
|
25
|
+
const createEthClient = (
|
26
|
+
chain: Chain,
|
27
|
+
jsonRpcUrl: string,
|
28
|
+
transport?: CustomTransport,
|
29
|
+
) =>
|
30
|
+
createWalletClient({
|
31
|
+
chain,
|
32
|
+
transport: transport || http(jsonRpcUrl),
|
33
|
+
}).extend(publicActions);
|
34
|
+
|
35
|
+
export function createContext(config: EnvConfig): {
|
36
|
+
chain: Chain;
|
37
|
+
account: ReturnType<typeof privateKeyToAccount>;
|
38
|
+
jsonRpcUrl: string;
|
39
|
+
ethClient: ReturnType<typeof createEthClient>;
|
40
|
+
confirmations: number;
|
41
|
+
} & EnvConfig;
|
42
|
+
|
43
|
+
export function createContext(
|
44
|
+
config: VlayerContextConfig,
|
45
|
+
transport?: CustomTransport,
|
46
|
+
): {
|
47
|
+
chain: Chain;
|
48
|
+
jsonRpcUrl: string;
|
49
|
+
account: PrivateKeyAccount;
|
50
|
+
ethClient: ReturnType<typeof createEthClient>;
|
51
|
+
confirmations: number;
|
52
|
+
} & VlayerContextConfig;
|
53
|
+
|
54
|
+
export function createContext(
|
55
|
+
config: VlayerContextConfig | EnvConfig,
|
56
|
+
transport?: CustomTransport,
|
57
|
+
) {
|
58
|
+
const chain = getChainSpecs(config.chainName);
|
59
|
+
const jsonRpcUrl = config.jsonRpcUrl ?? chain.rpcUrls.default.http[0];
|
60
|
+
|
61
|
+
return {
|
62
|
+
...config,
|
63
|
+
chain,
|
64
|
+
account: config.privateKey && privateKeyToAccount(config.privateKey),
|
65
|
+
jsonRpcUrl,
|
66
|
+
ethClient: createEthClient(chain, jsonRpcUrl, transport),
|
67
|
+
confirmations: getChainConfirmations(config.chainName),
|
68
|
+
};
|
69
|
+
}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import { getConfig } from "./getConfig";
|
2
|
+
import { createContext } from "./createContext";
|
3
|
+
import { type ContractArg, type ContractSpec } from "types/ethereum";
|
4
|
+
import { type Address } from "viem";
|
5
|
+
import { getChainConfirmations } from "./getChainConfirmations";
|
6
|
+
import debug from "debug";
|
7
|
+
|
8
|
+
const log = debug("vlayer:prover");
|
9
|
+
|
10
|
+
export const waitForContractDeploy = async ({
|
11
|
+
hash,
|
12
|
+
}: {
|
13
|
+
hash: `0x${string}`;
|
14
|
+
}): Promise<Address> => {
|
15
|
+
const { ethClient: client } = createContext(getConfig());
|
16
|
+
const receipt = await client.waitForTransactionReceipt({
|
17
|
+
hash,
|
18
|
+
confirmations: getChainConfirmations(client.chain?.name),
|
19
|
+
retryCount: 120,
|
20
|
+
retryDelay: 1000,
|
21
|
+
});
|
22
|
+
|
23
|
+
if (!receipt.contractAddress || receipt.status !== "success") {
|
24
|
+
throw new Error(
|
25
|
+
`Cannot get contract address from receipt: ${receipt.status}`,
|
26
|
+
);
|
27
|
+
}
|
28
|
+
|
29
|
+
return receipt.contractAddress;
|
30
|
+
};
|
31
|
+
|
32
|
+
export const waitForTransactionReceipt = async ({
|
33
|
+
hash,
|
34
|
+
}: {
|
35
|
+
hash: `0x${string}`;
|
36
|
+
}) => {
|
37
|
+
const { ethClient } = createContext(getConfig());
|
38
|
+
return ethClient.waitForTransactionReceipt({
|
39
|
+
hash,
|
40
|
+
confirmations: getChainConfirmations(ethClient.chain?.name),
|
41
|
+
retryCount: 120,
|
42
|
+
retryDelay: 1000,
|
43
|
+
});
|
44
|
+
};
|
45
|
+
|
46
|
+
export const deployProver = async ({
|
47
|
+
proverSpec,
|
48
|
+
proverArgs,
|
49
|
+
}: {
|
50
|
+
proverSpec: ContractSpec;
|
51
|
+
proverArgs?: ContractArg[];
|
52
|
+
}) => {
|
53
|
+
const config = getConfig();
|
54
|
+
const { ethClient, account, chain } = createContext(config);
|
55
|
+
|
56
|
+
const proverHash = await ethClient.deployContract({
|
57
|
+
chain,
|
58
|
+
account,
|
59
|
+
args: proverArgs,
|
60
|
+
abi: proverSpec.abi,
|
61
|
+
bytecode: proverSpec.bytecode.object,
|
62
|
+
});
|
63
|
+
log(`Prover hash: ${proverHash}`);
|
64
|
+
const prover = await waitForContractDeploy({ hash: proverHash });
|
65
|
+
return prover;
|
66
|
+
};
|
67
|
+
|
68
|
+
export const deployVlayerContracts = async ({
|
69
|
+
proverSpec,
|
70
|
+
verifierSpec,
|
71
|
+
proverArgs,
|
72
|
+
verifierArgs,
|
73
|
+
}: {
|
74
|
+
proverSpec: ContractSpec;
|
75
|
+
verifierSpec: ContractSpec;
|
76
|
+
proverArgs?: ContractArg[];
|
77
|
+
verifierArgs?: ContractArg[];
|
78
|
+
}) => {
|
79
|
+
log("Starting contract deployment process...");
|
80
|
+
const config = getConfig();
|
81
|
+
const { chain, ethClient, account } = createContext(config);
|
82
|
+
|
83
|
+
log("Deploying prover contract...");
|
84
|
+
const proverHash = await ethClient.deployContract({
|
85
|
+
chain,
|
86
|
+
account,
|
87
|
+
args: proverArgs,
|
88
|
+
abi: proverSpec.abi,
|
89
|
+
bytecode: proverSpec.bytecode.object,
|
90
|
+
});
|
91
|
+
log(`Prover hash: ${proverHash}`);
|
92
|
+
const prover = await waitForContractDeploy({ hash: proverHash });
|
93
|
+
log(`Prover contract deployed at: ${prover}`);
|
94
|
+
|
95
|
+
log("Deploying verifier contract...");
|
96
|
+
const verifierHash = await ethClient.deployContract({
|
97
|
+
chain,
|
98
|
+
account,
|
99
|
+
args: prover ? [prover, ...(verifierArgs ?? [])] : verifierArgs,
|
100
|
+
abi: verifierSpec.abi,
|
101
|
+
bytecode: verifierSpec.bytecode.object,
|
102
|
+
});
|
103
|
+
const verifier = await waitForContractDeploy({ hash: verifierHash });
|
104
|
+
log(`Verifier contract deployed at: ${verifier}`);
|
105
|
+
|
106
|
+
log("Contract deployment completed successfully");
|
107
|
+
return { prover, verifier };
|
108
|
+
};
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import dotenvflow from "dotenv-flow";
|
2
|
+
import { type EnvConfig } from "./types";
|
3
|
+
|
4
|
+
const ensureEnvVariable = (envVar: string) => {
|
5
|
+
if (!process.env[envVar]) {
|
6
|
+
if (envVar === "EXAMPLES_TEST_PRIVATE_KEY") {
|
7
|
+
throw new Error(
|
8
|
+
`${envVar} missing. Add a HEX private key with ETH in .env.local for deploy and verify transactions.`,
|
9
|
+
);
|
10
|
+
}
|
11
|
+
throw new Error(`${envVar} is not set`);
|
12
|
+
}
|
13
|
+
return process.env[envVar];
|
14
|
+
};
|
15
|
+
|
16
|
+
const ensureVlayerEnv = () => {
|
17
|
+
try {
|
18
|
+
if (!process.env.VLAYER_ENV) {
|
19
|
+
throw new Error("VLAYER_ENV is not set. Available options: testnet, dev");
|
20
|
+
}
|
21
|
+
if (!["testnet", "dev"].includes(process.env.VLAYER_ENV)) {
|
22
|
+
throw new Error(
|
23
|
+
`Invalid VLAYER_ENV: ${process.env.VLAYER_ENV}. Available options: testnet, anvil, mainnet`,
|
24
|
+
);
|
25
|
+
}
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
27
|
+
} catch (e) {
|
28
|
+
return "dev";
|
29
|
+
}
|
30
|
+
|
31
|
+
return process.env.VLAYER_ENV;
|
32
|
+
};
|
33
|
+
|
34
|
+
const dotEnvFlowConfig = () => {
|
35
|
+
dotenvflow.config({
|
36
|
+
node_env: ensureVlayerEnv(),
|
37
|
+
});
|
38
|
+
};
|
39
|
+
|
40
|
+
export const toCamelCase = (str: string) =>
|
41
|
+
str
|
42
|
+
.toLowerCase()
|
43
|
+
.replace(/([-_][a-z])/g, (group) =>
|
44
|
+
group.toUpperCase().replace("-", "").replace("_", ""),
|
45
|
+
);
|
46
|
+
|
47
|
+
const envVars = [
|
48
|
+
{ var: "CHAIN_NAME" },
|
49
|
+
{ var: "PROVER_URL" },
|
50
|
+
{ var: "JSON_RPC_URL" },
|
51
|
+
{ var: "L2_JSON_RPC_URL", optional: true },
|
52
|
+
{ var: "EXAMPLES_TEST_PRIVATE_KEY", to: "privateKey" },
|
53
|
+
{ var: "VLAYER_API_TOKEN", to: "token", optional: true },
|
54
|
+
];
|
55
|
+
|
56
|
+
export const getConfig = () => {
|
57
|
+
dotEnvFlowConfig();
|
58
|
+
return envVars.reduce((config, envVar) => {
|
59
|
+
try {
|
60
|
+
return {
|
61
|
+
...config,
|
62
|
+
[envVar.to ?? toCamelCase(envVar.var)]: ensureEnvVariable(envVar.var),
|
63
|
+
};
|
64
|
+
} catch (e) {
|
65
|
+
if (envVar.optional) {
|
66
|
+
return { ...config };
|
67
|
+
}
|
68
|
+
throw e;
|
69
|
+
}
|
70
|
+
}, {} as EnvConfig);
|
71
|
+
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
// result of env parsing
|
2
|
+
// mostly needed by the examples to be able to properly perform
|
3
|
+
// pre run deployment
|
4
|
+
|
5
|
+
export type EnvConfig = {
|
6
|
+
chainName: string;
|
7
|
+
proverUrl: string;
|
8
|
+
jsonRpcUrl: string;
|
9
|
+
l2JsonRpcUrl?: string;
|
10
|
+
privateKey: `0x${string}`;
|
11
|
+
token?: string;
|
12
|
+
};
|
13
|
+
|
14
|
+
// represents what is needed by client to properly
|
15
|
+
// work in whole vlayer flow
|
16
|
+
// privateKey is optional and used only for anvil
|
17
|
+
// to avoid involving metamask into the flow
|
18
|
+
|
19
|
+
export type VlayerContextConfig = {
|
20
|
+
chainName: string;
|
21
|
+
jsonRpcUrl: string;
|
22
|
+
proverUrl: string;
|
23
|
+
wsProxyUrl?: string;
|
24
|
+
notaryUrl?: string;
|
25
|
+
privateKey?: `0x${string}`;
|
26
|
+
};
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import fs from "fs";
|
2
|
+
import dotenv from "dotenv";
|
3
|
+
import debug from "debug";
|
4
|
+
|
5
|
+
const log = debug("vlayer:config");
|
6
|
+
|
7
|
+
export const writeEnvVariables = async (
|
8
|
+
envPath: string,
|
9
|
+
overrides: { [key: string]: string | undefined },
|
10
|
+
) => {
|
11
|
+
fs.appendFileSync(envPath, "");
|
12
|
+
const envFile = Bun.file(envPath);
|
13
|
+
let envContent = await envFile.text();
|
14
|
+
|
15
|
+
if (!envContent) {
|
16
|
+
envContent = "";
|
17
|
+
}
|
18
|
+
|
19
|
+
const newEnvs = Object.assign(dotenv.parse(envContent), overrides);
|
20
|
+
|
21
|
+
const envLines = Object.entries(newEnvs)
|
22
|
+
.map(([key, value]) => `${key}=${value}`)
|
23
|
+
.join("\n");
|
24
|
+
|
25
|
+
await Bun.write(envPath, envLines);
|
26
|
+
|
27
|
+
log(`Successfully updated the ${envPath} with: `, overrides);
|
28
|
+
};
|
package/src/index.ts
ADDED