diff --git a/src/common/ant-registry.ts b/src/common/ant-registry.ts
new file mode 100644
index 00000000..a1f348b3
--- /dev/null
+++ b/src/common/ant-registry.ts
@@ -0,0 +1,106 @@
+/**
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+import { ANT_REGISTRY_ID } from '../constants.js';
+import {
+ AoANTRegistryRead,
+ AoANTRegistryWrite,
+ AoMessageResult,
+ AoSigner,
+ OptionalSigner,
+ ProcessConfiguration,
+ WithSigner,
+ isProcessConfiguration,
+ isProcessIdConfiguration,
+} from '../types.js';
+import { createAoSigner } from '../utils/ao.js';
+import { AOProcess } from './index.js';
+
+export class ANTRegistry {
+ static init(): AoANTRegistryRead;
+ static init(
+ config: Required & { signer?: undefined },
+ ): AoANTRegistryRead;
+ static init({
+ signer,
+ ...config
+ }: WithSigner>): AoANTRegistryRead;
+ static init(
+ config?: OptionalSigner,
+ ): AoANTRegistryRead | AoANTRegistryWrite {
+ if (config && config.signer) {
+ const { signer, ...rest } = config;
+ return new AoANTRegistryWriteable({
+ ...rest,
+ signer,
+ });
+ }
+ return new AoANTRegistryReadable(config);
+ }
+}
+
+export class AoANTRegistryReadable implements AoANTRegistryRead {
+ protected process: AOProcess;
+
+ constructor(config?: ProcessConfiguration) {
+ if (
+ config &&
+ (isProcessIdConfiguration(config) || isProcessConfiguration(config))
+ ) {
+ this.process = AOProcess.fromConfiguration(config);
+ } else {
+ this.process = AOProcess.fromConfiguration({
+ processId: ANT_REGISTRY_ID,
+ });
+ }
+ }
+
+ // Should we rename this to "getANTsByAddress"? seems more clear, though not same as handler name
+ async accessControlList({ address }: { address: string }): Promise {
+ return this.process.read({
+ tags: [
+ { name: 'Action', value: 'Access-Control-List' },
+ { name: 'Address', value: address },
+ ],
+ });
+ }
+}
+
+export class AoANTRegistryWriteable
+ extends AoANTRegistryReadable
+ implements AoANTRegistryWrite
+{
+ private signer: AoSigner;
+
+ constructor({ signer, ...config }: WithSigner) {
+ super(config);
+ this.signer = createAoSigner(signer);
+ }
+
+ async register({
+ processId,
+ }: {
+ processId: string;
+ }): Promise {
+ return this.process.send({
+ tags: [
+ { name: 'Action', value: 'Register' },
+ { name: 'Process-Id', value: processId },
+ ],
+ signer: this.signer,
+ });
+ }
+}
diff --git a/src/common/contracts/ao-process.ts b/src/common/contracts/ao-process.ts
index 3ed4a61c..9e20e2e0 100644
--- a/src/common/contracts/ao-process.ts
+++ b/src/common/contracts/ao-process.ts
@@ -16,10 +16,20 @@
*/
import { connect } from '@permaweb/aoconnect';
-import { AOContract, AoClient, AoSigner } from '../../types.js';
+import {
+ AOContract,
+ AoClient,
+ AoSigner,
+ ProcessConfiguration,
+ isProcessConfiguration,
+ isProcessIdConfiguration,
+} from '../../types.js';
import { safeDecode } from '../../utils/json.js';
import { version } from '../../version.js';
-import { WriteInteractionError } from '../error.js';
+import {
+ InvalidContractConfigurationError,
+ WriteInteractionError,
+} from '../error.js';
import { ILogger, Logger } from '../logger.js';
export class AOProcess implements AOContract {
@@ -41,6 +51,18 @@ export class AOProcess implements AOContract {
this.ao = ao;
}
+ static fromConfiguration(config: Required) {
+ if (isProcessConfiguration(config)) {
+ return config.process;
+ } else if (isProcessIdConfiguration(config)) {
+ return new AOProcess({
+ processId: config.processId,
+ });
+ } else {
+ throw new InvalidContractConfigurationError();
+ }
+ }
+
async read({
tags,
retries = 3,
diff --git a/src/common/index.ts b/src/common/index.ts
index 63a144b8..959e5ea1 100644
--- a/src/common/index.ts
+++ b/src/common/index.ts
@@ -17,6 +17,7 @@
export * from './error.js';
export * from './logger.js';
export * from './ant.js';
+export * from './ant-registry.js';
// ao
export * from './io.js';
diff --git a/src/constants.ts b/src/constants.ts
index 7b72e504..f6308c9d 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -37,6 +37,10 @@ export const IO_DEVNET_PROCESS_ID =
export const ioDevnetProcessId = IO_DEVNET_PROCESS_ID;
export const IO_TESTNET_PROCESS_ID =
'agYcCFJtrMG6cqMuZfskIkFTGvUPddICmtQSBIoPdiA';
+
+// TODO: set ant registry ID with deployed contract
+export const ANT_REGISTRY_ID =
+ process.env.ANT_REGISTRY_ID ?? 'todo-set-ant-registry-id';
export const MIO_PER_IO = 1_000_000;
export const AOS_MODULE_ID = 'cbn0KKrBZH7hdNkNokuXLtGryrWM--PjSTBqIzw9Kkk';
export const ANT_LUA_ID = 'Flwio4Lr08g6s6uim6lEJNnVGD9ylvz0_aafvpiL8FI';
diff --git a/src/io.ts b/src/io.ts
index 27c36553..3f8d755f 100644
--- a/src/io.ts
+++ b/src/io.ts
@@ -325,6 +325,14 @@ export interface AoANTWrite extends AoANTRead {
setName({ name }): Promise;
}
+export interface AoANTRegistryRead {
+ accessControlList(params: { address: string }): Promise;
+}
+
+export interface AoANTRegistryWrite extends AoANTRegistryRead {
+ register(params: { processId: string }): Promise;
+}
+
// AO Contract types
export interface AoIOState {
GatewayRegistry: Record;