feat: [FEATURE] Safe Block Fetch #464
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "warp-contracts",
|
"name": "warp-contracts",
|
||||||
"version": "1.4.21",
|
"version": "1.4.22-beta.1",
|
||||||
"description": "An implementation of the SmartWeave smart contract protocol.",
|
"description": "An implementation of the SmartWeave smart contract protocol.",
|
||||||
"types": "./lib/types/index.d.ts",
|
"types": "./lib/types/index.d.ts",
|
||||||
"main": "./lib/cjs/index.js",
|
"main": "./lib/cjs/index.js",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { LoggerFactory } from '../../../logging/LoggerFactory';
|
|||||||
import { DeployPlugin } from 'warp-contracts-plugin-deploy';
|
import { DeployPlugin } from 'warp-contracts-plugin-deploy';
|
||||||
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
|
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
|
||||||
import { InteractionCompleteEvent } from '../../../core/modules/StateEvaluator';
|
import { InteractionCompleteEvent } from '../../../core/modules/StateEvaluator';
|
||||||
|
import { NetworkCommunicationError } from '../../../utils/utils';
|
||||||
|
|
||||||
describe('Testing the Profit Sharing Token', () => {
|
describe('Testing the Profit Sharing Token', () => {
|
||||||
let contractSrc: string;
|
let contractSrc: string;
|
||||||
@@ -117,7 +118,7 @@ describe('Testing the Profit Sharing Token', () => {
|
|||||||
expect(resultVM.target).toEqual('uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M');
|
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;
|
let handlerCalled = false;
|
||||||
const interactionResult = await pst.writeInteraction({
|
const interactionResult = await pst.writeInteraction({
|
||||||
function: 'dispatchEvent'
|
function: 'dispatchEvent'
|
||||||
@@ -208,4 +209,36 @@ describe('Testing the Profit Sharing Token', () => {
|
|||||||
expect((await pst.currentBalance(walletAddress)).balance).toEqual(startBalance - 100);
|
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 balances = state.balances;
|
||||||
const canEvolve = state.canEvolve;
|
const canEvolve = state.canEvolve;
|
||||||
const input = action.input;
|
const input = action.input;
|
||||||
@@ -37,6 +37,24 @@ export function handle(state, action) {
|
|||||||
return { state };
|
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') {
|
if (input.function === 'balance') {
|
||||||
const target = input.target;
|
const target = input.target;
|
||||||
const ticker = state.ticker;
|
const ticker = state.ticker;
|
||||||
|
|||||||
@@ -37,6 +37,24 @@ export async function handle(state, action) {
|
|||||||
return {state};
|
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') {
|
if (input.function === 'dispatchEvent') {
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { GQLNodeInterface, GQLTagInterface, VrfData } from './gqlResult';
|
|||||||
import { CacheKey, SortKeyCache } from '../cache/SortKeyCache';
|
import { CacheKey, SortKeyCache } from '../cache/SortKeyCache';
|
||||||
import { SortKeyCacheRangeOptions } from '../cache/SortKeyCacheRangeOptions';
|
import { SortKeyCacheRangeOptions } from '../cache/SortKeyCacheRangeOptions';
|
||||||
import { InteractionState } from '../contract/states/InteractionState';
|
import { InteractionState } from '../contract/states/InteractionState';
|
||||||
|
import { safeGet } from '../utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -47,6 +48,8 @@ export class SmartWeaveGlobal {
|
|||||||
owner: string;
|
owner: string;
|
||||||
};
|
};
|
||||||
unsafeClient: Arweave;
|
unsafeClient: Arweave;
|
||||||
|
baseArweaveUrl: string;
|
||||||
|
safeArweaveGet: (input: RequestInfo | URL, init?: RequestInit) => Promise<unknown>;
|
||||||
|
|
||||||
contracts: {
|
contracts: {
|
||||||
readContractState: (contractId: string) => Promise<any>;
|
readContractState: (contractId: string) => Promise<any>;
|
||||||
@@ -79,6 +82,10 @@ export class SmartWeaveGlobal {
|
|||||||
wallets: arweave.wallets,
|
wallets: arweave.wallets,
|
||||||
crypto: arweave.crypto
|
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;
|
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)}`);
|
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