Skip to content

Commit

Permalink
feat(ao): experiment with initial implementation of ao contract
Browse files Browse the repository at this point in the history
  • Loading branch information
dtfiedler committed May 29, 2024
1 parent e62558d commit 6118cea
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 49 deletions.
74 changes: 39 additions & 35 deletions examples/esm/index.mjs
Original file line number Diff line number Diff line change
@@ -1,39 +1,43 @@
import { ARNS_TESTNET_REGISTRY_TX, ArIO } from '@ar.io/sdk';
import { ArIO } from '@ar.io/sdk';

(async () => {
const arIO = ArIO.init({
contractTxId: ARNS_TESTNET_REGISTRY_TX,
// const arIO = ArIO.init({
// contractTxId: ARNS_TESTNET_REGISTRY_TX,
// });
// // testnet gateways
// const testnetGateways = await arIO.getGateways();
// const protocolBalance = await arIO.getBalance({
// address: ARNS_TESTNET_REGISTRY_TX,
// });
// const ardriveRecord = await arIO.getArNSRecord({ domain: 'ardrive' });
// const allRecords = await arIO.getArNSRecords();
// const oldEpoch = await arIO.getEpoch({
// blockHeight: 1382230,
// });
// const epoch = await arIO.getCurrentEpoch();
// const observations = await arIO.getObservations();
// const observation = await arIO.getObservations({ epochStartHeight: 1350700 });
// const distributions = await arIO.getDistributions();
// console.dir(
// {
// testnetGateways,
// ardriveRecord,
// protocolBalance,
// arnsStats: {
// 'registered domains': Object.keys(allRecords).length,
// ardrive: allRecords.ardrive,
// },
// oldEpoch,
// epoch,
// observations,
// observation,
// distributions,
// },
// { depth: 2 },
// );
const process = ArIO.init({
processId: 'GaQrvEMKBpkjofgnBi_B3IgIDmY_XYelVLB6GcRGrHc',
});
// testnet gateways
const testnetGateways = await arIO.getGateways();
const protocolBalance = await arIO.getBalance({
address: ARNS_TESTNET_REGISTRY_TX,
});
const ardriveRecord = await arIO.getArNSRecord({ domain: 'ardrive' });
const allRecords = await arIO.getArNSRecords();
const oldEpoch = await arIO.getEpoch({
blockHeight: 1382230,
});
const epoch = await arIO.getCurrentEpoch();
const observations = await arIO.getObservations();
const observation = await arIO.getObservations({ epochStartHeight: 1350700 });
const distributions = await arIO.getDistributions();

console.dir(
{
testnetGateways,
ardriveRecord,
protocolBalance,
arnsStats: {
'registered domains': Object.keys(allRecords).length,
ardrive: allRecords.ardrive,
},
oldEpoch,
epoch,
observations,
observation,
distributions,
},
{ depth: 2 },
);
const state = await process.getState();
console.log({ state });
})();
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
"warp-contracts-plugin-deploy": "^1.0.13"
},
"dependencies": {
"@permaweb/aoconnect": "^0.0.55",
"arbundles": "0.11.0",
"arweave": "1.14.4",
"axios": "1.4.0",
Expand Down
18 changes: 15 additions & 3 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { ArconnectSigner, ArweaveSigner } from 'arbundles';
import { DataItem } from 'warp-arbundles';
import { Transaction } from 'warp-contracts';

import { RemoteContract, WarpContract } from './common/index.js';
import { AOProcess, RemoteContract, WarpContract } from './common/index.js';
import {
ANTRecord,
ANTState,
Expand Down Expand Up @@ -59,6 +59,13 @@ export type ContractConfiguration<T = NonNullable<unknown>> =
| {
contractTxId?: string;
};
export type ProcessConfiguration<T = NonNullable<unknown>> =
| {
process: AOProcess<T>;
}
| {
processId: string;
};

export type EvaluationOptions = {
evalTo?: { sortKey: SortKey } | { blockHeight: BlockHeight };
Expand All @@ -71,12 +78,13 @@ export type EvaluationParameters<T = NonNullable<unknown>> = {
} & T;

export type ReadParameters<Input> = {
functionName: string;
functionName?: string;
inputs?: Input;
tags?: Array<{ name: string; value: string }>;
};

export type WriteParameters<Input> = WithSigner<
Required<ReadParameters<Input>>
Required<Omit<ReadParameters<Input>, 'tags'>>
>;

export interface BaseContract<T> {
Expand All @@ -91,6 +99,10 @@ export interface ReadContract {
}: EvaluationParameters<ReadParameters<Input>>): Promise<State>;
}

export interface AOContract {
read<K>({ tags }): Promise<K>;
}

export interface WriteContract {
writeInteraction<Input>({
functionName,
Expand Down
83 changes: 78 additions & 5 deletions src/common/ar-io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { ARNS_TESTNET_REGISTRY_TX } from '../constants.js';
import {
AR_IO_CONTRACT_FUNCTIONS,
AoIOState,
ArIOReadContract,
ArIOState,
ArIOWriteContract,
Expand All @@ -34,6 +35,7 @@ import {
JoinNetworkParams,
Observations,
OptionalSigner,
ProcessConfiguration,
RegistrationType,
TransactionId,
UpdateGatewaySettingsParams,
Expand All @@ -46,9 +48,15 @@ import {
import {
isContractConfiguration,
isContractTxIdConfiguration,
isProcessConfiguration,
isProcessIdConfiguration,
} from '../utils/smartweave.js';
import { RemoteContract } from './contracts/remote-contract.js';
import { InvalidContractConfigurationError, WarpContract } from './index.js';
import {
AOProcess,
InvalidContractConfigurationError,
WarpContract,
} from './index.js';

export class ArIO {
/**
Expand Down Expand Up @@ -147,8 +155,11 @@ export class ArIO {

export class ArIOReadable implements ArIOReadContract {
protected contract: RemoteContract<ArIOState> | WarpContract<ArIOState>;
protected process: AOProcess<AoIOState>;

constructor(config?: ContractConfiguration<ArIOState>) {
constructor(
config?: ContractConfiguration<ArIOState> | ProcessConfiguration<AoIOState>,
) {
if (!config) {
this.contract = new RemoteContract<ArIOState>({
contractTxId: ARNS_TESTNET_REGISTRY_TX,
Expand All @@ -159,6 +170,12 @@ export class ArIOReadable implements ArIOReadContract {
this.contract = new RemoteContract<ArIOState>({
contractTxId: config.contractTxId,
});
} else if (isProcessConfiguration<AoIOState>(config)) {
this.process = config.process;
} else if (isProcessIdConfiguration(config)) {
this.process = new AOProcess<AoIOState>({
processId: config.processId,
});
} else {
throw new InvalidContractConfigurationError();
}
Expand All @@ -178,10 +195,16 @@ export class ArIOReadable implements ArIOReadContract {
* arIO.getState({ evaluationOptions: { evalTo: { sortKey: 'mySortKey' } } });
* ```
*/
async getState(params: EvaluationParameters = {}): Promise<ArIOState> {
async getState<T = ArIOState | AoIOState>(
params: EvaluationParameters = {},
): Promise<T> {
if (this.process instanceof AOProcess) {
return this.process.getState() as T;
}
const state = await this.contract.getState(params);
return state;
return state as T;
}

/**
* @param domain @type {string} The domain name.
* @param evaluationOptions @type {EvaluationOptions} The evaluation options.
Expand All @@ -203,6 +226,12 @@ export class ArIOReadable implements ArIOReadContract {
}: EvaluationParameters<{ domain: string }>): Promise<
ArNSNameData | undefined
> {
// handle ao by sending tags
if (this.process instanceof AOProcess) {
return this.process.read<ArNSNameData>({
tags: [{ name: 'Action', value: 'Record' }],
});
}
const records = await this.getArNSRecords({ evaluationOptions });
return records[domain];
}
Expand All @@ -224,6 +253,11 @@ export class ArIOReadable implements ArIOReadContract {
async getArNSRecords({
evaluationOptions,
}: EvaluationParameters = {}): Promise<Record<string, ArNSNameData>> {
if (this.process instanceof AOProcess) {
return this.process.read<Record<string, ArNSNameData>>({
tags: [{ name: 'Action', value: 'Records' }],
});
}
const state = await this.contract.getState({ evaluationOptions });
return state.records;
}
Expand All @@ -247,6 +281,11 @@ export class ArIOReadable implements ArIOReadContract {
}: EvaluationParameters): Promise<
Record<string, ArNSReservedNameData> | Record<string, never>
> {
if (this.process instanceof AOProcess) {
return this.process.read<Record<string, ArNSReservedNameData>>({
tags: [{ name: 'Action', value: 'ReservedNames' }],
});
}
const state = await this.contract.getState({ evaluationOptions });
return state.reserved;
}
Expand All @@ -272,6 +311,14 @@ export class ArIOReadable implements ArIOReadContract {
}: EvaluationParameters<{ domain: string }>): Promise<
ArNSReservedNameData | undefined
> {
if (this.process instanceof AOProcess) {
return this.process.read<Record<string, ArNSReservedNameData>>({
tags: [
{ name: 'Action', value: 'ReservedName' },
{ name: 'Name', value: domain },
],
});
}
const reservedNames = await this.getArNSReservedNames({
evaluationOptions,
});
Expand All @@ -298,6 +345,14 @@ export class ArIOReadable implements ArIOReadContract {
address,
evaluationOptions,
}: EvaluationParameters<{ address: string }>): Promise<number> {
if (this.process instanceof AOProcess) {
return this.process.read<number>({
tags: [
{ name: 'Action', value: 'Balance' },
{ name: 'Address', value: address },
],
});
}
const balances = await this.getBalances({ evaluationOptions });
return balances[address] || 0;
}
Expand All @@ -320,6 +375,11 @@ export class ArIOReadable implements ArIOReadContract {
async getBalances({ evaluationOptions }: EvaluationParameters = {}): Promise<
Record<string, number>
> {
if (this.process instanceof AOProcess) {
return this.process.read<Record<WalletAddress, number>>({
tags: [{ name: 'Action', value: 'Balances' }],
});
}
const state = await this.contract.getState({ evaluationOptions });
return state.balances;
}
Expand All @@ -344,6 +404,14 @@ export class ArIOReadable implements ArIOReadContract {
address,
evaluationOptions,
}: EvaluationParameters<{ address: string }>): Promise<Gateway | undefined> {
if (this.process instanceof AOProcess) {
return this.process.read<Gateway | undefined>({
tags: [
{ name: 'Action', value: 'Gateway' },
{ name: 'Address', value: address },
],
});
}
return this.contract
.readInteraction<{ target: string }, Gateway>({
functionName: AR_IO_CONTRACT_FUNCTIONS.GATEWAY,
Expand Down Expand Up @@ -373,8 +441,13 @@ export class ArIOReadable implements ArIOReadContract {
* ```
*/
async getGateways({ evaluationOptions }: EvaluationParameters = {}): Promise<
Record<string, Gateway> | Record<string, never>
Record<WalletAddress, Gateway> | Record<string, never>
> {
if (this.process instanceof AOProcess) {
return this.process.read<Record<WalletAddress, Gateway>>({
tags: [{ name: 'Action', value: 'Gateways' }],
});
}
return this.contract.readInteraction({
functionName: AR_IO_CONTRACT_FUNCTIONS.GATEWAYS,
evaluationOptions,
Expand Down
Loading

0 comments on commit 6118cea

Please sign in to comment.