@aztec/aztec.js 0.0.1-commit.c7c42ec → 0.0.1-commit.f295ac2

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.
Files changed (88) hide show
  1. package/dest/account/account.d.ts +3 -3
  2. package/dest/account/account.d.ts.map +1 -1
  3. package/dest/account/account_contract.d.ts +2 -2
  4. package/dest/account/account_contract.d.ts.map +1 -1
  5. package/dest/account/account_with_secret_key.d.ts +2 -1
  6. package/dest/account/account_with_secret_key.d.ts.map +1 -1
  7. package/dest/api/block.d.ts +2 -2
  8. package/dest/api/block.d.ts.map +1 -1
  9. package/dest/api/block.js +1 -1
  10. package/dest/api/protocol.d.ts +7 -1
  11. package/dest/api/protocol.d.ts.map +1 -1
  12. package/dest/api/protocol.js +6 -0
  13. package/dest/api/wallet.d.ts +2 -2
  14. package/dest/api/wallet.d.ts.map +1 -1
  15. package/dest/api/wallet.js +1 -1
  16. package/dest/authorization/call_authorization_request.d.ts +22 -1
  17. package/dest/authorization/call_authorization_request.d.ts.map +1 -1
  18. package/dest/contract/batch_call.d.ts +1 -1
  19. package/dest/contract/batch_call.d.ts.map +1 -1
  20. package/dest/contract/batch_call.js +3 -1
  21. package/dest/contract/contract_base.d.ts +4 -1
  22. package/dest/contract/contract_base.d.ts.map +1 -1
  23. package/dest/contract/contract_function_interaction.d.ts +1 -1
  24. package/dest/contract/deploy_method.d.ts +1 -1
  25. package/dest/contract/deploy_method.d.ts.map +1 -1
  26. package/dest/contract/deploy_method.js +5 -4
  27. package/dest/contract/protocol_contracts/auth-registry.d.ts +36 -0
  28. package/dest/contract/protocol_contracts/auth-registry.d.ts.map +1 -0
  29. package/dest/contract/protocol_contracts/auth-registry.js +928 -0
  30. package/dest/contract/protocol_contracts/contract-class-registry.d.ts +35 -0
  31. package/dest/contract/protocol_contracts/contract-class-registry.d.ts.map +1 -0
  32. package/dest/contract/protocol_contracts/contract-class-registry.js +797 -0
  33. package/dest/contract/protocol_contracts/contract-instance-registry.d.ts +31 -0
  34. package/dest/contract/protocol_contracts/contract-instance-registry.d.ts.map +1 -0
  35. package/dest/contract/protocol_contracts/contract-instance-registry.js +867 -0
  36. package/dest/contract/protocol_contracts/fee-juice.d.ts +30 -0
  37. package/dest/contract/protocol_contracts/fee-juice.d.ts.map +1 -0
  38. package/dest/contract/protocol_contracts/fee-juice.js +824 -0
  39. package/dest/contract/protocol_contracts/multi-call-entrypoint.d.ts +34 -0
  40. package/dest/contract/protocol_contracts/multi-call-entrypoint.d.ts.map +1 -0
  41. package/dest/contract/protocol_contracts/multi-call-entrypoint.js +576 -0
  42. package/dest/contract/protocol_contracts/public-checks.d.ts +26 -0
  43. package/dest/contract/protocol_contracts/public-checks.d.ts.map +1 -0
  44. package/dest/contract/protocol_contracts/public-checks.js +592 -0
  45. package/dest/contract/wait_for_proven.d.ts +2 -2
  46. package/dest/contract/wait_for_proven.d.ts.map +1 -1
  47. package/dest/deployment/broadcast_function.js +3 -3
  48. package/dest/deployment/publish_class.js +2 -2
  49. package/dest/deployment/publish_instance.d.ts +2 -2
  50. package/dest/deployment/publish_instance.d.ts.map +1 -1
  51. package/dest/deployment/publish_instance.js +3 -3
  52. package/dest/ethereum/portal_manager.d.ts +6 -3
  53. package/dest/ethereum/portal_manager.d.ts.map +1 -1
  54. package/dest/ethereum/portal_manager.js +10 -10
  55. package/dest/scripts/generate_protocol_contract_types.d.ts +2 -0
  56. package/dest/scripts/generate_protocol_contract_types.d.ts.map +1 -0
  57. package/dest/scripts/generate_protocol_contract_types.js +120 -0
  58. package/dest/wallet/account_manager.d.ts +5 -2
  59. package/dest/wallet/account_manager.d.ts.map +1 -1
  60. package/dest/wallet/wallet.d.ts +181 -2483
  61. package/dest/wallet/wallet.d.ts.map +1 -1
  62. package/dest/wallet/wallet.js +46 -84
  63. package/package.json +14 -12
  64. package/src/api/block.ts +1 -1
  65. package/src/api/protocol.ts +7 -0
  66. package/src/api/wallet.ts +0 -2
  67. package/src/contract/batch_call.ts +4 -2
  68. package/src/contract/deploy_method.ts +7 -6
  69. package/src/contract/protocol_contracts/auth-registry.ts +542 -0
  70. package/src/contract/protocol_contracts/contract-class-registry.ts +442 -0
  71. package/src/contract/protocol_contracts/contract-instance-registry.ts +501 -0
  72. package/src/contract/protocol_contracts/fee-juice.ts +462 -0
  73. package/src/contract/protocol_contracts/multi-call-entrypoint.ts +338 -0
  74. package/src/contract/protocol_contracts/public-checks.ts +324 -0
  75. package/src/deployment/broadcast_function.ts +3 -3
  76. package/src/deployment/publish_class.ts +2 -2
  77. package/src/deployment/publish_instance.ts +3 -6
  78. package/src/ethereum/portal_manager.ts +9 -8
  79. package/src/scripts/generate_protocol_contract_types.ts +150 -0
  80. package/src/wallet/wallet.ts +109 -80
  81. package/dest/contract/protocol_contracts.d.ts +0 -9
  82. package/dest/contract/protocol_contracts.d.ts.map +0 -1
  83. package/dest/contract/protocol_contracts.js +0 -26
  84. package/dest/contract/unsafe_contract.d.ts +0 -15
  85. package/dest/contract/unsafe_contract.d.ts.map +0 -1
  86. package/dest/contract/unsafe_contract.js +0 -6
  87. package/src/contract/protocol_contracts.ts +0 -35
  88. package/src/contract/unsafe_contract.ts +0 -19
@@ -16,7 +16,7 @@ import {
16
16
  import { Capsule } from '@aztec/stdlib/tx';
17
17
 
18
18
  import type { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
19
- import { getClassRegistryContract } from '../contract/protocol_contracts.js';
19
+ import { ContractClassRegistryContract } from '../contract/protocol_contracts/contract-class-registry.js';
20
20
  import type { Wallet } from '../wallet/index.js';
21
21
 
22
22
  /**
@@ -58,7 +58,7 @@ export async function broadcastPrivateFunction(
58
58
 
59
59
  const vkHash = await computeVerificationKeyHash(privateFunctionArtifact);
60
60
 
61
- const classRegistry = await getClassRegistryContract(wallet);
61
+ const classRegistry = ContractClassRegistryContract.at(wallet);
62
62
  const bytecode = bufferAsFields(
63
63
  privateFunctionArtifact.bytecode,
64
64
  MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
@@ -121,7 +121,7 @@ export async function broadcastUtilityFunction(
121
121
  privateFunctionsArtifactTreeRoot,
122
122
  } = await createUtilityFunctionMembershipProof(selector, artifact);
123
123
 
124
- const classRegistry = await getClassRegistryContract(wallet);
124
+ const classRegistry = ContractClassRegistryContract.at(wallet);
125
125
  const bytecode = bufferAsFields(
126
126
  utilityFunctionArtifact.bytecode,
127
127
  MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
@@ -9,7 +9,7 @@ import { getContractClassFromArtifact } from '@aztec/stdlib/contract';
9
9
  import { Capsule } from '@aztec/stdlib/tx';
10
10
 
11
11
  import type { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
12
- import { getClassRegistryContract } from '../contract/protocol_contracts.js';
12
+ import { ContractClassRegistryContract } from '../contract/protocol_contracts/contract-class-registry.js';
13
13
  import type { Wallet } from '../wallet/index.js';
14
14
 
15
15
  /** Sets up a call to publish a contract class given its artifact. */
@@ -19,7 +19,7 @@ export async function publishContractClass(
19
19
  ): Promise<ContractFunctionInteraction> {
20
20
  const { artifactHash, privateFunctionsRoot, publicBytecodeCommitment, packedBytecode } =
21
21
  await getContractClassFromArtifact(artifact);
22
- const classRegistry = await getClassRegistryContract(wallet);
22
+ const classRegistry = ContractClassRegistryContract.at(wallet);
23
23
 
24
24
  const encodedBytecode = bufferAsFields(packedBytecode, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);
25
25
  return classRegistry.methods.publish(artifactHash, privateFunctionsRoot, publicBytecodeCommitment).with({
@@ -1,7 +1,7 @@
1
1
  import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
2
2
 
3
3
  import type { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
4
- import { getInstanceRegistryContract } from '../contract/protocol_contracts.js';
4
+ import { ContractInstanceRegistryContract } from '../contract/protocol_contracts/contract-instance-registry.js';
5
5
  import type { Wallet } from '../wallet/wallet.js';
6
6
 
7
7
  /**
@@ -9,11 +9,8 @@ import type { Wallet } from '../wallet/wallet.js';
9
9
  * @param wallet - The wallet to use for the publication (setup) tx.
10
10
  * @param instance - The instance to publish.
11
11
  */
12
- export async function publishInstance(
13
- wallet: Wallet,
14
- instance: ContractInstanceWithAddress,
15
- ): Promise<ContractFunctionInteraction> {
16
- const contractInstanceRegistry = await getInstanceRegistryContract(wallet);
12
+ export function publishInstance(wallet: Wallet, instance: ContractInstanceWithAddress): ContractFunctionInteraction {
13
+ const contractInstanceRegistry = ContractInstanceRegistryContract.at(wallet);
17
14
  const { salt, currentContractClassId: contractClassId, publicKeys, deployer: instanceDeployer } = instance;
18
15
  const isUniversalDeploy = instanceDeployer.isZero();
19
16
  return contractInstanceRegistry.methods.publish_for_public_execution(
@@ -1,5 +1,6 @@
1
1
  import type { ExtendedViemWalletClient, ViemContract } from '@aztec/ethereum/types';
2
2
  import { extractEvent } from '@aztec/ethereum/utils';
3
+ import type { EpochNumber } from '@aztec/foundation/branded-types';
3
4
  import { sha256ToField } from '@aztec/foundation/crypto/sha256';
4
5
  import { Fr } from '@aztec/foundation/curves/bn254';
5
6
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -408,26 +409,26 @@ export class L1TokenPortalManager extends L1ToL2TokenPortalManager {
408
409
  * Withdraws funds from the portal by consuming an L2 to L1 message. Returns once the tx is mined on L1.
409
410
  * @param amount - Amount to withdraw.
410
411
  * @param recipient - Who will receive the funds.
411
- * @param blockNumber - L2 block number of the message.
412
+ * @param epochNumber - Epoch number of the message.
412
413
  * @param messageIndex - Index of the message.
413
414
  * @param siblingPath - Sibling path of the message.
414
415
  */
415
416
  public async withdrawFunds(
416
417
  amount: bigint,
417
418
  recipient: EthAddress,
418
- blockNumber: bigint,
419
+ epochNumber: EpochNumber,
419
420
  messageIndex: bigint,
420
421
  siblingPath: SiblingPath<number>,
421
422
  ) {
422
423
  this.logger.info(
423
- `Sending L1 tx to consume message at block ${blockNumber} index ${messageIndex} to withdraw ${amount}`,
424
+ `Sending L1 tx to consume message at epoch ${epochNumber} index ${messageIndex} to withdraw ${amount}`,
424
425
  );
425
426
 
426
427
  const messageLeafId = getL2ToL1MessageLeafId({ leafIndex: messageIndex, siblingPath });
427
- const isConsumedBefore = await this.outbox.read.hasMessageBeenConsumedAtCheckpoint([blockNumber, messageLeafId]);
428
+ const isConsumedBefore = await this.outbox.read.hasMessageBeenConsumedAtEpoch([BigInt(epochNumber), messageLeafId]);
428
429
  if (isConsumedBefore) {
429
430
  throw new Error(
430
- `L1 to L2 message at block ${blockNumber} index ${messageIndex} height ${siblingPath.pathSize} has already been consumed`,
431
+ `L2 to L1 message at epoch ${epochNumber} index ${messageIndex} height ${siblingPath.pathSize} has already been consumed`,
431
432
  );
432
433
  }
433
434
 
@@ -436,7 +437,7 @@ export class L1TokenPortalManager extends L1ToL2TokenPortalManager {
436
437
  recipient.toString(),
437
438
  amount,
438
439
  false,
439
- BigInt(blockNumber),
440
+ BigInt(epochNumber),
440
441
  messageIndex,
441
442
  siblingPath.toBufferArray().map((buf: Buffer): Hex => `0x${buf.toString('hex')}`),
442
443
  ]);
@@ -445,10 +446,10 @@ export class L1TokenPortalManager extends L1ToL2TokenPortalManager {
445
446
  hash: await this.extendedClient.writeContract(withdrawRequest),
446
447
  });
447
448
 
448
- const isConsumedAfter = await this.outbox.read.hasMessageBeenConsumedAtCheckpoint([blockNumber, messageLeafId]);
449
+ const isConsumedAfter = await this.outbox.read.hasMessageBeenConsumedAtEpoch([BigInt(epochNumber), messageLeafId]);
449
450
  if (!isConsumedAfter) {
450
451
  throw new Error(
451
- `L1 to L2 message at block ${blockNumber} index ${messageIndex} height ${siblingPath.pathSize} not consumed after withdrawal`,
452
+ `L2 to L1 message at epoch ${epochNumber} index ${messageIndex} height ${siblingPath.pathSize} not consumed after withdrawal`,
452
453
  );
453
454
  }
454
455
  }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Generates type-safe contract wrappers for protocol contracts.
3
+ * These wrappers use a minimal artifact (without bytecode) since PXE already has the full artifacts registered.
4
+ */
5
+ import { generateTypescriptContractInterface } from '@aztec/builder/codegen';
6
+ import {
7
+ type ContractArtifact,
8
+ type FunctionAbi,
9
+ FunctionType,
10
+ getAllFunctionAbis,
11
+ loadContractArtifact,
12
+ } from '@aztec/stdlib/abi';
13
+ import type { NoirCompiledContract } from '@aztec/stdlib/noir';
14
+
15
+ import { promises as fs } from 'fs';
16
+ import path from 'path';
17
+
18
+ const log = console.log;
19
+
20
+ const noirContractsRoot = path.join(import.meta.dirname, '../../../../noir-projects/noir-contracts');
21
+ const srcPath = path.join(noirContractsRoot, 'target');
22
+ const outputDir = path.join(import.meta.dirname, '../contract/protocol_contracts');
23
+
24
+ function toKebabCase(str: string): string {
25
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
26
+ }
27
+
28
+ function functionTypeToEnum(type: FunctionType): string {
29
+ switch (type) {
30
+ case FunctionType.PRIVATE:
31
+ return 'FunctionType.PRIVATE';
32
+ case FunctionType.PUBLIC:
33
+ return 'FunctionType.PUBLIC';
34
+ case FunctionType.UTILITY:
35
+ return 'FunctionType.UTILITY';
36
+ }
37
+ }
38
+
39
+ function generateFunctionAbiJson(abi: FunctionAbi): string {
40
+ const baseObj = {
41
+ name: abi.name,
42
+ isOnlySelf: abi.isOnlySelf,
43
+ isStatic: abi.isStatic,
44
+ isInitializer: abi.isInitializer,
45
+ parameters: abi.parameters,
46
+ returnTypes: abi.returnTypes,
47
+ errorTypes: abi.errorTypes,
48
+ };
49
+ const jsonStr = JSON.stringify(baseObj);
50
+ return jsonStr.replace('{', `{ functionType: ${functionTypeToEnum(abi.functionType)},`);
51
+ }
52
+
53
+ function generateProtocolContractArtifact(input: ContractArtifact): string {
54
+ const allAbis = getAllFunctionAbis(input);
55
+ const functionAbis = input.functions.map(f => allAbis.find(abi => abi.name === f.name)!);
56
+ const nonDispatchAbis = input.nonDispatchPublicFunctions;
57
+
58
+ const functionsArray = functionAbis
59
+ .map(abi => `{ ...${generateFunctionAbiJson(abi)}, bytecode: Buffer.from([]), debugSymbols: '' }`)
60
+ .join(',\n ');
61
+
62
+ const nonDispatchArray = nonDispatchAbis.map(abi => generateFunctionAbiJson(abi)).join(',\n ');
63
+
64
+ return `{
65
+ name: '${input.name}',
66
+ functions: [
67
+ ${functionsArray}
68
+ ],
69
+ nonDispatchPublicFunctions: [
70
+ ${nonDispatchArray}
71
+ ],
72
+ outputs: { structs: {}, globals: {} },
73
+ storageLayout: {},
74
+ fileMap: {},
75
+ }`;
76
+ }
77
+
78
+ async function generateProtocolContractInterface(
79
+ input: ContractArtifact,
80
+ protocolContractName: string,
81
+ ): Promise<string> {
82
+ const baseInterface = await generateTypescriptContractInterface(input);
83
+
84
+ // Match everything between "public declare methods: {" and the closing "};"
85
+ const methodsMatch = baseInterface.match(/public declare methods: \{([\s\S]*?)\n \};/);
86
+ if (!methodsMatch) {
87
+ throw new Error('Could not extract methods from generated interface');
88
+ }
89
+
90
+ const artifactCode = generateProtocolContractArtifact(input);
91
+ const contractName = `${input.name}Contract`;
92
+
93
+ return `
94
+ /* Autogenerated file, do not edit! */
95
+
96
+ /* eslint-disable */
97
+ import { ProtocolContractAddress } from '@aztec/protocol-contracts';
98
+ import { FunctionType } from '@aztec/stdlib/abi';
99
+
100
+ import type { ContractArtifact } from '../../api/abi.js';
101
+ import { PublicKeys } from '../../api/keys.js';
102
+ import type { AztecAddressLike, EthAddressLike, FieldLike, FunctionSelectorLike, WrappedFieldLike } from '../../utils/abi_types.js';
103
+ import { ContractBase, type ContractMethod } from '../contract_base.js';
104
+ import { ContractFunctionInteraction } from '../contract_function_interaction.js';
105
+ import type { Wallet } from '../../wallet/wallet.js';
106
+
107
+ const ${contractName}Artifact: ContractArtifact = ${artifactCode};
108
+
109
+ export class ${contractName} extends ContractBase {
110
+ private constructor(wallet: Wallet) {
111
+ super(ProtocolContractAddress.${protocolContractName}, ${contractName}Artifact, wallet);
112
+ }
113
+
114
+ public static at(wallet: Wallet): ${contractName} {
115
+ return new ${contractName}(wallet);
116
+ }
117
+
118
+ public declare methods: {${methodsMatch[1]}
119
+ };
120
+ }
121
+ `;
122
+ }
123
+
124
+ async function main() {
125
+ await fs.rm(outputDir, { recursive: true, force: true });
126
+ await fs.mkdir(outputDir, { recursive: true });
127
+
128
+ const srcNames = JSON.parse(
129
+ await fs.readFile(path.join(noirContractsRoot, 'protocol_contracts.json'), 'utf8'),
130
+ ) as string[];
131
+
132
+ for (const srcName of srcNames) {
133
+ // srcName is like "auth_registry_contract-AuthRegistry", split to get the contract name
134
+ const name = srcName.split('-')[1];
135
+ const artifactPath = path.join(srcPath, `${srcName}.json`);
136
+ const json = JSON.parse(await fs.readFile(artifactPath, 'utf8')) as NoirCompiledContract;
137
+ const contractArtifact = loadContractArtifact(json);
138
+
139
+ const content = await generateProtocolContractInterface(contractArtifact, name);
140
+ const fileName = `${toKebabCase(name)}.ts`;
141
+ await fs.writeFile(path.join(outputDir, fileName), content);
142
+
143
+ log(`Generated ${fileName}`);
144
+ }
145
+ }
146
+
147
+ main().catch(err => {
148
+ console.error('Error generating protocol contract types:', err);
149
+ process.exit(1);
150
+ });
@@ -12,13 +12,7 @@ import {
12
12
  } from '@aztec/stdlib/abi';
13
13
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
14
14
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
15
- import {
16
- type ContractClassMetadata,
17
- ContractClassWithIdSchema,
18
- type ContractInstanceWithAddress,
19
- ContractInstanceWithAddressSchema,
20
- type ContractMetadata,
21
- } from '@aztec/stdlib/contract';
15
+ import { type ContractInstanceWithAddress, ContractInstanceWithAddressSchema } from '@aztec/stdlib/contract';
22
16
  import { Gas } from '@aztec/stdlib/gas';
23
17
  import { AbiDecodedSchema, type ApiSchemaFor, optional, schemas, zodFor } from '@aztec/stdlib/schemas';
24
18
  import {
@@ -60,7 +54,7 @@ export type Aliased<T> = {
60
54
 
61
55
  /**
62
56
  * Options for simulating interactions with the wallet. Overrides the fee settings of an interaction with
63
- * a simplified version that only hints at the wallet wether the interaction contains a
57
+ * a simplified version that only hints at the wallet whether the interaction contains a
64
58
  * fee payment method or not
65
59
  */
66
60
  export type SimulateOptions = Omit<SimulateInteractionOptions, 'fee'> & {
@@ -70,7 +64,7 @@ export type SimulateOptions = Omit<SimulateInteractionOptions, 'fee'> & {
70
64
 
71
65
  /**
72
66
  * Options for profiling interactions with the wallet. Overrides the fee settings of an interaction with
73
- * a simplified version that only hints at the wallet wether the interaction contains a
67
+ * a simplified version that only hints at the wallet whether the interaction contains a
74
68
  * fee payment method or not
75
69
  */
76
70
  export type ProfileOptions = Omit<ProfileInteractionOptions, 'fee'> & {
@@ -80,7 +74,7 @@ export type ProfileOptions = Omit<ProfileInteractionOptions, 'fee'> & {
80
74
 
81
75
  /**
82
76
  * Options for sending/proving interactions with the wallet. Overrides the fee settings of an interaction with
83
- * a simplified version that only hints at the wallet wether the interaction contains a
77
+ * a simplified version that only hints at the wallet whether the interaction contains a
84
78
  * fee payment method or not
85
79
  */
86
80
  export type SendOptions = Omit<SendInteractionOptions, 'fee'> & {
@@ -89,36 +83,40 @@ export type SendOptions = Omit<SendInteractionOptions, 'fee'> & {
89
83
  };
90
84
 
91
85
  /**
92
- * Helper type that represents all methods that can be batched.
86
+ * Helper type that represents all methods that can be batched (all methods except batch itself).
93
87
  */
94
- export type BatchableMethods = Pick<
95
- Wallet,
96
- 'registerContract' | 'sendTx' | 'registerSender' | 'simulateUtility' | 'simulateTx'
97
- >;
88
+ export type BatchableMethods = Omit<Wallet, 'batch'>;
98
89
 
99
90
  /**
100
- * From the batchable methods, we create a type that represents a method call with its name and arguments.
101
- * This is what the wallet will accept as arguments to the `batch` method.
91
+ * A method call with its name and arguments.
102
92
  */
103
- export type BatchedMethod<T extends keyof BatchableMethods> = {
93
+ type BatchedMethodInternal<T extends keyof BatchableMethods> = {
104
94
  /** The method name */
105
95
  name: T;
106
96
  /** The method arguments */
107
97
  args: Parameters<BatchableMethods[T]>;
108
98
  };
109
99
 
100
+ /**
101
+ * Union of all possible batched method calls.
102
+ * This ensures type safety: the `args` must match the specific `name`.
103
+ */
104
+ export type BatchedMethod = {
105
+ [K in keyof BatchableMethods]: BatchedMethodInternal<K>;
106
+ }[keyof BatchableMethods];
107
+
110
108
  /**
111
109
  * Helper type to extract the return type of a batched method
112
110
  */
113
111
  export type BatchedMethodResult<T> =
114
- T extends BatchedMethod<infer K> ? Awaited<ReturnType<BatchableMethods[K]>> : never;
112
+ T extends BatchedMethodInternal<infer K> ? Awaited<ReturnType<BatchableMethods[K]>> : never;
115
113
 
116
114
  /**
117
115
  * Wrapper type for batch results that includes the method name for discriminated union deserialization.
118
116
  * Each result is wrapped as \{ name: 'methodName', result: ActualResult \} to allow proper deserialization
119
117
  * when AztecAddress and TxHash would otherwise be ambiguous (both are hex strings).
120
118
  */
121
- export type BatchedMethodResultWrapper<T extends BatchedMethod<keyof BatchableMethods>> = {
119
+ export type BatchedMethodResultWrapper<T extends BatchedMethod> = {
122
120
  /** The method name */
123
121
  name: T['name'];
124
122
  /** The method result */
@@ -128,7 +126,7 @@ export type BatchedMethodResultWrapper<T extends BatchedMethod<keyof BatchableMe
128
126
  /**
129
127
  * Maps a tuple of BatchedMethod to a tuple of their wrapped return types
130
128
  */
131
- export type BatchResults<T extends readonly BatchedMethod<keyof BatchableMethods>[]> = {
129
+ export type BatchResults<T extends readonly BatchedMethod[]> = {
132
130
  [K in keyof T]: BatchedMethodResultWrapper<T[K]>;
133
131
  };
134
132
 
@@ -164,18 +162,44 @@ export type PrivateEvent<T> = {
164
162
  metadata: InTx;
165
163
  };
166
164
 
165
+ /**
166
+ * Contract metadata including deployment and registration status.
167
+ */
168
+ export type ContractMetadata = {
169
+ /** The contract instance */
170
+ instance?: ContractInstanceWithAddress;
171
+ /** Whether the contract has been initialized (init nullifier exists) */
172
+ isContractInitialized: boolean;
173
+ /** Whether the contract instance is publicly deployed on-chain */
174
+ isContractPublished: boolean;
175
+ /** Whether the contract has been updated to a different class */
176
+ isContractUpdated: boolean;
177
+ /** The updated contract class ID if the contract has been updated */
178
+ updatedContractClassId?: Fr | undefined;
179
+ };
180
+
181
+ /**
182
+ * Contract class metadata.
183
+ */
184
+ export type ContractClassMetadata = {
185
+ /** Whether the artifact is registered in the wallet */
186
+ isArtifactRegistered: boolean;
187
+ /** Whether the contract class is publicly registered on-chain */
188
+ isContractClassPubliclyRegistered: boolean;
189
+ };
190
+
167
191
  /**
168
192
  * The wallet interface.
169
193
  */
170
194
  export type Wallet = {
171
- getContractClassMetadata(id: Fr, includeArtifact?: boolean): Promise<ContractClassMetadata>;
172
- getContractMetadata(address: AztecAddress): Promise<ContractMetadata>;
173
195
  getPrivateEvents<T>(
174
196
  eventMetadata: EventMetadataDefinition,
175
197
  eventFilter: PrivateEventFilter,
176
198
  ): Promise<PrivateEvent<T>[]>;
177
199
  getChainInfo(): Promise<ChainInfo>;
178
200
  getTxReceipt(txHash: TxHash): Promise<TxReceipt>;
201
+ getContractMetadata(address: AztecAddress): Promise<ContractMetadata>;
202
+ getContractClassMetadata(id: Fr): Promise<ContractClassMetadata>;
179
203
  registerSender(address: AztecAddress, alias?: string): Promise<AztecAddress>;
180
204
  getAddressBook(): Promise<Aliased<AztecAddress>[]>;
181
205
  getAccounts(): Promise<Aliased<AztecAddress>[]>;
@@ -189,7 +213,7 @@ export type Wallet = {
189
213
  profileTx(exec: ExecutionPayload, opts: ProfileOptions): Promise<TxProfileResult>;
190
214
  sendTx(exec: ExecutionPayload, opts: SendOptions): Promise<TxHash>;
191
215
  createAuthWit(from: AztecAddress, messageHashOrIntent: Fr | IntentInnerHash | CallIntent): Promise<AuthWitness>;
192
- batch<const T extends readonly BatchedMethod<keyof BatchableMethods>[]>(methods: T): Promise<BatchResults<T>>;
216
+ batch<const T extends readonly BatchedMethod[]>(methods: T): Promise<BatchResults<T>>;
193
217
  };
194
218
 
195
219
  export const FunctionCallSchema = z.object({
@@ -258,45 +282,6 @@ export const MessageHashOrIntentSchema = z.union([
258
282
  }),
259
283
  ]);
260
284
 
261
- export const BatchedMethodSchema = z.union([
262
- z.object({
263
- name: z.literal('registerSender'),
264
- args: z.tuple([schemas.AztecAddress, optional(z.string())]),
265
- }),
266
- z.object({
267
- name: z.literal('registerContract'),
268
- args: z.tuple([ContractInstanceWithAddressSchema, optional(ContractArtifactSchema), optional(schemas.Fr)]),
269
- }),
270
- z.object({
271
- name: z.literal('sendTx'),
272
- args: z.tuple([ExecutionPayloadSchema, SendOptionsSchema]),
273
- }),
274
- z.object({
275
- name: z.literal('simulateUtility'),
276
- args: z.tuple([FunctionCallSchema, optional(z.array(AuthWitness.schema))]),
277
- }),
278
- z.object({
279
- name: z.literal('simulateTx'),
280
- args: z.tuple([ExecutionPayloadSchema, SimulateOptionsSchema]),
281
- }),
282
- ]);
283
-
284
- export const ContractMetadataSchema = zodFor<ContractMetadata>()(
285
- z.object({
286
- contractInstance: z.union([ContractInstanceWithAddressSchema, z.undefined()]),
287
- isContractInitialized: z.boolean(),
288
- isContractPublished: z.boolean(),
289
- }),
290
- );
291
-
292
- export const ContractClassMetadataSchema = zodFor<ContractClassMetadata>()(
293
- z.object({
294
- contractClass: z.union([ContractClassWithIdSchema, z.undefined()]),
295
- isContractClassPubliclyRegistered: z.boolean(),
296
- artifact: z.union([ContractArtifactSchema, z.undefined()]),
297
- }),
298
- );
299
-
300
285
  export const EventMetadataDefinitionSchema = z.object({
301
286
  eventSelector: schemas.EventSelector,
302
287
  abiType: AbiTypeSchema,
@@ -318,14 +303,31 @@ export const PrivateEventFilterSchema = z.object({
318
303
  toBlock: optional(BlockNumberPositiveSchema),
319
304
  });
320
305
 
321
- export const WalletSchema: ApiSchemaFor<Wallet> = {
306
+ export const ContractMetadataSchema = z.object({
307
+ instance: optional(ContractInstanceWithAddressSchema),
308
+ isContractInitialized: z.boolean(),
309
+ isContractPublished: z.boolean(),
310
+ isContractUpdated: z.boolean(),
311
+ updatedContractClassId: optional(schemas.Fr),
312
+ });
313
+
314
+ export const ContractClassMetadataSchema = z.object({
315
+ isArtifactRegistered: z.boolean(),
316
+ isContractClassPubliclyRegistered: z.boolean(),
317
+ });
318
+
319
+ /**
320
+ * Record of all wallet method schemas (excluding batch).
321
+ * This is the single source of truth for method schemas - batch schemas are derived from this.
322
+ */
323
+ const WalletMethodSchemas = {
322
324
  getChainInfo: z
323
325
  .function()
324
326
  .args()
325
327
  .returns(z.object({ chainId: schemas.Fr, version: schemas.Fr })),
326
- getContractClassMetadata: z.function().args(schemas.Fr, optional(z.boolean())).returns(ContractClassMetadataSchema),
327
- getContractMetadata: z.function().args(schemas.AztecAddress).returns(ContractMetadataSchema),
328
328
  getTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema),
329
+ getContractMetadata: z.function().args(schemas.AztecAddress).returns(ContractMetadataSchema),
330
+ getContractClassMetadata: z.function().args(schemas.Fr).returns(ContractClassMetadataSchema),
329
331
  getPrivateEvents: z
330
332
  .function()
331
333
  .args(EventMetadataDefinitionSchema, PrivateEventFilterSchema)
@@ -351,19 +353,46 @@ export const WalletSchema: ApiSchemaFor<Wallet> = {
351
353
  profileTx: z.function().args(ExecutionPayloadSchema, ProfileOptionsSchema).returns(TxProfileResult.schema),
352
354
  sendTx: z.function().args(ExecutionPayloadSchema, SendOptionsSchema).returns(TxHash.schema),
353
355
  createAuthWit: z.function().args(schemas.AztecAddress, MessageHashOrIntentSchema).returns(AuthWitness.schema),
356
+ };
357
+
358
+ /**
359
+ * Creates batch schemas from the individual wallet methods.
360
+ * This allows us to define them once and derive batch schemas automatically,
361
+ * reducing duplication and ensuring consistency.
362
+ */
363
+ function createBatchSchemas<T extends Record<string, z.ZodFunction<z.ZodTuple<any, any>, z.ZodTypeAny>>>(
364
+ methodSchemas: T,
365
+ ) {
366
+ const names = Object.keys(methodSchemas) as (keyof T)[];
367
+
368
+ const namesAndArgs = names.map(name =>
369
+ z.object({
370
+ name: z.literal(name),
371
+ args: methodSchemas[name].parameters(),
372
+ }),
373
+ );
374
+
375
+ const namesAndReturns = names.map(name =>
376
+ z.object({
377
+ name: z.literal(name),
378
+ result: methodSchemas[name].returnType(),
379
+ }),
380
+ );
381
+
382
+ // Type assertion needed because discriminatedUnion expects a tuple type [T, T, ...T[]]
383
+ // but we're building the array dynamically. The runtime behavior is correct.
384
+ return {
385
+ input: z.discriminatedUnion('name', namesAndArgs as [(typeof namesAndArgs)[0], ...typeof namesAndArgs]),
386
+ output: z.discriminatedUnion('name', namesAndReturns as [(typeof namesAndReturns)[0], ...typeof namesAndReturns]),
387
+ };
388
+ }
389
+
390
+ const { input: BatchedMethodSchema, output: BatchedResultSchema } = createBatchSchemas(WalletMethodSchemas);
391
+
392
+ export { BatchedMethodSchema, BatchedResultSchema };
393
+
394
+ export const WalletSchema: ApiSchemaFor<Wallet> = {
395
+ ...WalletMethodSchemas,
354
396
  // @ts-expect-error - ApiSchemaFor cannot properly type generic methods with readonly arrays
355
- batch: z
356
- .function()
357
- .args(z.array(BatchedMethodSchema))
358
- .returns(
359
- z.array(
360
- z.discriminatedUnion('name', [
361
- z.object({ name: z.literal('registerSender'), result: schemas.AztecAddress }),
362
- z.object({ name: z.literal('registerContract'), result: ContractInstanceWithAddressSchema }),
363
- z.object({ name: z.literal('sendTx'), result: TxHash.schema }),
364
- z.object({ name: z.literal('simulateUtility'), result: UtilitySimulationResult.schema }),
365
- z.object({ name: z.literal('simulateTx'), result: TxSimulationResult.schema }),
366
- ]),
367
- ),
368
- ),
397
+ batch: z.function().args(z.array(BatchedMethodSchema)).returns(z.array(BatchedResultSchema)),
369
398
  };
@@ -1,9 +0,0 @@
1
- import type { Wallet } from '../wallet/wallet.js';
2
- import { UnsafeContract } from './unsafe_contract.js';
3
- /** Returns a Contract wrapper for the contract class registry. */
4
- export declare function getClassRegistryContract(wallet: Wallet): Promise<UnsafeContract>;
5
- /** Returns a Contract wrapper for the contract instance registry. */
6
- export declare function getInstanceRegistryContract(wallet: Wallet): Promise<UnsafeContract>;
7
- /** Returns a Contract wrapper for the fee juice contract */
8
- export declare function getFeeJuice(wallet: Wallet): Promise<UnsafeContract>;
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2xfY29udHJhY3RzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29udHJhY3QvcHJvdG9jb2xfY29udHJhY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV0RCxrRUFBa0U7QUFDbEUsd0JBQXNCLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxNQUFNLDJCQVE1RDtBQUVELHFFQUFxRTtBQUNyRSx3QkFBc0IsMkJBQTJCLENBQUMsTUFBTSxFQUFFLE1BQU0sMkJBTy9EO0FBRUQsNERBQTREO0FBQzVELHdCQUFzQixXQUFXLENBQUMsTUFBTSxFQUFFLE1BQU0sMkJBTy9DIn0=
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol_contracts.d.ts","sourceRoot":"","sources":["../../src/contract/protocol_contracts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,kEAAkE;AAClE,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,2BAQ5D;AAED,qEAAqE;AACrE,wBAAsB,2BAA2B,CAAC,MAAM,EAAE,MAAM,2BAO/D;AAED,4DAA4D;AAC5D,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,2BAO/C"}
@@ -1,26 +0,0 @@
1
- import { ProtocolContractAddress } from '@aztec/protocol-contracts';
2
- import { UnsafeContract } from './unsafe_contract.js';
3
- /** Returns a Contract wrapper for the contract class registry. */ export async function getClassRegistryContract(wallet) {
4
- const { contractInstance } = await wallet.getContractMetadata(ProtocolContractAddress.ContractClassRegistry);
5
- if (!contractInstance) {
6
- throw new Error("ContractClassRegistry is not registered in this wallet's instance");
7
- }
8
- const { artifact } = await wallet.getContractClassMetadata(contractInstance.currentContractClassId, true);
9
- return new UnsafeContract(contractInstance, artifact, wallet);
10
- }
11
- /** Returns a Contract wrapper for the contract instance registry. */ export async function getInstanceRegistryContract(wallet) {
12
- const { contractInstance } = await wallet.getContractMetadata(ProtocolContractAddress.ContractInstanceRegistry);
13
- if (!contractInstance) {
14
- throw new Error("ContractInstanceRegistry is not registered in this wallet's instance");
15
- }
16
- const { artifact } = await wallet.getContractClassMetadata(contractInstance.currentContractClassId, true);
17
- return new UnsafeContract(contractInstance, artifact, wallet);
18
- }
19
- /** Returns a Contract wrapper for the fee juice contract */ export async function getFeeJuice(wallet) {
20
- const { contractInstance } = await wallet.getContractMetadata(ProtocolContractAddress.FeeJuice);
21
- if (!contractInstance) {
22
- throw new Error("FeeJuice is not registered in this wallet's instance");
23
- }
24
- const { artifact } = await wallet.getContractClassMetadata(contractInstance.currentContractClassId, true);
25
- return new UnsafeContract(contractInstance, artifact, wallet);
26
- }
@@ -1,15 +0,0 @@
1
- import type { ContractArtifact } from '@aztec/stdlib/abi';
2
- import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
3
- import type { Wallet } from '../wallet/wallet.js';
4
- import { ContractBase } from './contract_base.js';
5
- /** Unsafe constructor for ContractBase that bypasses the check that the instance is registered in the wallet. */
6
- export declare class UnsafeContract extends ContractBase {
7
- constructor(
8
- /** The deployed contract instance definition. */
9
- instance: ContractInstanceWithAddress,
10
- /** The Application Binary Interface for the contract. */
11
- artifact: ContractArtifact,
12
- /** The wallet used for interacting with this contract. */
13
- wallet: Wallet);
14
- }
15
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5zYWZlX2NvbnRyYWN0LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29udHJhY3QvdW5zYWZlX2NvbnRyYWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDMUQsT0FBTyxLQUFLLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUUxRSxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEQsaUhBQWlIO0FBQ2pILHFCQUFhLGNBQWUsU0FBUSxZQUFZO0lBQzlDO0lBQ0UsaURBQWlEO0lBQ2pELFFBQVEsRUFBRSwyQkFBMkI7SUFDckMseURBQXlEO0lBQ3pELFFBQVEsRUFBRSxnQkFBZ0I7SUFDMUIsMERBQTBEO0lBQzFELE1BQU0sRUFBRSxNQUFNLEVBR2Y7Q0FDRiJ9
@@ -1 +0,0 @@
1
- {"version":3,"file":"unsafe_contract.d.ts","sourceRoot":"","sources":["../../src/contract/unsafe_contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,iHAAiH;AACjH,qBAAa,cAAe,SAAQ,YAAY;IAC9C;IACE,iDAAiD;IACjD,QAAQ,EAAE,2BAA2B;IACrC,yDAAyD;IACzD,QAAQ,EAAE,gBAAgB;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAGf;CACF"}
@@ -1,6 +0,0 @@
1
- import { ContractBase } from './contract_base.js';
2
- /** Unsafe constructor for ContractBase that bypasses the check that the instance is registered in the wallet. */ export class UnsafeContract extends ContractBase {
3
- constructor(/** The deployed contract instance definition. */ instance, /** The Application Binary Interface for the contract. */ artifact, /** The wallet used for interacting with this contract. */ wallet){
4
- super(instance.address, artifact, wallet);
5
- }
6
- }