Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(types): simplify types for init functions, cleanup contructors #345

Merged
merged 4 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"allowed_elements": ["details", "summary"]
}
},
"cSpell.words": ["redelegate", "redelegating"]
"cSpell.words": ["ARIO", "redelegate", "redelegating"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
"dependencies": {
"@dha-team/arbundles": "^1.0.1",
"@permaweb/aoconnect": "^0.0.57",
"arweave": "1.14.4",
"arweave": "1.15.5",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this always makes me nervous. will do some validations across our clients (observer, ar-io-node, network-portal, arns.app) to validate if it causes any issues

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor version bump -- "Drop Node 16 Support". that semantic versioning 😂

"axios": "1.7.9",
"axios-retry": "^4.3.0",
"commander": "^12.1.0",
Expand Down
53 changes: 24 additions & 29 deletions src/common/ant-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
import {
AoMessageResult,
AoSigner,
OptionalSigner,
ProcessConfiguration,
WithSigner,
isProcessConfiguration,
Expand All @@ -30,24 +29,25 @@ import {
import { createAoSigner } from '../utils/ao.js';
import { AOProcess, InvalidContractConfigurationError } from './index.js';

type ANTRegistryNoSigner = ProcessConfiguration;
type ANTRegistryWithSigner = WithSigner<ProcessConfiguration>;
type ANTRegistryConfig = ANTRegistryNoSigner | ANTRegistryWithSigner;

export class ANTRegistry {
// by default give read
static init(): AoANTRegistryRead;

// no signer give read
static init(config: ANTRegistryNoSigner): AoANTRegistryRead;

// with signer give write
static init(config: ANTRegistryWithSigner): AoANTRegistryWrite;

static init(
config: Required<ProcessConfiguration> & { signer?: undefined },
): AoANTRegistryRead;
static init({
signer,
...config
}: WithSigner<Required<ProcessConfiguration>>): AoANTRegistryWrite;
static init(
config?: OptionalSigner<ProcessConfiguration>,
config?: ANTRegistryConfig,
): AoANTRegistryRead | AoANTRegistryWrite {
if (config && config.signer) {
const { signer, ...rest } = config;
return new AoANTRegistryWriteable({
...rest,
signer,
});
if (config !== undefined && 'signer' in config) {
return new AoANTRegistryWriteable(config);
}
return new AoANTRegistryReadable(config);
}
Expand All @@ -57,23 +57,18 @@ export class AoANTRegistryReadable implements AoANTRegistryRead {
protected process: AOProcess;

constructor(config?: ProcessConfiguration) {
if (
config &&
(isProcessIdConfiguration(config) || isProcessConfiguration(config))
) {
if (isProcessConfiguration(config)) {
this.process = config.process;
} else if (isProcessIdConfiguration(config)) {
this.process = new AOProcess({
processId: config.processId,
});
} else {
throw new InvalidContractConfigurationError();
}
} else {
if (config === undefined || Object.keys(config).length === 0) {
this.process = new AOProcess({
processId: ANT_REGISTRY_ID,
});
} else if (isProcessConfiguration(config)) {
this.process = config.process;
} else if (isProcessIdConfiguration(config)) {
this.process = new AOProcess({
processId: config.processId,
});
} else {
throw new InvalidContractConfigurationError();
}
}

Expand Down
48 changes: 19 additions & 29 deletions src/common/ant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
import {
AoMessageResult,
AoSigner,
OptionalSigner,
ProcessConfiguration,
WalletAddress,
WithSigner,
Expand All @@ -45,43 +44,34 @@ import { createAoSigner } from '../utils/ao.js';
import { parseSchemaResult } from '../utils/schema.js';
import { AOProcess, InvalidContractConfigurationError } from './index.js';

type ANTConfigOptionalStrict = Required<ProcessConfiguration> & {
strict?: boolean;
};
type ANTConfigNoSigner = ANTConfigOptionalStrict;
type ANTConfigWithSigner = WithSigner<ANTConfigOptionalStrict>;
type ANTConfig = ANTConfigNoSigner | ANTConfigWithSigner;

export class ANT {
static init(
config: Required<ProcessConfiguration> & {
signer?: undefined;
strict?: boolean;
},
): AoANTRead;
static init({
signer,
...config
}: WithSigner<Required<ProcessConfiguration>> & {
strict?: boolean;
}): AoANTWrite;
static init({
signer,
strict = false,
...config
}: OptionalSigner<Required<ProcessConfiguration>> & { strict?: boolean }):
| AoANTRead
| AoANTWrite {
// ao supported implementation
if (isProcessConfiguration(config) || isProcessIdConfiguration(config)) {
if (!signer) {
return new AoANTReadable({ strict, ...config });
}
return new AoANTWriteable({ signer, strict, ...config });
}
// no signer give read
static init(config: ANTConfigNoSigner): AoANTRead;

throw new InvalidContractConfigurationError();
// with signer give write
static init(config: ANTConfigWithSigner): AoANTWrite;

// implementation
static init(config: ANTConfig): AoANTRead | AoANTWrite {
if (config !== undefined && 'signer' in config) {
return new AoANTWriteable(config);
}
return new AoANTReadable(config);
}
}

export class AoANTReadable implements AoANTRead {
protected process: AOProcess;
private strict: boolean;

constructor(config: Required<ProcessConfiguration> & { strict?: boolean }) {
constructor(config: ANTConfigOptionalStrict) {
this.strict = config.strict || false;
if (isProcessConfiguration(config)) {
this.process = config.process;
Expand Down
94 changes: 25 additions & 69 deletions src/common/io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ import {
AoTokenSupplyData,
AoUpdateGatewaySettingsParams,
AoWeightedObserver,
ContractSigner,
OptionalSigner,
OptionalArweave,
PaginationParams,
PaginationResult,
ProcessConfiguration,
Expand Down Expand Up @@ -82,57 +81,36 @@ import { defaultArweave } from './arweave.js';
import { AOProcess } from './contracts/ao-process.js';
import { InvalidContractConfigurationError } from './error.js';

type ARIOConfigNoSigner = OptionalArweave<ProcessConfiguration>;
type ARIOConfigWithSigner = WithSigner<OptionalArweave<ProcessConfiguration>>;
type ARIOConfig = ARIOConfigNoSigner | ARIOConfigWithSigner;

export class ARIO {
// Overload: No arguments -> returns AoARIORead
static init(): AoARIORead;
static init({ process }: { process: AOProcess }): AoARIORead;
static init({
process,
signer,
}: WithSigner<{ process: AOProcess }>): AoARIOWrite;
static init({
processId,
signer,
}: WithSigner<{
processId?: string;
}>): AoARIOWrite;
static init({
processId,
signer,
}: {
signer?: ContractSigner | undefined;
processId: string;
});
static init({ processId }: { processId: string }): AoARIORead;
static init({
arweave,
...config
}: OptionalSigner<ProcessConfiguration> & { arweave?: Arweave } = {}):
| AoARIORead
| AoARIOWrite {
if (config !== undefined && config.signer) {
const { signer, ...rest } = config;
return new ARIOWriteable({
...rest,
signer,
arweave,
});

// Overload: config with signer -> returns AoARIOWrite
static init(config: ARIOConfigWithSigner): AoARIOWrite;

// Overload: config without signer -> returns AoARIORead
static init(config: ARIOConfigNoSigner): AoARIORead;

// Implementation
static init(config?: ARIOConfig): AoARIORead | AoARIOWrite {
if (config !== undefined && 'signer' in config) {
return new ARIOWriteable(config);
}
return new ARIOReadable({
arweave,
...config,
});
return new ARIOReadable(config);
}
}

export class ARIOReadable implements AoARIORead {
protected process: AOProcess;
protected epochSettings: AoEpochSettings | undefined;
protected arweave: Arweave;
constructor({
arweave = defaultArweave,
...config
}: ProcessConfiguration & { arweave?: Arweave }) {
if (config === undefined) {
constructor(config?: OptionalArweave<ProcessConfiguration>) {
this.arweave = config?.arweave ?? defaultArweave;
if (config === undefined || Object.keys(config).length === 0) {
this.process = new AOProcess({
processId: ARIO_TESTNET_PROCESS_ID,
});
Expand All @@ -145,7 +123,6 @@ export class ARIOReadable implements AoARIORead {
} else {
throw new InvalidContractConfigurationError();
}
this.arweave = arweave;
}

async getInfo(): Promise<{
Expand Down Expand Up @@ -740,38 +717,17 @@ export class ARIOReadable implements AoARIORead {
export class ARIOWriteable extends ARIOReadable implements AoARIOWrite {
protected declare process: AOProcess;
private signer: AoSigner;
constructor({
signer,
arweave,
...config
}: WithSigner<
| {
process?: AOProcess;
}
| { processId?: string }
> & { arweave?: Arweave }) {
if (Object.keys(config).length === 0) {
constructor({ signer, ...config }: ARIOConfigWithSigner) {
if (config === undefined) {
super({
process: new AOProcess({
processId: ARIO_TESTNET_PROCESS_ID,
}),
arweave: arweave,
});
this.signer = createAoSigner(signer);
} else if (isProcessConfiguration(config)) {
super({ process: config.process });
this.signer = createAoSigner(signer);
} else if (isProcessIdConfiguration(config)) {
super({
process: new AOProcess({
processId: config.processId,
}),
arweave: arweave,
});
this.signer = createAoSigner(signer);
} else {
throw new InvalidContractConfigurationError();
super(config);
}
this.signer = createAoSigner(signer);
}

async transfer(
Expand Down
5 changes: 4 additions & 1 deletion src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
spawn,
unmonitor,
} from '@permaweb/aoconnect';
import Arweave from 'arweave';

import { AoSigner } from './token.js';

Expand All @@ -33,7 +34,9 @@ export type WalletAddress = string;
export type TransactionId = string;
export type ProcessId = string;

// TODO: append this with other configuration options (e.g. local vs. remote evaluation)
export type OptionalArweave<T = NonNullable<unknown>> = {
arweave?: Arweave;
} & T;
export type ContractSigner = Signer | Window['arweaveWallet'] | AoSigner;
export type WithSigner<T = NonNullable<unknown>> = {
signer: ContractSigner;
Expand Down
40 changes: 21 additions & 19 deletions src/types/io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,25 @@ export type PaginationResult<T> = {
hasMore: boolean;
};

// Configuration
export type ProcessConfiguration =
| {
process?: AOProcess;
}
| {
processId?: string;
};
export type ProcessIdConfig = {
processId?: string;
};

export type EpochInput =
| {
epochIndex: AoEpochIndex;
}
| {
timestamp: Timestamp;
}
| undefined;
export type ProcessConfig = {
process?: AOProcess;
};

export type ProcessConfiguration = ProcessConfig | ProcessIdConfig;

export type EpochTimestampInput = {
timestamp: Timestamp;
};

export type EpochIndexInput = {
epochIndex: AoEpochIndex;
};

export type EpochInput = EpochTimestampInput | EpochIndexInput | undefined;

// AO/ARIO Contract
export type AoBalances = Record<WalletAddress, number>;
Expand Down Expand Up @@ -159,7 +161,7 @@ export type AoEpochData = {
startTimestamp: Timestamp;
endTimestamp: Timestamp;
distributionTimestamp: Timestamp;
// @deprecated - use `getDistributions` to get distribution data for a given epoch
/** @deprecated - use `getDistributions` to get distribution data for a given epoch **/
distributions: AoEpochDistributionData;
};
export type AoTokenSupplyData = {
Expand Down Expand Up @@ -689,13 +691,13 @@ export interface AoARIOWrite extends AoARIORead {
// Typeguard functions
export function isProcessConfiguration(
config: object,
): config is { process: AOProcess } {
): config is Required<ProcessConfiguration> & Record<string, never> {
return 'process' in config;
}

export function isProcessIdConfiguration(
config: object,
): config is { processId: string } {
): config is Required<ProcessIdConfig> & Record<string, never> {
return (
'processId' in config &&
typeof config.processId === 'string' &&
Expand Down
Loading
Loading