Skip to content

Commit

Permalink
chore(tests): add tests for blockheight and sortkey, break tests into…
Browse files Browse the repository at this point in the history
… domain centric files
  • Loading branch information
atticusofsparta committed Feb 29, 2024
1 parent ecb279d commit 48bc897
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 73 deletions.
47 changes: 35 additions & 12 deletions src/common/caches/arns-remote-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
ArNSStateResponse,
Gateway,
HTTPClient,
ReadInteractionFilters,
} from '../../types/index.js';
import { NotFound } from '../error.js';
import { AxiosHTTPService } from '../http.js';
Expand Down Expand Up @@ -58,32 +59,44 @@ export class ArNSRemoteCache implements ArIOContract {
}
}

async getGateway({ address }: { address: string }) {
async getGateway({
address,
blockHeight,
sortKey,
}: { address: string } & ReadInteractionFilters) {
this.logger.debug(`Fetching gateway ${address}`);
const gateway = await this.getGateways().then((gateways) => {
if (gateways[address] === undefined) {
throw new NotFound(`Gateway not found: ${address}`);
}
return gateways[address];
});
const gateway = await this.getGateways({ blockHeight, sortKey }).then(
(gateways) => {
if (gateways[address] === undefined) {
throw new NotFound(`Gateway not found: ${address}`);
}
return gateways[address];
},
);
return gateway;
}

async getGateways() {
async getGateways({ blockHeight, sortKey }: ReadInteractionFilters = {}) {
this.logger.debug(`Fetching gateways`);
const { result } = await this.http.get<
ArNSStateResponse<'result', Record<string, Gateway>>
>({
endpoint: `/contract/${this.contractTxId.toString()}/read/gateways`,
params: { blockHeight, sortKey },
});
return result;
}

async getBalance({ address }: { address: string }) {
async getBalance({
address,
blockHeight,
sortKey,
}: { address: string } & ReadInteractionFilters) {
this.logger.debug(`Fetching balance for ${address}`);
const { result } = await this.http
.get<ArNSStateResponse<'result', number>>({
endpoint: `/contract/${this.contractTxId.toString()}/state/balances/${address}`,
params: { blockHeight, sortKey },
})
.catch((e) => {
if (e instanceof NotFound) {
Expand All @@ -94,32 +107,42 @@ export class ArNSRemoteCache implements ArIOContract {
return result;
}

async getBalances() {
async getBalances({ blockHeight, sortKey }: ReadInteractionFilters = {}) {
this.logger.debug(`Fetching balances`);
const { result } = await this.http.get<
ArNSStateResponse<'result', Record<string, number>>
>({
endpoint: `/contract/${this.contractTxId.toString()}/state/balances`,
params: { blockHeight, sortKey },
});
return result;
}

async getRecord({ domain }: { domain: string }): Promise<ArNSNameData> {
async getRecord({
domain,
blockHeight,
sortKey,
}: { domain: string } & ReadInteractionFilters): Promise<ArNSNameData> {
this.logger.debug(`Fetching record for ${domain}`);
const { result } = await this.http.get<
ArNSStateResponse<'result', ArNSNameData>
>({
endpoint: `/contract/${this.contractTxId.toString()}/state/records/${domain}`,
params: { blockHeight, sortKey },
});
return result;
}

async getRecords(): Promise<Record<string, ArNSNameData>> {
async getRecords({
blockHeight,
sortKey,
}: ReadInteractionFilters = {}): Promise<Record<string, ArNSNameData>> {
this.logger.debug(`Fetching all records`);
const { result } = await this.http.get<
ArNSStateResponse<'result', Record<string, ArNSNameData>>
>({
endpoint: `/contract/${this.contractTxId.toString()}/state/records`,
params: { blockHeight, sortKey },
});
return result;
}
Expand Down
3 changes: 3 additions & 0 deletions src/common/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,19 @@ export class AxiosHTTPService implements HTTPClient {
signal,
allowedStatuses = [200, 202],
headers,
params,
}: {
endpoint: string;
signal?: AbortSignal;
allowedStatuses?: number[];
headers?: Record<string, string>;
params?: Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
}): Promise<T> {
this.logger.debug(`Get request to endpoint: ${endpoint}`);
const { status, statusText, data } = await this.axios.get<T>(endpoint, {
headers,
signal,
params,
});

if (!allowedStatuses.includes(status)) {
Expand Down
4 changes: 4 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
*/

export const ARWEAVE_TX_REGEX = new RegExp('^[a-zA-Z0-9_-]{43}$');
// sortkey: padded blockheight to 12, JS timestamp, hash of transactionID + block hash. Timestamp only applicable to L2 and normally is all zeros.
export const SORT_KEY_REGEX = new RegExp(
'^[0-9]{12},[0-9]{13},[a-fA-F0-9]{64}$',
);
export const ARNS_TESTNET_REGISTRY_TX =
process.env.ARNS_REGISTRY_TX ?? 'bLAgYxAdX2Ry-nt6aH2ixgvJXbpsEYm28NgJgyqfs-U';

Expand Down
26 changes: 22 additions & 4 deletions src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,29 @@
*/
import { ArNSNameData, Gateway } from './contract-state.js';

export type EvaluationFilters = {
blockHeight?: number;
sortKey?: string; // should be tested against regex for validity
};

// TODO: extend type with other read filters (e.g max eval time)
export type ReadInteractionFilters = EvaluationFilters;

// TODO: extend with additional methods
export interface ArIOContract {
getGateway({ address }: { address: WalletAddress }): Promise<Gateway>;
getGateway(
props: { address: WalletAddress } & ReadInteractionFilters,
): Promise<Gateway>;
getGateways(): Promise<Record<WalletAddress, Gateway>>;
getBalance({ address }: { address: WalletAddress }): Promise<number>;
getBalances(): Promise<Record<WalletAddress, number>>;
getRecord({ domain }: { domain: string }): Promise<ArNSNameData>;
getBalance(
props: { address: WalletAddress } & ReadInteractionFilters,
): Promise<number>;
getBalances(
props: ReadInteractionFilters,
): Promise<Record<WalletAddress, number>>;
getRecord(
props: { domain: string } & ReadInteractionFilters,
): Promise<ArNSNameData>;
getRecords(): Promise<Record<string, ArNSNameData>>;
}

Expand All @@ -45,11 +61,13 @@ export interface HTTPClient {
signal,
headers,
allowedStatuses,
params,
}: {
endpoint: string;
signal?: AbortSignal;
headers?: Record<string, string>;
allowedStatuses?: number[];
params?: Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
}): Promise<T>;
// TODO: add post method
// post<T>({
Expand Down
57 changes: 0 additions & 57 deletions tests/arns-remote-cache.test.ts

This file was deleted.

73 changes: 73 additions & 0 deletions tests/arns-remote-cache/balances.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ArNSRemoteCache } from '../../src/common/caches/arns-remote-cache.js';

describe('ArNSRemoteCache ~ BALANCES', () => {
const remoteCacheProvider = new ArNSRemoteCache({});

// balance tests
it('should fetch a balance', async () => {
const balance = await remoteCacheProvider.getBalance({
address: 'some-address',
});
expect(balance).toEqual(0);
});

it('should fetch all balances', async () => {
const balances = await remoteCacheProvider.getBalances();
expect(balances).toBeDefined();
});

it('should return balance at a given block height', async () => {
const address = '7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk';
const currentBalance = 2_363_250;
const transferAmount = 1000;
const transferBlockHeight = 1305612;
const balance = await remoteCacheProvider.getBalance({
address,
blockHeight: transferBlockHeight,
});
expect(balance).toEqual(currentBalance);

const previousBalance = await remoteCacheProvider.getBalance({
address,
blockHeight: transferBlockHeight - 1,
});
expect(previousBalance).toEqual(currentBalance + transferAmount);
});

it('should return balance at a given sort key', async () => {
const address = '7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk';
const balanceSortKey =
'000001305612,0000000000000,6806919fa401ad27fd86db576ef578857bd22a11d6905324d643368069146d4e';
const balance = await remoteCacheProvider.getBalance({
address,
sortKey: balanceSortKey,
});
expect(balance).toEqual(2363250);
});

it('should return balances at a given block height', async () => {
const address = '7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk';
const currentBalance = 2363250;
const transferAmount = 1000;
const transferBlockHeight = 1305612;
const balances = await remoteCacheProvider.getBalances({
blockHeight: transferBlockHeight,
});
expect(balances[address]).toEqual(currentBalance);

const previousBalances = await remoteCacheProvider.getBalances({
blockHeight: transferBlockHeight - 1,
});
expect(previousBalances[address]).toEqual(currentBalance + transferAmount);
});

it('should return balances at a given sort key', async () => {
const address = '7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk';
const balanceSortKey =
'000001305612,0000000000000,6806919fa401ad27fd86db576ef578857bd22a11d6905324d643368069146d4e';
const balances = await remoteCacheProvider.getBalances({
sortKey: balanceSortKey,
});
expect(balances[address]).toEqual(2363250);
});
});
68 changes: 68 additions & 0 deletions tests/arns-remote-cache/gateways.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ArNSRemoteCache } from '../../src/common/caches/arns-remote-cache.js';
import { NotFound } from '../../src/common/error.js';

describe('ArNSRemoteCache ~ GATEWAYS', () => {
const remoteCacheProvider = new ArNSRemoteCache({});

// gateway tests
it('should be able to fetch gateways', async () => {
const gateways = await remoteCacheProvider.getGateways();
expect(gateways).toBeDefined();
});

it('should should throw NotFound error on non existent gateway', async () => {
const error = await remoteCacheProvider
.getGateway({
address: 'some-address',
})
.catch((e) => e);
expect(error).toBeInstanceOf(NotFound);
});

it('should return gateway state at a given block height', async () => {
const blockHeight = 1372179;
const address = 'usOg4jFzqinXK_ExoU5NijjEyggNA255998LNiM8Vtc';
const gateway = await remoteCacheProvider.getGateway({
address,
blockHeight,
});
expect(gateway).toBeDefined();

const previousGatewayState = await remoteCacheProvider
.getGateway({
address,
blockHeight: blockHeight - 1,
})
.catch((e) => e);
expect(previousGatewayState).toBeInstanceOf(NotFound);
});

it('should return gateway state at a given sort key', async () => {
const sortKey =
'000001372179,0000000000000,1babf113056ce4d158c06f17ac8a1d0bff603dd6218dad98381d8e6d295f50a5';
const address = 'usOg4jFzqinXK_ExoU5NijjEyggNA255998LNiM8Vtc';
const gateway = await remoteCacheProvider.getGateway({
address,
sortKey,
});
expect(gateway).toBeDefined();
});

it('should return gateways state at a given block height', async () => {
const blockHeight = 1372179;
const address = 'usOg4jFzqinXK_ExoU5NijjEyggNA255998LNiM8Vtc';
const gateways = await remoteCacheProvider.getGateways({
blockHeight,
});
expect(gateways[address]).toBeDefined();
});

it('should return gateways state at a given sort key', async () => {
const address = 'usOg4jFzqinXK_ExoU5NijjEyggNA255998LNiM8Vtc';
const gateways = await remoteCacheProvider.getGateways({
sortKey:
'000001372179,0000000000000,1babf113056ce4d158c06f17ac8a1d0bff603dd6218dad98381d8e6d295f50a5',
});
expect(gateways[address]).toBeDefined();
});
});
Loading

0 comments on commit 48bc897

Please sign in to comment.