@aztec/cli 0.7.9 → 0.8.4
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 +19 -19
- package/dest/bin/index.js +0 -0
- package/dest/client.d.ts +9 -15
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +14 -22
- package/dest/encoding.js +8 -8
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +134 -106
- package/dest/unbox.d.ts.map +1 -1
- package/dest/unbox.js +47 -45
- package/dest/utils.d.ts +61 -8
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +169 -19
- package/package.json +61 -10
- package/src/client.ts +13 -22
- package/src/encoding.ts +9 -9
- package/src/index.ts +167 -136
- package/src/unbox.ts +52 -49
- package/src/utils.ts +192 -25
- package/.eslintrc.cjs +0 -1
- package/.tsbuildinfo +0 -1
- package/dest/client.test.d.ts +0 -2
- package/dest/client.test.d.ts.map +0 -1
- package/dest/client.test.js +0 -23
- package/dest/test/utils.test.d.ts +0 -2
- package/dest/test/utils.test.d.ts.map +0 -1
- package/dest/test/utils.test.js +0 -104
- package/src/client.test.ts +0 -34
- package/src/test/utils.test.ts +0 -133
- package/tsconfig.json +0 -30
package/src/unbox.ts
CHANGED
|
@@ -17,18 +17,8 @@ import * as path from 'path';
|
|
|
17
17
|
const GITHUB_OWNER = 'AztecProtocol';
|
|
18
18
|
const GITHUB_REPO = 'aztec-packages';
|
|
19
19
|
const GITHUB_TAG_PREFIX = 'aztec-packages';
|
|
20
|
-
const NOIR_CONTRACTS_PATH = 'yarn-project/noir-contracts/src/contracts';
|
|
21
20
|
const BOXES_PATH = 'yarn-project/boxes';
|
|
22
21
|
|
|
23
|
-
/**
|
|
24
|
-
* Converts a contract name in "upper camel case" to a folder name in snake case or kebab case.
|
|
25
|
-
* @param contractName - The contract name.
|
|
26
|
-
* @returns The folder name.
|
|
27
|
-
* */
|
|
28
|
-
function contractNameToFolder(contractName: string, separator = '-'): string {
|
|
29
|
-
return contractName.replace(/[\w]([A-Z])/g, m => `${m[0]}${separator}${m[1]}`).toLowerCase();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
22
|
/**
|
|
33
23
|
* If the box contains the noir contract source code, we don't need to download it from github.
|
|
34
24
|
* Otherwise, we download the contract source code from the `noir-contracts` and `noir-libs` subpackages.
|
|
@@ -50,7 +40,7 @@ async function isDirectoryNonEmpty(directoryPath: string): Promise<boolean> {
|
|
|
50
40
|
* @param localOutputPath - local path to copy to
|
|
51
41
|
*/
|
|
52
42
|
async function copyFolderFromGithub(data: JSZip, repositoryFolderPath: string, localOutputPath: string, log: LogFn) {
|
|
53
|
-
log(`Downloading from github: ${repositoryFolderPath}`);
|
|
43
|
+
log(`Downloading folder from github: ${repositoryFolderPath}`);
|
|
54
44
|
const repositoryDirectories = Object.values(data.files).filter(file => {
|
|
55
45
|
return file.dir && file.name.startsWith(repositoryFolderPath);
|
|
56
46
|
});
|
|
@@ -61,11 +51,11 @@ async function copyFolderFromGithub(data: JSZip, repositoryFolderPath: string, l
|
|
|
61
51
|
await fs.mkdir(targetPath, { recursive: true });
|
|
62
52
|
}
|
|
63
53
|
|
|
64
|
-
const
|
|
54
|
+
const folderFiles = Object.values(data.files).filter(file => {
|
|
65
55
|
return !file.dir && file.name.startsWith(repositoryFolderPath);
|
|
66
56
|
});
|
|
67
57
|
|
|
68
|
-
for (const file of
|
|
58
|
+
for (const file of folderFiles) {
|
|
69
59
|
const relativePath = file.name.replace(repositoryFolderPath, '');
|
|
70
60
|
const targetPath = `${localOutputPath}/${relativePath}`;
|
|
71
61
|
const content = await file.async('nodebuffer');
|
|
@@ -73,6 +63,27 @@ async function copyFolderFromGithub(data: JSZip, repositoryFolderPath: string, l
|
|
|
73
63
|
}
|
|
74
64
|
}
|
|
75
65
|
|
|
66
|
+
/**
|
|
67
|
+
* @param data - in memory unzipped clone of a github repo
|
|
68
|
+
* @param repositoryFile - path of the file to copy from github repo
|
|
69
|
+
* @param localOutputPath - local path to copy the file to
|
|
70
|
+
*/
|
|
71
|
+
async function copyFileFromGithub(data: JSZip, repositoryFile: string, localOutputPath: string, log: LogFn) {
|
|
72
|
+
log(`Downloading file from github: ${repositoryFile}`);
|
|
73
|
+
|
|
74
|
+
const file = data.files[repositoryFile];
|
|
75
|
+
|
|
76
|
+
if (!file || file.dir) {
|
|
77
|
+
throw new Error(`File not found or it's a directory: ${repositoryFile}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const filename = path.basename(repositoryFile);
|
|
81
|
+
const targetPath = `${localOutputPath}/${filename}`;
|
|
82
|
+
|
|
83
|
+
const content = await file.async('nodebuffer');
|
|
84
|
+
await fs.writeFile(targetPath, content);
|
|
85
|
+
}
|
|
86
|
+
|
|
76
87
|
/**
|
|
77
88
|
* Not flexible at at all, but quick fix to download a noir smart contract from our
|
|
78
89
|
* monorepo on github. this will copy over the `yarn-projects/boxes/{contract_name}` folder
|
|
@@ -92,8 +103,7 @@ async function downloadContractAndBoxFromGithub(
|
|
|
92
103
|
// small string conversion, in the ABI the contract name looks like PrivateToken
|
|
93
104
|
// but in the repostory it looks like private_token
|
|
94
105
|
|
|
95
|
-
|
|
96
|
-
log(`Downloading @aztex/boxes/${kebabCaseContractName} to ${outputPath}...`);
|
|
106
|
+
log(`Downloading @aztex/boxes/${contractName} to ${outputPath}...`);
|
|
97
107
|
// Step 1: Fetch the monorepo ZIP from GitHub, matching the CLI version
|
|
98
108
|
const url = `https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}/archive/refs/tags/${tag}.zip`;
|
|
99
109
|
const response = await fetch(url);
|
|
@@ -103,40 +113,26 @@ async function downloadContractAndBoxFromGithub(
|
|
|
103
113
|
const data = await zip.loadAsync(buffer);
|
|
104
114
|
|
|
105
115
|
// Step 2: copy the '@aztec/boxes/{contract-name}' subpackage to the output directory
|
|
106
|
-
// this is currently only implemented for
|
|
116
|
+
// this is currently only implemented for `blank` and `private-token` under 'boxes/{box-name}/'
|
|
107
117
|
const repoDirectoryPrefix = `${GITHUB_REPO}-${tag}`;
|
|
108
118
|
|
|
109
|
-
const boxPath = `${repoDirectoryPrefix}/${BOXES_PATH}/${
|
|
119
|
+
const boxPath = `${repoDirectoryPrefix}/${BOXES_PATH}/${contractName}`;
|
|
110
120
|
await copyFolderFromGithub(data, boxPath, outputPath, log);
|
|
111
121
|
|
|
122
|
+
// the expected noir version is contained in
|
|
123
|
+
// aztec-packages/yarn-project/noir-compiler/src/noir-version.json
|
|
124
|
+
// copy it in and use to update the package.json script to install that version of noir
|
|
125
|
+
const noirVersionPath = `${repoDirectoryPrefix}/yarn-project/noir-compiler/src/noir-version.json`;
|
|
126
|
+
await copyFileFromGithub(data, noirVersionPath, outputPath, log);
|
|
127
|
+
|
|
112
128
|
const contractTargetDirectory = path.join(outputPath, 'src', 'contracts');
|
|
113
129
|
const boxContainsNoirSource = await isDirectoryNonEmpty(contractTargetDirectory);
|
|
114
130
|
if (boxContainsNoirSource) {
|
|
115
131
|
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// noir-contracts and noir-libs subpackages and pray that the versions are compatible
|
|
121
|
-
log('Copying noir contracts...');
|
|
122
|
-
|
|
123
|
-
// source noir files for the contract are in this folder
|
|
124
|
-
const snakeCaseContractName = contractNameToFolder(contractName, '_');
|
|
125
|
-
const contractDirectoryPath = `${repoDirectoryPrefix}/${NOIR_CONTRACTS_PATH}/${snakeCaseContractName}_contract`;
|
|
126
|
-
// copy the noir contracts to the output directory under subdir /src/contracts/
|
|
127
|
-
const contractFiles = Object.values(data.files).filter(file => {
|
|
128
|
-
return !file.dir && file.name.startsWith(contractDirectoryPath);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Nargo.toml file needs to be in the root of the contracts directory,
|
|
132
|
-
// and noir files in the src/ subdirectory
|
|
133
|
-
await fs.mkdir(path.join(contractTargetDirectory, 'src'), { recursive: true });
|
|
134
|
-
for (const file of contractFiles) {
|
|
135
|
-
const filename = file.name.replace(`${contractDirectoryPath}/`, '');
|
|
136
|
-
const targetPath = path.join(contractTargetDirectory, filename);
|
|
137
|
-
const content = await file.async('nodebuffer');
|
|
138
|
-
await fs.writeFile(targetPath, content);
|
|
139
|
-
log(` ✓ ${filename}`);
|
|
132
|
+
} else {
|
|
133
|
+
// we used to support downloading from the noir contracts monorepo but now force box to contain source code
|
|
134
|
+
// This should never happen, because of the check we do initially on the box name.
|
|
135
|
+
throw Error(`Box ${contractName} does not contain noir source code.`);
|
|
140
136
|
}
|
|
141
137
|
}
|
|
142
138
|
/**
|
|
@@ -232,16 +228,23 @@ async function updatePackageJsonVersions(packageVersion: string, outputPath: str
|
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
}
|
|
231
|
+
// read the `noir-version.json`, grab the expected noir version, and patch the noir install script
|
|
232
|
+
const noirVersionPath = path.join(outputPath, 'noir-version.json');
|
|
233
|
+
const noirVersionContent = await fs.readFile(noirVersionPath, 'utf-8');
|
|
234
|
+
const noirVersionJSON = JSON.parse(noirVersionContent);
|
|
235
|
+
const noirTag = noirVersionJSON.tag;
|
|
236
|
+
packageData.scripts['install:noir'] = packageData.scripts['install:noir'].replace('NOIR_VERSION', `${noirTag}`);
|
|
237
|
+
log(`Updated Noir version to: ${noirTag}`);
|
|
235
238
|
|
|
236
239
|
// modify the version of the sandbox to pull - it's set to "latest" version in the monorepo,
|
|
237
240
|
// but we need to replace with the same tagVersion as the cli and the other aztec npm packages
|
|
238
241
|
// similarly, make sure we spinup the sandbox with the same version.
|
|
239
242
|
packageData.scripts['install:sandbox'] = packageData.scripts['install:sandbox'].replace(
|
|
240
243
|
'latest',
|
|
241
|
-
|
|
244
|
+
`${packageVersion}`,
|
|
242
245
|
);
|
|
243
246
|
|
|
244
|
-
packageData.scripts['start:sandbox'] = packageData.scripts['start:sandbox'].replace('latest',
|
|
247
|
+
packageData.scripts['start:sandbox'] = packageData.scripts['start:sandbox'].replace('latest', `${packageVersion}`);
|
|
245
248
|
|
|
246
249
|
// Convert back to a string and write back to the package.json file
|
|
247
250
|
const updatedContent = JSON.stringify(packageData, null, 2);
|
|
@@ -294,13 +297,13 @@ export async function unboxContract(
|
|
|
294
297
|
packageVersion: string,
|
|
295
298
|
log: LogFn,
|
|
296
299
|
) {
|
|
297
|
-
const contractNames = ['
|
|
300
|
+
const contractNames = ['private-token', 'blank', 'blank-react'];
|
|
298
301
|
|
|
299
302
|
if (!contractNames.includes(contractName)) {
|
|
300
303
|
log(
|
|
301
304
|
`The noir contract named "${contractName}" was not found in "@aztec/boxes" package. Valid options are:
|
|
302
305
|
${contractNames.join('\n\t')}
|
|
303
|
-
We recommend "
|
|
306
|
+
We recommend "private-token" as a default.`,
|
|
304
307
|
);
|
|
305
308
|
return;
|
|
306
309
|
}
|
|
@@ -308,17 +311,17 @@ export async function unboxContract(
|
|
|
308
311
|
|
|
309
312
|
const tag = `${GITHUB_TAG_PREFIX}-v${packageVersion}`;
|
|
310
313
|
// downloads the selected contract's relevant folder in @aztec/boxes/{contract_name}
|
|
311
|
-
// and the noir source code from `noir-contracts` into `${outputDirectoryName}/src/contracts`
|
|
312
|
-
// if not present in the box
|
|
313
314
|
await downloadContractAndBoxFromGithub(tag, contractName, outputPath, log);
|
|
314
315
|
// make adjustments for packaging to work as a standalone, as opposed to part of yarn workspace
|
|
315
|
-
// as in the monorepo source files
|
|
316
|
+
// as in the monorepo source files. replace things like "workspace^" with the actual version number
|
|
316
317
|
await updatePackagingConfigurations(packageVersion, tag, outputPath, log);
|
|
317
318
|
|
|
318
319
|
log('');
|
|
319
|
-
log(`${contractName} has been successfully
|
|
320
|
+
log(`${contractName} has been successfully initialized!`);
|
|
320
321
|
log('To get started, simply run the following commands:');
|
|
321
322
|
log(` cd ${outputDirectoryName}`);
|
|
322
323
|
log(' yarn');
|
|
324
|
+
log(' yarn start:sandbox');
|
|
325
|
+
log('And in another terminal in the same directory,');
|
|
323
326
|
log(' yarn start:dev');
|
|
324
327
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { AztecAddress,
|
|
2
|
-
import { createEthereumChain, deployL1Contracts } from '@aztec/ethereum';
|
|
1
|
+
import { AztecAddress, Fr, GrumpkinScalar, PXE, Point, TxHash } from '@aztec/aztec.js';
|
|
2
|
+
import { L1ContractArtifactsForDeployment, createEthereumChain, deployL1Contracts } from '@aztec/ethereum';
|
|
3
3
|
import { ContractAbi } from '@aztec/foundation/abi';
|
|
4
4
|
import { DebugLogger, LogFn } from '@aztec/foundation/log';
|
|
5
|
+
import {
|
|
6
|
+
ContractDeploymentEmitterAbi,
|
|
7
|
+
ContractDeploymentEmitterBytecode,
|
|
8
|
+
InboxAbi,
|
|
9
|
+
InboxBytecode,
|
|
10
|
+
OutboxAbi,
|
|
11
|
+
OutboxBytecode,
|
|
12
|
+
RegistryAbi,
|
|
13
|
+
RegistryBytecode,
|
|
14
|
+
RollupAbi,
|
|
15
|
+
RollupBytecode,
|
|
16
|
+
} from '@aztec/l1-artifacts';
|
|
5
17
|
|
|
18
|
+
import { InvalidArgumentError } from 'commander';
|
|
6
19
|
import fs from 'fs';
|
|
7
20
|
import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
|
|
8
21
|
|
|
9
22
|
import { encodeArgs } from './encoding.js';
|
|
10
23
|
|
|
11
|
-
export { createClient } from './client.js';
|
|
12
24
|
/**
|
|
13
25
|
* Helper type to dynamically import contracts.
|
|
14
26
|
*/
|
|
@@ -46,7 +58,29 @@ export async function deployAztecContracts(
|
|
|
46
58
|
) {
|
|
47
59
|
const account = !privateKey ? mnemonicToAccount(mnemonic!) : privateKeyToAccount(`0x${privateKey}`);
|
|
48
60
|
const chain = createEthereumChain(rpcUrl, apiKey);
|
|
49
|
-
|
|
61
|
+
const l1Artifacts: L1ContractArtifactsForDeployment = {
|
|
62
|
+
contractDeploymentEmitter: {
|
|
63
|
+
contractAbi: ContractDeploymentEmitterAbi,
|
|
64
|
+
contractBytecode: ContractDeploymentEmitterBytecode,
|
|
65
|
+
},
|
|
66
|
+
registry: {
|
|
67
|
+
contractAbi: RegistryAbi,
|
|
68
|
+
contractBytecode: RegistryBytecode,
|
|
69
|
+
},
|
|
70
|
+
inbox: {
|
|
71
|
+
contractAbi: InboxAbi,
|
|
72
|
+
contractBytecode: InboxBytecode,
|
|
73
|
+
},
|
|
74
|
+
outbox: {
|
|
75
|
+
contractAbi: OutboxAbi,
|
|
76
|
+
contractBytecode: OutboxBytecode,
|
|
77
|
+
},
|
|
78
|
+
rollup: {
|
|
79
|
+
contractAbi: RollupAbi,
|
|
80
|
+
contractBytecode: RollupBytecode,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
return await deployL1Contracts(chain.rpcUrl, account, chain.chainInfo, debugLogger, l1Artifacts);
|
|
50
84
|
}
|
|
51
85
|
|
|
52
86
|
/**
|
|
@@ -90,23 +124,23 @@ export async function getContractAbi(fileDir: string, log: LogFn) {
|
|
|
90
124
|
|
|
91
125
|
/**
|
|
92
126
|
* Utility to select a TX sender either from user input
|
|
93
|
-
* or from the first account that is found in
|
|
94
|
-
* @param
|
|
127
|
+
* or from the first account that is found in a PXE instance.
|
|
128
|
+
* @param pxe - The PXE instance that will be checked for an account.
|
|
95
129
|
* @param _from - The user input.
|
|
96
130
|
* @returns An Aztec address. Will throw if one can't be found in either options.
|
|
97
131
|
*/
|
|
98
|
-
export async function getTxSender(
|
|
132
|
+
export async function getTxSender(pxe: PXE, _from?: string) {
|
|
99
133
|
let from: AztecAddress;
|
|
100
134
|
if (_from) {
|
|
101
135
|
try {
|
|
102
136
|
from = AztecAddress.fromString(_from);
|
|
103
137
|
} catch {
|
|
104
|
-
throw new
|
|
138
|
+
throw new InvalidArgumentError(`Invalid option 'from' passed: ${_from}`);
|
|
105
139
|
}
|
|
106
140
|
} else {
|
|
107
|
-
const accounts = await
|
|
141
|
+
const accounts = await pxe.getRegisteredAccounts();
|
|
108
142
|
if (!accounts.length) {
|
|
109
|
-
throw new Error('No accounts found in
|
|
143
|
+
throw new Error('No accounts found in PXE instance.');
|
|
110
144
|
}
|
|
111
145
|
from = accounts[0].address;
|
|
112
146
|
}
|
|
@@ -116,28 +150,161 @@ export async function getTxSender(client: AztecRPC, _from?: string) {
|
|
|
116
150
|
/**
|
|
117
151
|
* Performs necessary checks, conversions & operations to call a contract fn from the CLI.
|
|
118
152
|
* @param contractFile - Directory of the compiled contract ABI.
|
|
119
|
-
* @param
|
|
153
|
+
* @param contractAddress - Aztec Address of the contract.
|
|
120
154
|
* @param functionName - Name of the function to be called.
|
|
121
155
|
* @param _functionArgs - Arguments to call the function with.
|
|
122
156
|
* @param log - Logger instance that will output to the CLI
|
|
123
157
|
* @returns Formatted contract address, function arguments and caller's aztec address.
|
|
124
158
|
*/
|
|
125
|
-
export async function prepTx(
|
|
126
|
-
contractFile: string,
|
|
127
|
-
_contractAddress: string,
|
|
128
|
-
functionName: string,
|
|
129
|
-
_functionArgs: string[],
|
|
130
|
-
log: LogFn,
|
|
131
|
-
) {
|
|
132
|
-
let contractAddress;
|
|
133
|
-
try {
|
|
134
|
-
contractAddress = AztecAddress.fromString(_contractAddress);
|
|
135
|
-
} catch {
|
|
136
|
-
throw new Error(`Unable to parse contract address ${_contractAddress}.`);
|
|
137
|
-
}
|
|
159
|
+
export async function prepTx(contractFile: string, functionName: string, _functionArgs: string[], log: LogFn) {
|
|
138
160
|
const contractAbi = await getContractAbi(contractFile, log);
|
|
139
161
|
const functionAbi = getAbiFunction(contractAbi, functionName);
|
|
140
162
|
const functionArgs = encodeArgs(_functionArgs, functionAbi.parameters);
|
|
141
163
|
|
|
142
|
-
return {
|
|
164
|
+
return { functionArgs, contractAbi };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Removes the leading 0x from a hex string. If no leading 0x is found the string is returned unchanged.
|
|
169
|
+
* @param hex - A hex string
|
|
170
|
+
* @returns A new string with leading 0x removed
|
|
171
|
+
*/
|
|
172
|
+
export const stripLeadingHex = (hex: string) => {
|
|
173
|
+
if (hex.length > 2 && hex.startsWith('0x')) {
|
|
174
|
+
return hex.substring(2);
|
|
175
|
+
}
|
|
176
|
+
return hex;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Parses a hex encoded string to an Fr integer to be used as salt
|
|
181
|
+
* @param str - Hex encoded string
|
|
182
|
+
* @returns A integer to be used as salt
|
|
183
|
+
*/
|
|
184
|
+
export function parseSaltFromHexString(str: string): Fr {
|
|
185
|
+
const hex = stripLeadingHex(str);
|
|
186
|
+
|
|
187
|
+
// ensure it's a hex string
|
|
188
|
+
if (!hex.match(/^[0-9a-f]+$/i)) {
|
|
189
|
+
throw new InvalidArgumentError('Invalid hex string');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// pad it so that we may read it as a buffer.
|
|
193
|
+
// Buffer needs _exactly_ two hex characters per byte
|
|
194
|
+
const padded = hex.length % 2 === 1 ? '0' + hex : hex;
|
|
195
|
+
|
|
196
|
+
// finally, turn it into an integer
|
|
197
|
+
return Fr.fromBuffer(Buffer.from(padded, 'hex'));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Parses an AztecAddress from a string. Throws InvalidArgumentError if the string is not a valid.
|
|
202
|
+
* @param address - A serialised Aztec address
|
|
203
|
+
* @returns An Aztec address
|
|
204
|
+
*/
|
|
205
|
+
export function parseAztecAddress(address: string): AztecAddress {
|
|
206
|
+
try {
|
|
207
|
+
return AztecAddress.fromString(address);
|
|
208
|
+
} catch {
|
|
209
|
+
throw new InvalidArgumentError(`Invalid address: ${address}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Parses a TxHash from a string. Throws InvalidArgumentError if the string is not a valid.
|
|
215
|
+
* @param txHash - A transaction hash
|
|
216
|
+
* @returns A TxHash instance
|
|
217
|
+
*/
|
|
218
|
+
export function parseTxHash(txHash: string): TxHash {
|
|
219
|
+
try {
|
|
220
|
+
return TxHash.fromString(txHash);
|
|
221
|
+
} catch {
|
|
222
|
+
throw new InvalidArgumentError(`Invalid transaction hash: ${txHash}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Parses a public key from a string. Throws InvalidArgumentError if the string is not a valid.
|
|
228
|
+
* @param publicKey - A public key
|
|
229
|
+
* @returns A Point instance
|
|
230
|
+
*/
|
|
231
|
+
export function parsePublicKey(publicKey: string): Point {
|
|
232
|
+
try {
|
|
233
|
+
return Point.fromString(publicKey);
|
|
234
|
+
} catch (err) {
|
|
235
|
+
throw new InvalidArgumentError(`Invalid public key: ${publicKey}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Parses a partial address from a string. Throws InvalidArgumentError if the string is not a valid.
|
|
241
|
+
* @param address - A partial address
|
|
242
|
+
* @returns A Fr instance
|
|
243
|
+
*/
|
|
244
|
+
export function parsePartialAddress(address: string): Fr {
|
|
245
|
+
try {
|
|
246
|
+
return Fr.fromString(address);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
throw new InvalidArgumentError(`Invalid partial address: ${address}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Parses a private key from a string. Throws InvalidArgumentError if the string is not a valid.
|
|
254
|
+
* @param privateKey - A string
|
|
255
|
+
* @returns A private key
|
|
256
|
+
*/
|
|
257
|
+
export function parsePrivateKey(privateKey: string): GrumpkinScalar {
|
|
258
|
+
try {
|
|
259
|
+
const value = GrumpkinScalar.fromString(privateKey);
|
|
260
|
+
// most likely a badly formatted key was passed
|
|
261
|
+
if (value.isZero()) {
|
|
262
|
+
throw new Error('Private key must not be zero');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return value;
|
|
266
|
+
} catch (err) {
|
|
267
|
+
throw new InvalidArgumentError(`Invalid private key: ${privateKey}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Parses a field from a string. Throws InvalidArgumentError if the string is not a valid field value.
|
|
273
|
+
* @param field - A string representing the field.
|
|
274
|
+
* @returns A field.
|
|
275
|
+
*/
|
|
276
|
+
export function parseField(field: string): Fr {
|
|
277
|
+
try {
|
|
278
|
+
const isHex = field.startsWith('0x') || field.match(new RegExp(`^[0-9a-f]{${Fr.SIZE_IN_BYTES * 2}}$`, 'i'));
|
|
279
|
+
if (isHex) {
|
|
280
|
+
return Fr.fromString(field);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (['true', 'false'].includes(field)) {
|
|
284
|
+
return new Fr(field === 'true');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const isNumber = +field || field === '0';
|
|
288
|
+
if (isNumber) {
|
|
289
|
+
return new Fr(BigInt(field));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const isBigInt = field.endsWith('n');
|
|
293
|
+
if (isBigInt) {
|
|
294
|
+
return new Fr(BigInt(field.replace(/n$/, '')));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return new Fr(BigInt(field));
|
|
298
|
+
} catch (err) {
|
|
299
|
+
throw new InvalidArgumentError(`Invalid field: ${field}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Parses an array of strings to Frs.
|
|
305
|
+
* @param fields - An array of strings representing the fields.
|
|
306
|
+
* @returns An array of Frs.
|
|
307
|
+
*/
|
|
308
|
+
export function parseFields(fields: string[]): Fr[] {
|
|
309
|
+
return fields.map(parseField);
|
|
143
310
|
}
|
package/.eslintrc.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('@aztec/foundation/eslint');
|