Skip to content

Commit

Permalink
fix(tests): update tests to use younger contract, add evalParams config
Browse files Browse the repository at this point in the history
  • Loading branch information
Atticus committed Mar 5, 2024
1 parent f8ff552 commit 2d0859c
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 135 deletions.
22 changes: 11 additions & 11 deletions src/common/ar-io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ArIOContract, ArNSNameData, Gateway } from '../types/index.js';
import { ArIOContract, ArNSNameData, Gateway, ReadInteractionFilters } from '../types/index.js';

Check failure on line 17 in src/common/ar-io.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Replace `·ArIOContract,·ArNSNameData,·Gateway,·ReadInteractionFilters·` with `⏎··ArIOContract,⏎··ArNSNameData,⏎··Gateway,⏎··ReadInteractionFilters,⏎`
import { ArNSRemoteCache } from './index.js';

export type CacheConfiguration = {
Expand All @@ -36,22 +36,22 @@ export class ArIO implements ArIOContract {
}
// implement ArIOContract interface

async getArNSRecord({ domain }: { domain: string }): Promise<ArNSNameData> {
return this.cache.getArNSRecord({ domain });
async getArNSRecord(params: { domain: string } & ReadInteractionFilters): Promise<ArNSNameData> {

Check failure on line 39 in src/common/ar-io.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Replace `params:·{·domain:·string·}·&·ReadInteractionFilters` with `⏎····params:·{·domain:·string·}·&·ReadInteractionFilters,⏎··`
return this.cache.getArNSRecord(params);
}
async getArNSRecords(): Promise<Record<string, ArNSNameData>> {
return this.cache.getArNSRecords();
async getArNSRecords(params: ReadInteractionFilters): Promise<Record<string, ArNSNameData>> {

Check failure on line 42 in src/common/ar-io.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Replace `params:·ReadInteractionFilters` with `⏎····params:·ReadInteractionFilters,⏎··`
return this.cache.getArNSRecords(params);
}
async getBalance({ address }: { address: string }): Promise<number> {
return this.cache.getBalance({ address });
async getBalance(params: { address: string } & ReadInteractionFilters): Promise<number> {

Check failure on line 45 in src/common/ar-io.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Replace `params:·{·address:·string·}·&·ReadInteractionFilters` with `⏎····params:·{·address:·string·}·&·ReadInteractionFilters,⏎··`
return this.cache.getBalance(params);
}
async getBalances(): Promise<Record<string, number>> {
return this.cache.getBalances();
}
async getGateway({ address }: { address: string }): Promise<Gateway> {
return this.cache.getGateway({ address });
async getGateway(params: { address: string }): Promise<Gateway> {
return this.cache.getGateway(params);
}
async getGateways(): Promise<Record<string, Gateway>> {
return this.cache.getGateways();
async getGateways(params: ReadInteractionFilters): Promise<Record<string, Gateway>> {

Check failure on line 54 in src/common/ar-io.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Replace `params:·ReadInteractionFilters` with `⏎····params:·ReadInteractionFilters,⏎··`
return this.cache.getGateways(params);
}
}
59 changes: 42 additions & 17 deletions src/common/caches/arns-remote-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import {
ArIOContract,
ArNSNameData,
ArNSStateResponse,
EvalToParams,
Gateway,
HTTPClient,
ReadInteractionFilters,
} from '../../types/index.js';
import { isBlockHeight, isSortKey } from '../../utils/index.js';
import { NotFound } from '../error.js';
import { AxiosHTTPService } from '../http.js';
import { DefaultLogger } from '../logger.js';
Expand Down Expand Up @@ -52,7 +54,16 @@ export class ArNSRemoteCache implements ArIOContract {
logger,
});
}
sortKeyOrBlockHeightParams(historicalIndex: any): EvalToParams {

Check warning on line 57 in src/common/caches/arns-remote-cache.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Unexpected any. Specify a different type

Check failure on line 58 in src/common/caches/arns-remote-cache.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Delete `⏎`
if (isSortKey(historicalIndex?.sortKey)) {
return { sortKey: historicalIndex.sortKey }

Check failure on line 60 in src/common/caches/arns-remote-cache.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Insert `;`
} if (isBlockHeight(historicalIndex?.blockHeight)) {

Check failure on line 61 in src/common/caches/arns-remote-cache.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Insert `⏎···`
return { blockHeight: historicalIndex.blockHeight }

Check failure on line 62 in src/common/caches/arns-remote-cache.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Insert `;`
}
return {}

Check failure on line 64 in src/common/caches/arns-remote-cache.ts

View workflow job for this annotation

GitHub Actions / build (18.x, lint)

Replace `⏎` with `;`

}
private validateContractTxId(id: string) {
if (!ARWEAVE_TX_REGEX.test(id)) {
throw new Error(`Invalid contract tx id: ${id}`);
Expand All @@ -61,11 +72,11 @@ export class ArNSRemoteCache implements ArIOContract {

async getGateway({
address,
blockHeight,
sortKey,
evaluationParameters,
}: { address: string } & ReadInteractionFilters) {
this.logger.debug(`Fetching gateway ${address}`);
const gateway = await this.getGateways({ blockHeight, sortKey }).then(

const gateway = await this.getGateways({ evaluationParameters }).then(
(gateways) => {
if (gateways[address] === undefined) {
throw new NotFound(`Gateway not found: ${address}`);
Expand All @@ -76,27 +87,34 @@ export class ArNSRemoteCache implements ArIOContract {
return gateway;
}

async getGateways({ blockHeight, sortKey }: ReadInteractionFilters) {
async getGateways({
evaluationParameters
}: ReadInteractionFilters = {}) {
this.logger.debug(`Fetching gateways`);

const params = this.sortKeyOrBlockHeightParams(evaluationParameters?.evalTo)

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

async getBalance({
address,
blockHeight,
sortKey,
evaluationParameters
}: { address: string } & ReadInteractionFilters) {
this.logger.debug(`Fetching balance for ${address}`);

const params = this.sortKeyOrBlockHeightParams(evaluationParameters?.evalTo)

const { result } = await this.http
.get<ArNSStateResponse<'result', number>>({
endpoint: `/contract/${this.contractTxId.toString()}/state/balances/${address}`,
params: { blockHeight, sortKey: sortKey?.toString() },
params,
})
.catch((e) => {
if (e instanceof NotFound) {
Expand All @@ -107,42 +125,49 @@ export class ArNSRemoteCache implements ArIOContract {
return result;
}

async getBalances({ blockHeight, sortKey }: ReadInteractionFilters) {
async getBalances({ evaluationParameters }: ReadInteractionFilters = {}) {
this.logger.debug(`Fetching balances`);

const params = this.sortKeyOrBlockHeightParams(evaluationParameters?.evalTo)

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

async getArNSRecord({
domain,
blockHeight,
sortKey,
evaluationParameters
}: { domain: string } & ReadInteractionFilters): Promise<ArNSNameData> {
this.logger.debug(`Fetching record for ${domain}`);

const params = this.sortKeyOrBlockHeightParams(evaluationParameters?.evalTo)

const { result } = await this.http.get<
ArNSStateResponse<'result', ArNSNameData>
>({
endpoint: `/contract/${this.contractTxId.toString()}/state/records/${domain}`,
params: { blockHeight, sortKey: sortKey?.toString() },
params,
});
return result;
}

async getArNSRecords({
blockHeight,
sortKey,
}: ReadInteractionFilters): Promise<Record<string, ArNSNameData>> {
evaluationParameters
}: ReadInteractionFilters = {}): Promise<Record<string, ArNSNameData>> {
this.logger.debug(`Fetching all records`);

const params = this.sortKeyOrBlockHeightParams(evaluationParameters?.evalTo)

const { result } = await this.http.get<
ArNSStateResponse<'result', Record<string, ArNSNameData>>
>({
endpoint: `/contract/${this.contractTxId.toString()}/state/records`,
params: { blockHeight, sortKey: sortKey?.toString() },
params
});
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class AxiosHTTPService implements HTTPClient {
headers?: Record<string, string>;
params?: Record<string, unknown>;
}): Promise<T> {
this.logger.debug(`Get request to endpoint: ${endpoint}`);
this.logger.debug(`Get request to endpoint: ${endpoint} with params ${JSON.stringify(params,undefined, 2)}`);
const { status, statusText, data } = await this.axios.get<T>(endpoint, {
headers,
signal,
Expand Down
27 changes: 15 additions & 12 deletions src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,39 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { SmartWeaveSortKey } from '../utils/index.js';
import { ArNSNameData, Gateway } from './contract-state.js';

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

export type EvalToParams = { sortKey?: SortKey } | { blockHeight?: BlockHeight };

export type EvaluationParameters = {
evalTo?: EvalToParams;
}

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

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

Expand Down
6 changes: 6 additions & 0 deletions src/utils/arweave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ARWEAVE_TX_REGEX } from '../constants.js';
import { BlockHeight } from '../types/common.js';

export const validateArweaveId = (id: string): boolean => {
return ARWEAVE_TX_REGEX.test(id);
};

export function isBlockHeight ( height: string | number): height is BlockHeight {
return height !== undefined
}

6 changes: 6 additions & 0 deletions src/utils/smartweave/evaluation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { SORT_KEY_REGEX } from '../../constants.js';
import { SortKey } from '../../types/common.js';


export function isSortKey(sortKey: string): sortKey is SortKey {
return SmartWeaveSortKey.validate(sortKey)
}

export class SmartWeaveSortKey {
private _sortKey: string;
Expand Down
62 changes: 31 additions & 31 deletions tests/arns-remote-cache/balances.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ArNSRemoteCache } from '../../src/common/caches/arns-remote-cache.js';
import { ARNS_DEVNET_REGISTRY_TX } from '../../src/constants.js';
import { SmartWeaveSortKey } from '../../src/utils/index.js';

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

const remoteCacheProvider = new ArNSRemoteCache({
contractTxId: ARNS_DEVNET_REGISTRY_TX
});
// balance tests
it('should fetch a balance', async () => {
const balance = await remoteCacheProvider.getBalance({
Expand All @@ -18,59 +20,57 @@ describe('ArNSRemoteCache ~ BALANCES', () => {
});

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 address = 'ySqMsg7O0R-BcUw35R3nxJJKJyIdauLCQ4DUZqPCiYo';
const transferBlockHeight = 1364752;
const currentBalance = await remoteCacheProvider.getBalance({
address, evaluationParameters: {
evalTo: { blockHeight: transferBlockHeight }
}
});
const transferAmount = 20000;

const balance = await remoteCacheProvider.getBalance({
address,
blockHeight: transferBlockHeight,
evaluationParameters: { evalTo: { blockHeight: transferBlockHeight } },
});
expect(balance).toEqual(currentBalance);

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

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

it('should return balances at a given block height', async () => {
const address = '7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk';
const currentBalance = 2363250;
const transferAmount = 1000;
const transferBlockHeight = 1305612;
const address = 'ySqMsg7O0R-BcUw35R3nxJJKJyIdauLCQ4DUZqPCiYo';
const transferBlockHeight = 1364752;
const currentBalance = await remoteCacheProvider.getBalance({
address, evaluationParameters: {
evalTo: { blockHeight: transferBlockHeight }
}
});
const balances = await remoteCacheProvider.getBalances({
blockHeight: transferBlockHeight,
evaluationParameters: { evalTo: { 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 = new SmartWeaveSortKey(
'000001305612,0000000000000,6806919fa401ad27fd86db576ef578857bd22a11d6905324d643368069146d4e',
);
const balances = await remoteCacheProvider.getBalances({
sortKey: balanceSortKey,
evaluationParameters: { evalTo: { blockHeight: transferBlockHeight - 1 } },
});
expect(balances[address]).toEqual(2363250);
expect(previousBalances[address]).toEqual(undefined);
});
});
Loading

0 comments on commit 2d0859c

Please sign in to comment.