Skip to content

Commit

Permalink
Merge pull request #371 from ar-io/ant-base-name-and-undername-commands
Browse files Browse the repository at this point in the history
feat(ant apis): add commands for new methods
  • Loading branch information
fedellen authored Jan 29, 2025
2 parents 58c77b9 + df830b6 commit 17d175f
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 186 deletions.
4 changes: 3 additions & 1 deletion CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ Commands:
transfer-ant-ownership [options] Transfer ownership of an ANT process
add-ant-controller [options] Add a controller to an ANT process
remove-ant-controller [options] Remove a controller from an ANT process
set-ant-record [options] Set a record of an ANT process
set-ant-record [options] Set a record of an ANT process. Deprecated: use set-ant-base-name and set-ant-undername
set-ant-base-name [options] Set the base name of an ANT process
set-ant-undername [options] Set an undername of an ANT process
remove-ant-record [options] Remove a record from an ANT process
set-ant-ticker [options] Set the ticker of an ANT process
set-ant-name [options] Set the name of an ANT process
Expand Down
59 changes: 23 additions & 36 deletions src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import { program } from 'commander';
import { AOProcess, AoMessageResult, spawnANT } from '../node/index.js';
import { mARIOToken } from '../types/token.js';
import { version } from '../version.js';
import {
setAntBaseNameCLICommand,
setAntRecordCLICommand,
} from './commands/antCommands.js';
import {
buyRecordCLICommand,
extendLeaseCLICommand,
Expand Down Expand Up @@ -85,6 +89,8 @@ import {
paginationAddressOptions,
paginationOptions,
redelegateStakeOptions,
setAntBaseNameOptions,
setAntUndernameOptions,
tokenCostOptions,
transferOptions,
updateGatewaySettingsOptions,
Expand Down Expand Up @@ -738,45 +744,26 @@ makeCommand<ProcessIdCLIOptions & { controller?: string }>({
},
});

makeCommand<
ProcessIdWriteActionCLIOptions & {
undername?: string;
transactionId?: string;
ttlSeconds?: number;
}
>({
makeCommand({
name: 'set-ant-record',
description: 'Set a record of an ANT process',
options: [
optionMap.processId,
optionMap.undername,
optionMap.transactionId,
optionMap.ttlSeconds,
...writeActionOptions,
],
action: async (options) => {
const ttlSeconds = options.ttlSeconds ?? 3600;
const undername = requiredStringFromOptions(options, 'undername');
const transactionId = requiredStringFromOptions(options, 'transactionId');
description:
'Set a record of an ANT process. Deprecated: use set-ant-base-name and set-ant-undername',
options: setAntUndernameOptions,
action: setAntRecordCLICommand,
});

await assertConfirmationPrompt(
`Are you sure you want to set this record?\n${JSON.stringify(
{ undername, transactionId, ttlSeconds },
null,
2,
)}`,
options,
);
makeCommand({
name: 'set-ant-base-name',
description: 'Set the base name of an ANT process',
options: setAntBaseNameOptions,
action: setAntBaseNameCLICommand,
});

return writeANTFromOptions(options).setRecord(
{
undername,
transactionId,
ttlSeconds,
},
writeActionTagsFromOptions(options),
);
},
makeCommand({
name: 'set-ant-undername',
description: 'Set an undername of an ANT process',
options: setAntUndernameOptions,
action: setAntRecordCLICommand,
});

makeCommand<ProcessIdWriteActionCLIOptions & { undername?: string }>({
Expand Down
116 changes: 116 additions & 0 deletions src/cli/commands/antCommands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
AoANTSetBaseNameRecordParams,
AoANTSetUndernameRecordParams,
} from '../../types/ant.js';
import { CLIWriteOptionsFromAoAntParams } from '../types.js';
import {
assertConfirmationPrompt,
defaultTtlSecondsCLI,
requiredStringFromOptions,
writeANTFromOptions,
writeActionTagsFromOptions,
} from '../utils.js';

/** @deprecated -- use set-ant-base-name and set-ant-undername */
export async function setAntRecordCLICommand(
o: CLIWriteOptionsFromAoAntParams<AoANTSetUndernameRecordParams>,
) {
const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI);
const undername = requiredStringFromOptions(o, 'undername');
const transactionId = requiredStringFromOptions(o, 'transactionId');

const writeAnt = writeANTFromOptions(o);

if (!o.skipConfirmation) {
await assertConfirmationPrompt(
`Are you sure you want to set this record on the ANT process ${writeAnt.processId}?\n${JSON.stringify(
{ undername, transactionId, ttlSeconds },
null,
2,
)}`,
o,
);
}

return writeANTFromOptions(o).setRecord(
{
undername,
transactionId,
ttlSeconds,
},
writeActionTagsFromOptions(o),
);
}

export async function setAntBaseNameCLICommand(
o: CLIWriteOptionsFromAoAntParams<AoANTSetBaseNameRecordParams>,
) {
const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI);
const transactionId = requiredStringFromOptions(o, 'transactionId');

const writeAnt = writeANTFromOptions(o);

if (!o.skipConfirmation) {
await assertConfirmationPrompt(
`Are you sure you want to set this base name on the ANT process ${writeAnt.processId}?\n${JSON.stringify(
{ transactionId, ttlSeconds },
null,
2,
)}`,
o,
);
}

return writeANTFromOptions(o).setBaseNameRecord(
{
transactionId,
ttlSeconds,
},
writeActionTagsFromOptions(o),
);
}

export async function setAntUndernameCLICommand(
o: CLIWriteOptionsFromAoAntParams<AoANTSetUndernameRecordParams>,
) {
const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI);
const undername = requiredStringFromOptions(o, 'undername');
const transactionId = requiredStringFromOptions(o, 'transactionId');

const writeAnt = writeANTFromOptions(o);

if (!o.skipConfirmation) {
await assertConfirmationPrompt(
`Are you sure you want to set this undername on the ANT process ${writeAnt.processId}?\n${JSON.stringify(
{ undername, transactionId, ttlSeconds },
null,
2,
)}`,
o,
);
}

return writeANTFromOptions(o).setUndernameRecord(
{
undername,
transactionId,
ttlSeconds,
},
writeActionTagsFromOptions(o),
);
}
12 changes: 12 additions & 0 deletions src/cli/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,15 @@ export const antStateOptions = [
optionMap.controllers,
optionMap.ttlSeconds,
];

export const setAntBaseNameOptions = [
optionMap.processId,
optionMap.transactionId,
optionMap.ttlSeconds,
...writeActionOptions,
];

export const setAntUndernameOptions = [
...setAntBaseNameOptions,
optionMap.undername,
];
4 changes: 4 additions & 0 deletions src/cli/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export type CLIReadOptionsFromAoParams<T> = CLIOptionsFromAoParams<T> &
export type CLIWriteOptionsFromAoParams<T> = WriteActionCLIOptions &
CLIOptionsFromAoParams<T>;

export type CLIWriteOptionsFromAoAntParams<T> = CLIWriteOptionsFromAoParams<
T & { processId: string }
>;

export type PaginationCLIOptions = GlobalCLIOptions &
CLIOptionsFromAoParams<PaginationParams>;

Expand Down
7 changes: 6 additions & 1 deletion src/cli/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ import {
WriteActionCLIOptions,
} from './types.js';

export const defaultTtlSecondsCLI = 3600;

export function stringifyJsonForCLIDisplay(
json: JsonSerializable | unknown,
): string {
Expand Down Expand Up @@ -612,7 +614,10 @@ export function getANTStateFromOptions(
ticker: options.ticker,
name: options.name,
keywords: options.keywords,
ttlSeconds: options.ttlSeconds !== undefined ? +options.ttlSeconds : 3600,
ttlSeconds:
options.ttlSeconds !== undefined
? +options.ttlSeconds
: defaultTtlSecondsCLI,
});
}

Expand Down
73 changes: 30 additions & 43 deletions src/common/ant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
AoANTInfo,
AoANTRead,
AoANTRecord,
AoANTSetBaseNameRecordParams,
AoANTSetUndernameRecordParams,
AoANTState,
AoANTWrite,
} from '../types/ant.js';
Expand Down Expand Up @@ -69,6 +71,7 @@ export class ANT {

export class AoANTReadable implements AoANTRead {
protected process: AOProcess;
public readonly processId: string;
private strict: boolean;

constructor(config: ANTConfigOptionalStrict) {
Expand All @@ -82,6 +85,8 @@ export class AoANTReadable implements AoANTRead {
} else {
throw new InvalidContractConfigurationError();
}

this.processId = this.process.processId;
}

async getState(
Expand Down Expand Up @@ -393,21 +398,9 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite {
* @param transactionId @type {string} The transactionId of the record.
* @param ttlSeconds @type {number} The time to live of the record.
* @returns {Promise<AoMessageResult>} The result of the interaction.
* @example
* ```ts
* ant.setController({ controller: "fGht8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk" });
* ```
*/
async setRecord(
{
undername,
transactionId,
ttlSeconds,
}: {
undername: string;
transactionId: string;
ttlSeconds: number;
},
{ undername, transactionId, ttlSeconds }: AoANTSetUndernameRecordParams,
options?: WriteOptions,
): Promise<AoMessageResult> {
return this.process.send({
Expand All @@ -433,22 +426,18 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite {
* ant.setBaseNameRecord({ transactionId: "432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM", ttlSeconds: 100 }); // ardrive.ar.io will resolve to the provided transaction id and be cached for 100 seconds by clients
* ```
*/
async setBaseNameRecord({
transactionId,
ttlSeconds,
}: {
transactionId: string;
ttlSeconds: number;
}): Promise<AoMessageResult> {
return this.process.send({
tags: [
{ name: 'Action', value: 'Set-Record' },
{ name: 'Sub-Domain', value: '@' },
{ name: 'Transaction-Id', value: transactionId },
{ name: 'TTL-Seconds', value: ttlSeconds.toString() },
],
signer: this.signer,
});
async setBaseNameRecord(
{ transactionId, ttlSeconds }: AoANTSetBaseNameRecordParams,
options?: WriteOptions,
): Promise<AoMessageResult> {
return this.setRecord(
{
transactionId,
ttlSeconds,
undername: '@',
},
options,
);
}

/**
Expand All @@ -463,20 +452,18 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite {
* ant.setUndernameRecord({ undername: "dapp", transactionId: "432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM", ttlSeconds: 100 }); // dapp_ardrive.ar.io will resolve to the provided transaction id and be cached for 100 seconds by clients
* ```
*/
async setUndernameRecord({
undername,
transactionId,
ttlSeconds,
}: {
undername: string;
transactionId: string;
ttlSeconds: number;
}): Promise<AoMessageResult> {
return this.setRecord({
undername,
transactionId,
ttlSeconds,
});
async setUndernameRecord(
{ undername, transactionId, ttlSeconds }: AoANTSetUndernameRecordParams,
options?: WriteOptions,
): Promise<AoMessageResult> {
return this.setRecord(
{
undername,
transactionId,
ttlSeconds,
},
options,
);
}

/**
Expand Down
Loading

0 comments on commit 17d175f

Please sign in to comment.