Skip to content

Commit

Permalink
v1.5.0-rc.0
Browse files Browse the repository at this point in the history
  • Loading branch information
szynwelski committed Dec 11, 2023
1 parent a4342a6 commit 5da88ff
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 171 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "warp-contracts",
"version": "1.4.25",
"version": "1.5.0-rc.0",
"description": "An implementation of the SmartWeave smart contract protocol.",
"types": "./lib/types/index.d.ts",
"main": "./lib/cjs/index.js",
Expand Down
298 changes: 152 additions & 146 deletions src/__tests__/integration/decentralized-sequencer/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,171 +14,177 @@ import { WARP_TAGS } from '../../../core/KnownTags';
import { LoggerFactory } from '../../../logging/LoggerFactory';

interface ExampleContractState {
counter: number;
counter: number;
}

const DECENTRALIZED_SEQUENCER_URLS = ['http://sequencer-0.testnet.warp.cc:1317',
'http://sequencer-1.testnet.warp.cc:1317',
'http://sequencer-2.testnet.warp.cc:1317'];
const DECENTRALIZED_SEQUENCER_URLS = [
'http://sequencer-0.testnet.warp.cc:1317',
'http://sequencer-1.testnet.warp.cc:1317',
'http://sequencer-2.testnet.warp.cc:1317'
];
const GW_URL = 'http://35.242.203.146:5666/';

describe('Testing sending of interactions to a decentralized sequencer', () => {
let contractSrc: string;
let initialState: string;
let wallet: JWKInterface;
let arlocal: ArLocal;
let warp: Warp;
let contract: Contract<ExampleContractState>;
let mockGwServer: Server;
let mockGwUrl: string;
let centralizedSequencerType: boolean;
let confirmAnyTx: boolean;

/**
* For testing purposes, operations returning the sequencer's address and registering/confirming interactions are mocked.
* Other requests are forwarded to the real Gateway.
*/
const mockGw = async () => {
mockGwServer = createServer((req, res) => {
if (req.url === '/gateway/sequencer/address') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
urls: centralizedSequencerType ? [mockGwUrl] : DECENTRALIZED_SEQUENCER_URLS,
type: centralizedSequencerType ? 'centralized' : 'decentralized'
}));
return;
} else if (req.url === '/gateway/v2/sequencer/register') {
centralizedSequencerType = false;
res.writeHead(301, { Location: DECENTRALIZED_SEQUENCER_URLS[0] });
res.end();
return;
} else if (req.url?.startsWith('/gateway/interactions/')) {
res.writeHead(confirmAnyTx ? 200 : 204);
res.end();
return;
}

var options = {
hostname: new URL(GW_URL).hostname,
port: new URL(GW_URL).port,
path: req.url,
method: req.method,
headers: req.headers
};

var proxy = request(options, (gwRes) => {
if (gwRes.statusCode) {
res.writeHead(gwRes.statusCode, gwRes.headers)
gwRes.pipe(res, {
end: true
});
}
});

req.pipe(proxy, {
end: true
});
});
await new Promise<void>(resolve => {
mockGwServer.listen(() => {
const address = mockGwServer.address() as AddressInfo
mockGwUrl = `http://localhost:${address.port}`
resolve()
})
});
}

beforeAll(async () => {
LoggerFactory.INST.logLevel('debug');
const port = 1813;
arlocal = new ArLocal(port, false);
await arlocal.start();

const arweave = Arweave.init({
host: 'localhost',
port: port,
protocol: 'http'
});

let contractSrc: string;
let initialState: string;
let wallet: JWKInterface;
let arlocal: ArLocal;
let warp: Warp;
let contract: Contract<ExampleContractState>;
let mockGwServer: Server;
let mockGwUrl: string;
let centralizedSequencerType: boolean;
let confirmAnyTx: boolean;

/**
* For testing purposes, operations returning the sequencer's address and registering/confirming interactions are mocked.
* Other requests are forwarded to the real Gateway.
*/
const mockGw = async () => {
mockGwServer = createServer((req, res) => {
if (req.url === '/gateway/sequencer/address') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(
JSON.stringify({
urls: centralizedSequencerType ? [mockGwUrl] : DECENTRALIZED_SEQUENCER_URLS,
type: centralizedSequencerType ? 'centralized' : 'decentralized'
})
);
return;
} else if (req.url === '/gateway/v2/sequencer/register') {
centralizedSequencerType = false;
confirmAnyTx = false;
await mockGw();

const cacheOptions = {
...defaultCacheOptions,
inMemory: true
res.writeHead(301, { Location: DECENTRALIZED_SEQUENCER_URLS[0] });
res.end();
return;
} else if (req.url?.startsWith('/gateway/interactions/')) {
res.writeHead(confirmAnyTx ? 200 : 204);
res.end();
return;
}

var options = {
hostname: new URL(GW_URL).hostname,
port: new URL(GW_URL).port,
path: req.url,
method: req.method,
headers: req.headers
};

var proxy = request(options, (gwRes) => {
if (gwRes.statusCode) {
res.writeHead(gwRes.statusCode, gwRes.headers);
gwRes.pipe(res, {
end: true
});
}
const gatewayOptions = { ...defaultWarpGwOptions, source: SourceType.WARP_SEQUENCER, confirmationStatus: { notCorrupted: true } }
});

warp = WarpFactory
.custom(arweave, cacheOptions, 'custom')
.useWarpGateway(gatewayOptions, cacheOptions)
.build()
.useGwUrl(mockGwUrl)
.use(new DeployPlugin());

({ jwk: wallet } = await warp.generateWallet());

contractSrc = fs.readFileSync(path.join(__dirname, '../data/example-contract.js'), 'utf8');
initialState = fs.readFileSync(path.join(__dirname, '../data/example-contract-state.json'), 'utf8');

const { contractTxId } = await warp.deploy({
wallet: new ArweaveSigner(wallet),
initState: initialState,
src: contractSrc
});
req.pipe(proxy, {
end: true
});
});
await new Promise<void>((resolve) => {
mockGwServer.listen(() => {
const address = mockGwServer.address() as AddressInfo;
mockGwUrl = `http://localhost:${address.port}`;
resolve();
});
});
};

beforeAll(async () => {
LoggerFactory.INST.logLevel('debug');
const port = 1813;
arlocal = new ArLocal(port, false);
await arlocal.start();

const arweave = Arweave.init({
host: 'localhost',
port: port,
protocol: 'http'
});

contract = warp.contract<ExampleContractState>(contractTxId).setEvaluationOptions({
sequencerUrl: mockGwUrl
});
contract.connect(wallet);
centralizedSequencerType = false;
confirmAnyTx = false;
await mockGw();

const cacheOptions = {
...defaultCacheOptions,
inMemory: true
};
const gatewayOptions = {
...defaultWarpGwOptions,
source: SourceType.WARP_SEQUENCER,
confirmationStatus: { notCorrupted: true }
};

warp = WarpFactory.custom(arweave, cacheOptions, 'custom')
.useWarpGateway(gatewayOptions, cacheOptions)
.build()
.useGwUrl(mockGwUrl)
.use(new DeployPlugin());

({ jwk: wallet } = await warp.generateWallet());

contractSrc = fs.readFileSync(path.join(__dirname, '../data/example-contract.js'), 'utf8');
initialState = fs.readFileSync(path.join(__dirname, '../data/example-contract-state.json'), 'utf8');

const { contractTxId } = await warp.deploy({
wallet: new ArweaveSigner(wallet),
initState: initialState,
src: contractSrc
});

contract = warp.contract<ExampleContractState>(contractTxId).setEvaluationOptions({
sequencerUrl: mockGwUrl
});
contract.connect(wallet);
});

afterAll(async () => {
await arlocal.stop();
await new Promise(resolve => {
mockGwServer.close(resolve)
})
afterAll(async () => {
await arlocal.stop();
await new Promise((resolve) => {
mockGwServer.close(resolve);
});
});

const getNonceFromResult = (result: WriteInteractionResponse | null): number => {
if (result) {
for (let tag of result.interactionTx.tags) {
if (tag.name === WARP_TAGS.SEQUENCER_NONCE) {
return Number(tag.value)
}
}
const getNonceFromResult = (result: WriteInteractionResponse | null): number => {
if (result) {
for (let tag of result.interactionTx.tags) {
if (tag.name === WARP_TAGS.SEQUENCER_NONCE) {
return Number(tag.value);
}
return -1
}
}

it('should follow the redirection returned by the centralized sequencer.', async () => {
confirmAnyTx = true;
centralizedSequencerType = true;
contract.setEvaluationOptions({
waitForConfirmation: true
});

await contract.writeInteraction({ function: 'add' });
const result = await contract.writeInteraction({ function: 'add' });
expect(getNonceFromResult(result)).toEqual(1)
return -1;
};

it('should follow the redirection returned by the centralized sequencer.', async () => {
confirmAnyTx = true;
centralizedSequencerType = true;
contract.setEvaluationOptions({
waitForConfirmation: true
});

it('should add new interactions waiting for confirmation from the gateway', async () => {
contract.setEvaluationOptions({ waitForConfirmation: true })
setTimeout(() => confirmAnyTx = true, 2000);
await contract.writeInteraction({ function: 'add' });
const result = await contract.writeInteraction({ function: 'add' });
expect(getNonceFromResult(result)).toEqual(1);
});

await contract.writeInteraction({ function: 'add' });
const result = await contract.writeInteraction({ function: 'add' });
expect(getNonceFromResult(result)).toEqual(3)
});
it('should add new interactions waiting for confirmation from the gateway', async () => {
contract.setEvaluationOptions({ waitForConfirmation: true });
setTimeout(() => (confirmAnyTx = true), 2000);

it('should add new interactions without waiting for confirmation from the gateway', async () => {
contract.setEvaluationOptions({ waitForConfirmation: false })
await contract.writeInteraction({ function: 'add' });
const result = await contract.writeInteraction({ function: 'add' });
expect(getNonceFromResult(result)).toEqual(3);
});

await contract.writeInteraction({ function: 'add' });
const result = await contract.writeInteraction({ function: 'add' });
expect(getNonceFromResult(result)).toEqual(5)
});
it('should add new interactions without waiting for confirmation from the gateway', async () => {
contract.setEvaluationOptions({ waitForConfirmation: false });

await contract.writeInteraction({ function: 'add' });
const result = await contract.writeInteraction({ function: 'add' });
expect(getNonceFromResult(result)).toEqual(5);
});
});
Loading

0 comments on commit 5da88ff

Please sign in to comment.