Skip to content

Commit

Permalink
Merge pull request #52 from ar-io/type-cleanup
Browse files Browse the repository at this point in the history
fix(types): use generic types and make config optional on `init` for ArIO client
  • Loading branch information
dtfiedler authored Apr 25, 2024
2 parents f0e012f + 4a3ee89 commit 881c54b
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 159 deletions.
2 changes: 1 addition & 1 deletion examples/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</script>

<script type="module" defer>
import { ArIO } from 'https://unpkg.com/@ar.io/sdk@1.0.0';
import { ArIO } from '../../bundles/web.bundle.min.js';

const arIO = ArIO.init();

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"prepare": "husky install",
"example:mjs": "yarn build:esm && node examples/node/index.mjs",
"example:cjs": "yarn build:cjs && node examples/node/index.cjs",
"example:web": "yarn build:web && cp -r bundles/* examples/web && http-server --port 8080 --host -o examples/web"
"example:web": "yarn build:web && http-server --port 8080 --host -o examples/web"
},
"devDependencies": {
"@commitlint/cli": "^17.1.2",
Expand Down
41 changes: 18 additions & 23 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,18 @@ export type TransactionId = string;

// TODO: append this with other configuration options (e.g. local vs. remote evaluation)
export type ContractSigner = ArweaveSigner | ArconnectSigner;
export type WithSigner = { signer: ContractSigner }; // TODO: optionally allow JWK in place of signer
export type ContractConfiguration =
export type WithSigner<T = NonNullable<unknown>> = {
signer: ContractSigner;
} & T; // TODO: optionally allow JWK in place of signer
export type OptionalSigner<T = NonNullable<unknown>> = {
signer?: ContractSigner;
} & T;
export type ContractConfiguration<T = NonNullable<unknown>> =
| {
contract?: WarpContract<unknown> | RemoteContract<unknown>;
contract?: WarpContract<T> | RemoteContract<T>;
}
| {
contractTxId: string;
contractTxId?: string;
};

export type EvaluationOptions = {
Expand All @@ -63,13 +68,15 @@ export type EvaluationParameters<T = NonNullable<unknown>> = {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} & T;

export type WriteParameters<Input> = {
export type ReadParameters<Input> = {
functionName: string;
inputs: Input;
dryWrite?: boolean;
// TODO: add syncState and abortSignal options
inputs?: Input;
};

export type WriteParameters<Input> = WithSigner<
Required<ReadParameters<Input>>
>;

export interface BaseContract<T> {
getState(params: EvaluationParameters): Promise<T>;
}
Expand All @@ -79,10 +86,7 @@ export interface ReadContract {
functionName,
inputs,
evaluationOptions,
}: EvaluationParameters<{
functionName: string;
inputs?: Input;
}>): Promise<State>;
}: EvaluationParameters<ReadParameters<Input>>): Promise<State>;
}

export interface WriteContract {
Expand All @@ -95,15 +99,6 @@ export interface WriteContract {
>): Promise<WriteInteractionResult>;
}

export interface SmartWeaveContract<T> {
getContractState(params: EvaluationParameters): Promise<T>;
readInteraction<I, K>({
functionName,
inputs,
evaluationOptions,
}: EvaluationParameters<{ functionName: string; inputs?: I }>): Promise<K>;
}

// TODO: extend with additional methods
export interface ArIOReadContract extends BaseContract<ArIOState> {
getGateway({
Expand Down Expand Up @@ -139,9 +134,9 @@ export interface ArIOReadContract extends BaseContract<ArIOState> {
getEpoch({
blockHeight,
evaluationOptions,
}: {
}: EvaluationParameters<{
blockHeight: number;
} & EvaluationParameters): Promise<EpochDistributionData>;
}>): Promise<EpochDistributionData>;
getCurrentEpoch({
evaluationOptions,
}: EvaluationParameters): Promise<EpochDistributionData>;
Expand Down
72 changes: 44 additions & 28 deletions src/common/ant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
ContractSigner,
EvaluationOptions,
EvaluationParameters,
OptionalSigner,
WithSigner,
WriteInteractionResult,
} from '../types.js';
Expand All @@ -47,15 +48,18 @@ export class ANT {
* ANT.createContract({ contractTxId: 'myContractTxId' });
* ```
*/
static createContract(config: ContractConfiguration): WarpContract<ANTState> {
static createWriteableContract(
config: Required<ContractConfiguration<ANTState>>,
): WarpContract<ANTState> {
if (isContractConfiguration<ANTState>(config)) {
if (config.contract instanceof WarpContract) {
return config.contract;
}
return config.contract instanceof WarpContract
? config.contract
: new WarpContract<ANTState>(config.contract.configuration());
} else if (isContractTxIdConfiguration(config)) {
return new WarpContract<ANTState>({ contractTxId: config.contractTxId });
} else {
throw new InvalidContractConfigurationError();
}
throw new InvalidContractConfigurationError();
}

/**
Expand All @@ -82,23 +86,20 @@ export class ANT {
* const readable = ANT.init({ contract: myContract });
* ```
*/
static init(
config: ContractConfiguration &
WithSigner &
({ contract: WarpContract<ANTState> } | { contractTxId: string }),
): ANTWritable;
static init(
config?: ContractConfiguration &
({ contract?: RemoteContract<ANTState> } | { contractTxId: string }),
): ANTReadable;
static init(
config: ContractConfiguration & {
signer?: ContractSigner;
} = {},
) {
if (config?.signer) {
const signer = config.signer;
const contract = this.createContract(config);
static init(config: Required<ContractConfiguration<ANTState>>): ANTReadable;
static init({
signer,
...config
}: WithSigner<
// must be a WarpContract to get a ArIOWriteable
{ contract: WarpContract<ANTState> } | { contractTxId: string }
>): ANTWritable;
static init({
signer,
...config
}: OptionalSigner<Required<ContractConfiguration<ANTState>>>) {
if (signer) {
const contract = this.createWriteableContract(config);
return new ANTWritable({ signer, contract });
} else {
return new ANTReadable(config);
Expand All @@ -109,13 +110,15 @@ export class ANT {
export class ANTReadable implements ANTReadContract {
protected contract: RemoteContract<ANTState> | WarpContract<ANTState>;

constructor(config: ContractConfiguration) {
constructor(config: Required<ContractConfiguration<ANTState>>) {
if (isContractConfiguration<ANTState>(config)) {
this.contract = config.contract;
} else if (isContractTxIdConfiguration(config)) {
this.contract = new RemoteContract<ANTState>({
contractTxId: config.contractTxId,
});
} else {
throw new InvalidContractConfigurationError();
}
}

Expand Down Expand Up @@ -325,7 +328,7 @@ export class ANTReadable implements ANTReadContract {
evaluationOptions,
}: EvaluationParameters<{ address: string }>): Promise<number> {
const balances = await this.getBalances({ evaluationOptions });
return balances[address];
return balances[address] || 0;
}
}

Expand All @@ -334,11 +337,24 @@ export class ANTWritable extends ANTReadable {
private signer: ContractSigner;

constructor({
contract,
signer,
}: { contract: WarpContract<ANTState> } & WithSigner) {
super({ contract });
this.signer = signer;
...config
}: WithSigner<
{ contract: WarpContract<ANTState> } | { contractTxId: string }
>) {
if (isContractConfiguration<ANTState>(config)) {
super({ contract: config.contract });
this.signer = signer;
} else if (isContractTxIdConfiguration(config)) {
super({
contract: new WarpContract<ANTState>({
contractTxId: config.contractTxId,
}),
});
this.signer = signer;
} else {
throw new InvalidContractConfigurationError();
}
}

/**
Expand Down
Loading

0 comments on commit 881c54b

Please sign in to comment.