feat: bundlr, sequencer
This commit is contained in:
committed by
Piotr Pędziwiatr
parent
fcfa93aae3
commit
a5740a0d1d
@@ -132,6 +132,23 @@ export interface Contract<State = unknown> {
|
||||
strict?: boolean
|
||||
): Promise<string | null>;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new "interaction" transaction using RedStone Sequencer - this, with combination with
|
||||
* RedStone Gateway, gives instant transaction availability and finality guaranteed by Bundlr.
|
||||
*
|
||||
* @param input - new input to the contract that will be assigned with this interactions transaction
|
||||
* @param tags - additional tags that can be attached to the newly created interaction transaction
|
||||
* @param transfer - additional {@link ArTransfer} than can be attached to the interaction transaction
|
||||
* @param strict - transaction will be posted on Arweave only if the dry-run of the input result is "ok"
|
||||
*/
|
||||
bundleInteraction<Input = unknown>(
|
||||
input: Input,
|
||||
tags?: Tags,
|
||||
transfer?: ArTransfer,
|
||||
strict?: boolean
|
||||
): Promise<string | null>;
|
||||
|
||||
/**
|
||||
* Returns the full call tree report the last
|
||||
* interaction with contract (eg. after reading state)
|
||||
|
||||
@@ -188,6 +188,60 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
}
|
||||
const { arweave } = this.smartweave;
|
||||
|
||||
const interactionTx = await this.createInteraction(input, tags, transfer, strict);
|
||||
const response = await arweave.transactions.post(interactionTx);
|
||||
|
||||
if (response.status !== 200) {
|
||||
this.logger.error('Error while posting transaction', response);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._evaluationOptions.waitForConfirmation) {
|
||||
this.logger.info('Waiting for confirmation of', interactionTx.id);
|
||||
const benchmark = Benchmark.measure();
|
||||
await this.waitForConfirmation(interactionTx.id);
|
||||
this.logger.info('Transaction confirmed after', benchmark.elapsed());
|
||||
}
|
||||
return interactionTx.id;
|
||||
}
|
||||
|
||||
async bundleInteraction<Input>(
|
||||
input: Input,
|
||||
tags: Tags = [],
|
||||
transfer: ArTransfer = emptyTransfer,
|
||||
strict = false
|
||||
): Promise<any | null> {
|
||||
this.logger.info('Bundle interaction input', input);
|
||||
if (!this.wallet) {
|
||||
throw new Error("Wallet not connected. Use 'connect' method first.");
|
||||
}
|
||||
const interactionTx = await this.createInteraction(input, tags, transfer, strict);
|
||||
|
||||
const response = await fetch(`${this._evaluationOptions.sequencerAddress}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);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.logger.error(error);
|
||||
if (error.body?.message) {
|
||||
this.logger.error(error.body.message);
|
||||
}
|
||||
throw new Error(`Unable to bundle interaction: ${JSON.stringify(error)}`);
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async createInteraction<Input>(input: Input, tags: { name: string; value: string }[], transfer: ArTransfer, strict: boolean) {
|
||||
if (this._evaluationOptions.internalWrites) {
|
||||
// Call contract and verify if there are any internal writes:
|
||||
// 1. Evaluate current contract state
|
||||
@@ -230,21 +284,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
transfer.target,
|
||||
transfer.winstonQty
|
||||
);
|
||||
|
||||
const response = await arweave.transactions.post(interactionTx);
|
||||
|
||||
if (response.status !== 200) {
|
||||
this.logger.error('Error while posting transaction', response);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._evaluationOptions.waitForConfirmation) {
|
||||
this.logger.info('Waiting for confirmation of', interactionTx.id);
|
||||
const benchmark = Benchmark.measure();
|
||||
await this.waitForConfirmation(interactionTx.id);
|
||||
this.logger.info('Transaction confirmed after', benchmark.elapsed());
|
||||
}
|
||||
return interactionTx.id;
|
||||
return interactionTx;
|
||||
}
|
||||
|
||||
txId(): string {
|
||||
|
||||
@@ -92,6 +92,8 @@ export class DefaultEvaluationOptions implements EvaluationOptions {
|
||||
stackTrace = {
|
||||
saveState: false
|
||||
};
|
||||
|
||||
sequencerAddress = "https://gateway.redstone.finance/";
|
||||
}
|
||||
|
||||
// an interface for the contract EvaluationOptions - can be used to change the behaviour of some of the features.
|
||||
@@ -133,4 +135,6 @@ export interface EvaluationOptions {
|
||||
// whether output state should be saved for each interaction in the stack trace (may result in huuuuge json files!)
|
||||
saveState: boolean;
|
||||
};
|
||||
|
||||
sequencerAddress: string;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
|
||||
|
||||
const interactionTx: GQLNodeInterface = missingInteraction.node;
|
||||
|
||||
this.logger.debug(
|
||||
this.logger.error(
|
||||
`[${contractDefinition.txId}][${missingInteraction.node.id}][${missingInteraction.node.block.height}]: ${
|
||||
missingInteractions.indexOf(missingInteraction) + 1
|
||||
}/${missingInteractions.length} [of all:${sortedInteractions.length}]`
|
||||
|
||||
@@ -18,6 +18,11 @@ export class LexicographicalInteractionsSorter implements InteractionsSorter {
|
||||
private async addSortKey(txInfo: GQLEdgeInterface) {
|
||||
const { node } = txInfo;
|
||||
|
||||
// might have been already set by the RedStone Sequencer
|
||||
if (txInfo.sortKey !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
txInfo.sortKey = await this.createSortKey(node.block.id, node.id, node.block.height);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,17 +10,23 @@ import {
|
||||
import * as fs from 'fs';
|
||||
import knex from 'knex';
|
||||
import os from "os";
|
||||
import {readJSON} from "../../redstone-smartweave-examples/src/_utils";
|
||||
import {TsLogFactory} from '../src/logging/node/TsLogFactory';
|
||||
|
||||
const logger = LoggerFactory.INST.create('Contract');
|
||||
|
||||
LoggerFactory.use(new TsLogFactory());
|
||||
LoggerFactory.INST.logLevel('fatal');
|
||||
LoggerFactory.INST.logLevel('info', 'Contract');
|
||||
LoggerFactory.INST.logLevel('debug', 'RedstoneGatewayInteractionsLoader');
|
||||
LoggerFactory.INST.logLevel('error', 'DefaultStateEvaluator');
|
||||
|
||||
async function main() {
|
||||
printTestInfo();
|
||||
|
||||
|
||||
const PIANITY_CONTRACT = 'SJ3l7474UHh3Dw6dWVT1bzsJ-8JvOewtGoDdOecWIZo';
|
||||
const PIANITY_COMMUNITY_CONTRACT = 'n05LTiuWcAYjizXAu-ghegaWjL89anZ6VdvuHcU6dno';
|
||||
const LOOT_CONTRACT = 'Daj-MNSnH55TDfxqC7v4eq0lKzVIwh98srUaWqyuZtY';
|
||||
const CACHE_PATH = 'cache.sqlite.db';
|
||||
|
||||
const heapUsedBefore = Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100;
|
||||
@@ -51,18 +57,28 @@ async function main() {
|
||||
)
|
||||
)
|
||||
.setInteractionsLoader(
|
||||
new RedstoneGatewayInteractionsLoader('https://gateway.redstone.finance', { notCorrupted: true })
|
||||
new RedstoneGatewayInteractionsLoader('https://gateway.redstone.finance', {notCorrupted: true})
|
||||
)
|
||||
.setDefinitionLoader(
|
||||
new RedstoneGatewayContractDefinitionLoader('https://gateway.redstone.finance', arweave, new MemCache())
|
||||
)
|
||||
.build();
|
||||
|
||||
const contract = smartweave.contract(PIANITY_CONTRACT);
|
||||
await contract.readState();
|
||||
const jwk = readJSON("../redstone-node/.secrets/redstone-jwk.json");
|
||||
const contract = smartweave.contract(LOOT_CONTRACT)
|
||||
/*.setEvaluationOptions({
|
||||
sequencerAddress: "http://localhost:5666/"
|
||||
})*/
|
||||
.connect(jwk);
|
||||
const bundledInteraction = await contract.bundleInteraction({
|
||||
function: "generate"
|
||||
});
|
||||
|
||||
const contract2 = smartweave.contract(PIANITY_COMMUNITY_CONTRACT);
|
||||
await contract2.readState();
|
||||
logger.info("Bundled interaction", bundledInteraction);
|
||||
|
||||
// bundlr balance I-5rWUehEv-MjdK9gFw09RxfSLQX9DIHxG614Wf8qo0 -h https://node1.bundlr.network/ -c arweave
|
||||
|
||||
//await contract.readState();
|
||||
|
||||
const heapUsedAfter = Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100;
|
||||
const rssUsedAfter = Math.round((process.memoryUsage().rss / 1024 / 1024) * 100) / 100;
|
||||
@@ -79,6 +95,7 @@ async function main() {
|
||||
const result = contract.lastReadStateStats();
|
||||
|
||||
logger.warn('total evaluation: ', result);
|
||||
return;
|
||||
}
|
||||
|
||||
function printTestInfo() {
|
||||
|
||||
Reference in New Issue
Block a user