Skip to content

Commit

Permalink
feat: fetch options plugin (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
asiaziola authored Dec 29, 2022
1 parent 92306e2 commit 277e692
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 18 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,25 @@ An example - LMDB - implementation is available [here](https://github.com/warp-c
A dedicated CLI which eases the process of using main methods of the Warp SDK library has been created. Please refer to [`warp-contracts-cli` npm page](https://www.npmjs.com/package/warp-contracts-cli) for more details.
### Customize `fetch` options
It is possible to customize `fetch` options using dedicated plugin. In order to change `fetch` options one needs to create an implementation of [WarpPlugin](https://github.com/warp-contracts/warp/blob/main/src/core/WarpPlugin.ts) interface. `process` method will receive following properties:
```ts
interface FetchRequest {
input: RequestInfo | URL;
init: Partial<RequestInit>;
}
```
...and it should return updated `fetch` options (by returning updated `init` object). An example of such implementation in [src/tools/fetch-options-plugin.ts](https://github.com/warp-contracts/warp/tree/main/tools/fetch-options-plugin.ts).
In order to use this plugin, it needs to be attached while creating `Warp` instance, e.g.:
```ts
const warp = WarpFactory.forMainnet().use(new FetchOptionsPlugin());
```
### Migrations
#### old factories to WarpFactory
Expand Down
35 changes: 20 additions & 15 deletions src/contract/HandlerBasedContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { generateMockVrf } from '../utils/vrf';
import { Signature, SignatureType } from './Signature';
import { ContractDefinition } from '../core/ContractDefinition';
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
import { WarpFetchWrapper } from '../core/WarpFetchWrapper';

/**
* An implementation of {@link Contract} that is backwards compatible with current style
Expand All @@ -59,6 +60,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
private _sorter: InteractionsSorter;
private _rootSortKey: string;
private signature: Signature;
private warpFetchWrapper: WarpFetchWrapper;

constructor(
private readonly _contractTxId: string,
Expand Down Expand Up @@ -113,6 +115,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
}

this.getCallStack = this.getCallStack.bind(this);
this.warpFetchWrapper = new WarpFetchWrapper(this.warp);
}

async readState(
Expand Down Expand Up @@ -301,15 +304,16 @@ export class HandlerBasedContract<State> implements Contract<State> {
options.vrf
);

const response = await fetch(`${this._evaluationOptions.sequencerUrl}gateway/sequencer/register`, {
method: 'POST',
body: JSON.stringify(interactionTx),
headers: {
'Accept-Encoding': 'gzip, deflate, br',
'Content-Type': 'application/json',
Accept: 'application/json'
}
})
const response = await this.warpFetchWrapper
.fetch(`${this._evaluationOptions.sequencerUrl}gateway/sequencer/register`, {
method: 'POST',
body: JSON.stringify(interactionTx),
headers: {
'Accept-Encoding': 'gzip, deflate, br',
'Content-Type': 'application/json',
Accept: 'application/json'
}
})
.then((res) => {
this.logger.debug(res);
return res.ok ? res.json() : Promise.reject(res);
Expand Down Expand Up @@ -746,12 +750,13 @@ export class HandlerBasedContract<State> implements Contract<State> {

async syncState(externalUrl: string, params?: any): Promise<Contract> {
const { stateEvaluator } = this.warp;
const response = await fetch(
`${externalUrl}?${new URLSearchParams({
id: this._contractTxId,
...params
})}`
)
const response = await this.warpFetchWrapper
.fetch(
`${externalUrl}?${new URLSearchParams({
id: this._contractTxId,
...params
})}`
)
.then((res) => {
return res.ok ? res.json() : Promise.reject(res);
})
Expand Down
15 changes: 13 additions & 2 deletions src/contract/deploy/impl/DefaultCreateContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@
import Arweave from 'arweave';
import Transaction from 'arweave/node/lib/transaction';
import { Signature, SignatureType } from '../../../contract/Signature';
import { WarpFetchWrapper } from '../../../core/WarpFetchWrapper';
import { SmartWeaveTags } from '../../../core/SmartWeaveTags';
import { Warp } from '../../../core/Warp';
import { WARP_GW_URL } from '../../../core/WarpFactory';
import { LoggerFactory } from '../../../logging/LoggerFactory';
import { CreateContract, ContractData, ContractDeploy, FromSrcTxContractData, ArWallet, BundlrNodeType, BUNDLR_NODES } from '../CreateContract';
import {
CreateContract,
ContractData,
ContractDeploy,
FromSrcTxContractData,
ArWallet,
BundlrNodeType,
BUNDLR_NODES
} from '../CreateContract';
import { SourceData, SourceImpl } from './SourceImpl';
import { Buffer } from 'redstone-isomorphic';

Expand All @@ -15,10 +24,12 @@ export class DefaultCreateContract implements CreateContract {
private readonly source: SourceImpl;

private signature: Signature;
private readonly warpFetchWrapper: WarpFetchWrapper;

constructor(private readonly arweave: Arweave, private warp: Warp) {
this.deployFromSourceTx = this.deployFromSourceTx.bind(this);
this.source = new SourceImpl(this.warp);
this.warpFetchWrapper = new WarpFetchWrapper(this.warp);
}

async deploy(contractData: ContractData, disableBundling?: boolean): Promise<ContractDeploy> {
Expand Down Expand Up @@ -190,7 +201,7 @@ export class DefaultCreateContract implements CreateContract {
};
}

const response = await fetch(`${WARP_GW_URL}/gateway/contracts/deploy`, {
const response = await this.warpFetchWrapper.fetch(`${WARP_GW_URL}/gateway/contracts/deploy`, {
method: 'POST',
body: JSON.stringify(body),
headers: {
Expand Down
37 changes: 37 additions & 0 deletions src/core/WarpFetchWrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { LoggerFactory } from '../logging/LoggerFactory';
import { Warp } from './Warp';

export interface FetchRequest {
input: RequestInfo | URL;
init: Partial<RequestInit>;
}

export class WarpFetchWrapper {
private readonly name = 'WarpFetchWrapper';
private readonly logger = LoggerFactory.INST.create(this.name);

constructor(private warp: Warp) {
this.warp = warp;
}

fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
let fetchOptions: RequestInit;

if (this.warp.hasPlugin('fetch-options')) {
const fetchOptionsPlugin = this.warp.loadPlugin<FetchRequest, Partial<RequestInit>>('fetch-options');
try {
const updatedFetchOptions = fetchOptionsPlugin.process({ input, init: init || {} });
fetchOptions = { ...init, ...updatedFetchOptions };
} catch (e) {
if (e.message) {
this.logger.error(e.message);
}
throw new Error(`Unable to process fetch options: ${e.message}`);
}
} else {
fetchOptions = init;
}

return fetch(input, fetchOptions);
}
}
3 changes: 2 additions & 1 deletion src/core/WarpPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export const knownWarpPlugins = [
'smartweave-extension-ethers',
'subscription',
'ivm-handler-api',
'evaluation-progress'
'evaluation-progress',
'fetch-options'
] as const;
export type WarpPluginType = typeof knownWarpPlugins[number];

Expand Down
70 changes: 70 additions & 0 deletions tools/fetch-options-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { WarpPlugin, WarpPluginType } from '../src/core/WarpPlugin';
import { FetchRequest } from '../src/core/WarpFetchWrapper';
import { JWKInterface } from 'arweave/node/lib/wallet';
import fs from 'fs';
import path from 'path';
import { LoggerFactory } from '../src/logging/LoggerFactory';
import { defaultCacheOptions, WarpFactory } from '../src/core/WarpFactory';

class FetchOptionsPlugin implements WarpPlugin<FetchRequest, RequestInit> {
process(request: FetchRequest): Partial<RequestInit> {
const url = request.input;

let fetchOptions: Partial<RequestInit> = {};

if (url == `https://d1o5nlqr4okus2.cloudfront.net/gateway/sequencer/register`) {
fetchOptions = {
keepalive: true
};
}

return fetchOptions;
}

type(): WarpPluginType {
return 'fetch-options';
}
}

async function main() {
const wallet: JWKInterface = readJSON('./.secrets/jwk.json');
LoggerFactory.INST.logLevel('debug');
const logger = LoggerFactory.INST.create('FetchOptionsPlugin');

try {
const warp = WarpFactory.forMainnet({ ...defaultCacheOptions, inMemory: true }).use(new FetchOptionsPlugin());

const jsContractSrc = fs.readFileSync(path.join(__dirname, 'data/js/token-pst.js'), 'utf8');
const initialState = fs.readFileSync(path.join(__dirname, 'data/js/token-pst.json'), 'utf8');

const { contractTxId } = await warp.createContract.deploy({
wallet,
initState: initialState,
src: jsContractSrc
});

const contract = warp.contract(contractTxId).connect(wallet);

await contract.writeInteraction({
function: 'transfer',
target: 'uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M',
qty: 55555
});

const { cachedValue } = await contract.readState();
logger.info(`Cached value: ${cachedValue}`);
} catch (e) {
logger.error(e);
}
}

export function readJSON(path: string): JWKInterface {
const content = fs.readFileSync(path, 'utf-8');
try {
return JSON.parse(content);
} catch (e) {
throw new Error(`File "${path}" does not contain a valid JSON`);
}
}

main().catch((e) => console.error(e));

0 comments on commit 277e692

Please sign in to comment.