Skip to content

Commit

Permalink
Merge pull request #259 from ar-io/PE-7107-records
Browse files Browse the repository at this point in the history
feat(PE-7107): update getRecords to return as flat array of objects
  • Loading branch information
atticusofsparta authored Nov 14, 2024
2 parents 7926567 + 4fc2192 commit 0fb3420
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 20 deletions.
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1597,36 +1597,43 @@ const records = await ant.getRecords();
<summary>Output</summary>

```json
{
"@": {
[
{
"name": "@",
"transactionId": "nOXJjj_vk0Dc1yCgdWD8kti_1iHruGzLQLNNBHVpN0Y",
"ttlSeconds": 3600
},
"cn": {
{
"name": "cn",
"transactionId": "_HquerT6pfGFXrVxRxQTkJ7PV5RciZCqvMjLtUY0C1k",
"ttlSeconds": 3300
},
"dapp": {
{
"name": "dapp",
"transactionId": "hxlxVgAG0K4o3fVD9T6Q4VBWpPmMZwMWgRh1kcuh3WU",
"ttlSeconds": 3600
},
"logo": {
{
"name": "logo",
"transactionId": "KKmRbIfrc7wiLcG0zvY1etlO0NBx1926dSCksxCIN3A",
"ttlSeconds": 3600
},
"og": {
{
"name": "og",
"transactionId": "YzD_Pm5VAfYpMD3zQCgMUcKKuleGhEH7axlrnrDCKBo",
"ttlSeconds": 3600
},
"og_dapp": {
{
"name": "og_dapp",
"transactionId": "5iR4wBu4KUV1pUz1YpYE1ARXSRHUT5G2ptMuoN2JDlI",
"ttlSeconds": 3600
},
"og_logo": {
{
"name": "og_logo",
"transactionId": "TB2wJyKrPnkAW79DAwlJYwpgdHKpijEJWQfcwX715Co",
"ttlSeconds": 3600
}
}
]
```

</details>
Expand Down
21 changes: 14 additions & 7 deletions src/common/ant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import { z } from 'zod';
import {
AntBalancesSchema,
AntControllersSchema,
AntEntriesSchema,
AntInfoSchema,
AntReadOptions,
AntRecordSchema,
AntRecordsSchema,
AntStateSchema,
AoANTInfo,
AoANTRead,
AoANTRecord,
AoANTRecordEntry,
AoANTState,
AoANTWrite,
} from '../types/ant.js';
Expand All @@ -40,7 +41,7 @@ import {
isProcessConfiguration,
isProcessIdConfiguration,
} from '../types/index.js';
import { createAoSigner } from '../utils/ao.js';
import { createAoSigner, parseAntRecords } from '../utils/ao.js';
import { parseSchemaResult } from '../utils/schema.js';
import { AOProcess, InvalidContractConfigurationError } from './index.js';

Expand Down Expand Up @@ -154,7 +155,7 @@ export class AoANTReadable implements AoANTRead {
}

/**
* @returns {Promise<Record<string, AoANTRecord>>} All the undernames managed by the ANT.
* @returns {Promise<AoANTRecordEntry[]>} All the undernames managed by the ANT.
* @example
* Get the current records
* ```ts
Expand All @@ -163,13 +164,19 @@ export class AoANTReadable implements AoANTRead {
*/
async getRecords(
{ strict }: AntReadOptions = { strict: this.strict },
): Promise<Record<string, AoANTRecord>> {
): Promise<AoANTRecordEntry[]> {
const tags = [{ name: 'Action', value: 'Records' }];
const records = await this.process.read<Record<string, AoANTRecord>>({
const records = await this.process.read<
AoANTRecordEntry[] | Record<string, AoANTRecord>
>({
tags,
});
if (strict) parseSchemaResult(AntRecordsSchema, records);
return records;

const result = parseAntRecords(records);

if (strict) parseSchemaResult(AntEntriesSchema, result);

return result;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ export const IO_TESTNET_PROCESS_ID =
export const ANT_REGISTRY_ID = 'i_le_yKKPVstLTDSmkHRqf-wYphMnwB9OhleiTgMkWc';
export const MIO_PER_IO = 1_000_000;
export const AOS_MODULE_ID = 'cbn0KKrBZH7hdNkNokuXLtGryrWM--PjSTBqIzw9Kkk';
export const ANT_LUA_ID = 'pOh2yupSaQCrLI_-ah8tVTiusUdVNTxxeWTQQHNdf30';
export const ANT_LUA_ID = 'AWO2a2lVfQnjPFThjE4Uuw4ZFAd9EsCHBEgDYkJA-kk'; // v8 id test - remove comment when updated with actual v8 id.
export const DEFAULT_SCHEDULER_ID =
'_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA';
8 changes: 7 additions & 1 deletion src/types/ant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,15 @@ export const AntRecordSchema = z.object({
transactionId: ArweaveTxIdSchema.describe('The Target ID of the undername'),
ttlSeconds: z.number(),
});
export const AntEntrySchema = z.intersection(
AntRecordSchema,
z.object({ name: z.string() }),
);
export type AoANTRecord = z.infer<typeof AntRecordSchema>;
export type AoANTRecordEntry = z.infer<typeof AntEntrySchema>;

export const AntRecordsSchema = z.record(z.string(), AntRecordSchema);
export const AntEntriesSchema = z.array(AntEntrySchema);
export const AntControllersSchema = z.array(
ArweaveTxIdSchema.describe('Controller address'),
);
Expand Down Expand Up @@ -180,7 +186,7 @@ export interface AoANTRead {
{ undername }: { undername: string },
opts?: AntReadOptions,
): Promise<AoANTRecord | undefined>;
getRecords(opts?: AntReadOptions): Promise<Record<string, AoANTRecord>>;
getRecords(opts?: AntReadOptions): Promise<AoANTRecordEntry[]>;
getOwner(opts?: AntReadOptions): Promise<WalletAddress>;
getControllers(): Promise<WalletAddress[]>;
getTicker(opts?: AntReadOptions): Promise<string>;
Expand Down
29 changes: 28 additions & 1 deletion src/utils/ao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
AOS_MODULE_ID,
DEFAULT_SCHEDULER_ID,
} from '../constants.js';
import { AoANTRecord } from '../types/ant.js';
import { AoANTRecord, AoANTRecordEntry } from '../types/ant.js';
import {
AoClient,
AoSigner,
Expand Down Expand Up @@ -253,3 +253,30 @@ export function createAoSigner(signer: ContractSigner): AoSigner {

return aoSigner;
}

/**
* @param records @type {AoANTRecordEntry[] | Record<string, AoANTRecord>} - the records returned by an ANT
* @returns @type {AoANTRecordEntry[]} - the alphabetically sorted records
*/
export function parseAntRecords(
records: AoANTRecordEntry[] | Record<string, AoANTRecord>,
): AoANTRecordEntry[] {
const result = Array.isArray(records)
? records // assumes if records is an array that its AoANTRecordEntry[]
: // backwards compatibility for when ANTs returned as Record<string, AoANTRecord>
Object.keys(records) // sort the keys since string indexed maps in lua do not retain order
.sort((a: string, b: string) => {
if (a == '@') return -1;
if (b == '@') return 1;
return a.localeCompare(b);
})
.reduce((acc: AoANTRecordEntry[], undername: string) => {
acc.push({
...records[undername],
name: undername,
});
return acc;
}, [] as AoANTRecordEntry[]);

return result;
}
26 changes: 25 additions & 1 deletion tests/e2e/esm/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -628,14 +628,34 @@ describe('e2e esm tests', async () => {
});

describe('ANT', async () => {
const processId = 'YcxE5IbqZYK72H64ELoysxiJ-0wb36deYPv55wgl8xo';
// ANT v8 source
const processId = 'oQ4GNTed8cnNw-H5olq606gCFd5MbGSV4NTmfpIW4FI';
const ant = ANT.init({
process: new AOProcess({
processId,
ao: aoClient,
}),
});

it('should be able to get info on old ant', async () => {
const pid = 'YcxE5IbqZYK72H64ELoysxiJ-0wb36deYPv55wgl8xo';
const oldAnt = ANT.init({
process: new AOProcess({
processId: pid,
ao: aoClient,
}),
});
const info = await oldAnt.getInfo();
assert(info, 'failed to get info on old ANT with id of: ' + pid);

const records = await oldAnt.getRecords();
assert(records, 'failed to get records');
it("should return records from old ANT alphabetized with '@' being first", () => {
assert.strictEqual(records[0].name, '@');
assert.strictEqual(records.at(-1).name, 'zed');
});
});

it('should be able to create ANTWriteable with valid signers', async () => {
for (const signer of signers) {
const nonStrictAnt = ANT.init({
Expand Down Expand Up @@ -667,6 +687,10 @@ describe('e2e esm tests', async () => {
it('should be able to get the ANT records', async () => {
const records = await ant.getRecords();
assert.ok(records);
it("should return ANT records alphabetized with '@' being first", async () => {
assert.strictEqual(records[0].name, '@');
assert.strictEqual(records.at(-1).name, 'zed');
});
});

it('should be able to get a @ record from the ANT', async () => {
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Arweave from 'arweave';
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';

import { AoANTRecord, AoANTRecordEntry } from '../../src/types/ant.js';
import { parseAntRecords } from '../../src/utils/ao.js';
import {
getCurrentBlockUnixTimestampMs,
pruneTags,
Expand Down Expand Up @@ -64,3 +66,32 @@ describe('getCurrentBlockUnixTimestamp', () => {
assert.ok(timestamp <= maxTimestamp);
});
});

describe('ANT', () => {
it('should parse and sort records from an ANT', () => {
const recordMap: Record<string, AoANTRecord> = {
zed: {
transactionId: ''.padEnd(43, '1'),
ttlSeconds: 3600,
},
['@']: { transactionId: ''.padEnd(43, '1'), ttlSeconds: 3600 },
};

const recordList: AoANTRecordEntry[] = [
{
transactionId: ''.padEnd(43, '1'),
ttlSeconds: 3600,
name: '@',
},
{
transactionId: ''.padEnd(43, '1'),
ttlSeconds: 3600,
name: 'zed',
},
];

assert.deepEqual(parseAntRecords(recordMap), recordList);
assert.strictEqual(parseAntRecords(recordMap)[0].name, '@');
assert.deepEqual(parseAntRecords(recordList), recordList);
});
});

0 comments on commit 0fb3420

Please sign in to comment.