feat: [FEATURE] Safe Block Fetch #464
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "warp-contracts",
|
||||
"version": "1.4.21",
|
||||
"version": "1.4.22-beta.1",
|
||||
"description": "An implementation of the SmartWeave smart contract protocol.",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
"main": "./lib/cjs/index.js",
|
||||
|
||||
@@ -13,6 +13,7 @@ import { LoggerFactory } from '../../../logging/LoggerFactory';
|
||||
import { DeployPlugin } from 'warp-contracts-plugin-deploy';
|
||||
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
|
||||
import { InteractionCompleteEvent } from '../../../core/modules/StateEvaluator';
|
||||
import { NetworkCommunicationError } from '../../../utils/utils';
|
||||
|
||||
describe('Testing the Profit Sharing Token', () => {
|
||||
let contractSrc: string;
|
||||
@@ -117,7 +118,7 @@ describe('Testing the Profit Sharing Token', () => {
|
||||
expect(resultVM.target).toEqual('uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M');
|
||||
});
|
||||
|
||||
it('should properly dispatch en event', async () => {
|
||||
it('should properly dispatch an event', async () => {
|
||||
let handlerCalled = false;
|
||||
const interactionResult = await pst.writeInteraction({
|
||||
function: 'dispatchEvent'
|
||||
@@ -208,4 +209,36 @@ describe('Testing the Profit Sharing Token', () => {
|
||||
expect((await pst.currentBalance(walletAddress)).balance).toEqual(startBalance - 100);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when loading data from Arweave", () => {
|
||||
it('should allow to safe fetch from external api', async () => {
|
||||
const blockData = await arweave.blocks.getCurrent();
|
||||
|
||||
await pst.writeInteraction({
|
||||
function: 'loadBlockData',
|
||||
height: blockData.height
|
||||
});
|
||||
|
||||
await mineBlock(warp);
|
||||
|
||||
const result = await pst.readState();
|
||||
|
||||
expect((result.cachedValue.state as any).blocks['' + blockData.height]).toEqual(blockData.indep_hash);
|
||||
});
|
||||
|
||||
// note: this has to be the last test.
|
||||
it('should stop evaluation on safe fetch error', async () => {
|
||||
const blockData = await arweave.blocks.getCurrent();
|
||||
|
||||
await pst.writeInteraction({
|
||||
function: 'loadBlockData',
|
||||
height: blockData.height,
|
||||
throwError: true
|
||||
});
|
||||
|
||||
await mineBlock(warp);
|
||||
|
||||
await expect(pst.readState()).rejects.toThrowError(NetworkCommunicationError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function handle(state, action) {
|
||||
export async function handle(state, action) {
|
||||
const balances = state.balances;
|
||||
const canEvolve = state.canEvolve;
|
||||
const input = action.input;
|
||||
@@ -37,6 +37,24 @@ export function handle(state, action) {
|
||||
return { state };
|
||||
}
|
||||
|
||||
if (input.function === 'loadBlockData') {
|
||||
const height = input.height;
|
||||
const throwError = input.throwError;
|
||||
|
||||
const blockData = await SmartWeave.safeArweaveGet(
|
||||
throwError
|
||||
? `/blockkkk/height/${height}`
|
||||
: `/block/height/${height}`
|
||||
);
|
||||
|
||||
if (!state.blocks) {
|
||||
state.blocks = {};
|
||||
}
|
||||
|
||||
state.blocks["" + height] = blockData.indep_hash;
|
||||
return { state };
|
||||
}
|
||||
|
||||
if (input.function === 'balance') {
|
||||
const target = input.target;
|
||||
const ticker = state.ticker;
|
||||
|
||||
@@ -37,6 +37,24 @@ export async function handle(state, action) {
|
||||
return {state};
|
||||
}
|
||||
|
||||
if (input.function === 'loadBlockData') {
|
||||
const height = input.height;
|
||||
const throwError = input.throwError;
|
||||
|
||||
const blockData = await SmartWeave.safeArweaveGet(
|
||||
throwError
|
||||
? `/blockkkk/height/${height}`
|
||||
: `/block/height/${height}`
|
||||
);
|
||||
|
||||
if (!state.blocks) {
|
||||
state.blocks = {};
|
||||
}
|
||||
|
||||
state.blocks["" + height] = blockData.indep_hash;
|
||||
return { state };
|
||||
}
|
||||
|
||||
if (input.function === 'dispatchEvent') {
|
||||
return {
|
||||
state,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { GQLNodeInterface, GQLTagInterface, VrfData } from './gqlResult';
|
||||
import { CacheKey, SortKeyCache } from '../cache/SortKeyCache';
|
||||
import { SortKeyCacheRangeOptions } from '../cache/SortKeyCacheRangeOptions';
|
||||
import { InteractionState } from '../contract/states/InteractionState';
|
||||
import { safeGet } from '../utils/utils';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -47,6 +48,8 @@ export class SmartWeaveGlobal {
|
||||
owner: string;
|
||||
};
|
||||
unsafeClient: Arweave;
|
||||
baseArweaveUrl: string;
|
||||
safeArweaveGet: (input: RequestInfo | URL, init?: RequestInit) => Promise<unknown>;
|
||||
|
||||
contracts: {
|
||||
readContractState: (contractId: string) => Promise<any>;
|
||||
@@ -79,6 +82,10 @@ export class SmartWeaveGlobal {
|
||||
wallets: arweave.wallets,
|
||||
crypto: arweave.crypto
|
||||
};
|
||||
this.baseArweaveUrl = `${arweave.api.config.protocol}://${arweave.api.config.host}:${arweave.api.config.port}`;
|
||||
this.safeArweaveGet = async function(query: string) {
|
||||
return safeGet(`${this.baseArweaveUrl}${query}`);
|
||||
};
|
||||
|
||||
this.evaluationOptions = evaluationOptions;
|
||||
|
||||
|
||||
@@ -115,3 +115,7 @@ export async function getJsonResponse<T>(response: Promise<Response>): Promise<T
|
||||
throw new NetworkCommunicationError(`Error while parsing json response: ${JSON.stringify(e)}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function safeGet<T>(input: RequestInfo | URL, init?: RequestInit): Promise<T> {
|
||||
return getJsonResponse(fetch(input, init));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user