Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 134 additions & 160 deletions deno.lock

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions e2e/client/node/scripts/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ const yaci_enabled = Deno.env.get("DISABLE_LINUX_YACI") === "true"
? false
: true;

const midnight_enabled = Deno ? (Deno.env.get("DISABLE_MIDNIGHT") === "true"
? false
: true) : true;
const midnight_enabled = Deno
? (Deno.env.get("DISABLE_MIDNIGHT") === "true" ? false : true)
: true;

const avail_enabled = Deno
? (Deno.env.get("DISABLE_AVAIL") === "true" ? false : true)
: true;

const config = Value.Parse(OrchestratorConfig, {
processes: {
Expand All @@ -33,9 +37,8 @@ const config = Value.Parse(OrchestratorConfig, {
processesToLaunch: [
launchEvm("@e2e/evm-contracts"),
yaci_enabled ? launchCardano("@e2e/cardano-contracts") : {},
avail_enabled ? launchAvail("@e2e/avail-contracts") : {},
midnight_enabled ? launchMidnight("@e2e/midnight-contracts") : {},
// Uncomment to enable Avail Process
// launchAvail("@e2e/avail-contracts"),
{
stopProcessAtPort: [10590],
processes: [
Expand Down
20 changes: 17 additions & 3 deletions e2e/client/node/src/state-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ stm.addStateTransition("attack", function* (data) {
// Example 1:
// How to write in the DB.
yield* World.resolve(insertStateMachineInput, {
inputs: `attack playerId: ${data.parsedInput.playerId} with moveId: ${data.parsedInput.moveId}`,
inputs:
`attack playerId: ${data.parsedInput.playerId} with moveId: ${data.parsedInput.moveId}`,
block_height: data.blockHeight,
});

Expand Down Expand Up @@ -99,7 +100,7 @@ stm.addStateTransition("midnightContractState", function* (data) {
console.log(
"📚 Contract state is array with",
payload.content.length,
"items"
"items",
);
break;

Expand All @@ -114,6 +115,19 @@ stm.addStateTransition("midnightContractState", function* (data) {
return;
});

stm.addStateTransition(
"avail-app-state",
function* (data) {
const { payload } = data.parsedInput;
const parsedPayload = JSON.parse(payload.suppliedValue);
console.log(
"📦 Avail App state has message:",
parsedPayload.message || parsedPayload,
);
return;
},
);

stm.addStateTransition("throw_error", function* (data) {
throw new Error("This is a test error");
});
Expand Down Expand Up @@ -167,7 +181,7 @@ stm.addStateTransition("transfer", function* (data) {
*/
export const gameStateTransitions: StartConfigGameStateTransitions = function* (
blockHeight: number,
input: BaseStfInput
input: BaseStfInput,
): SyncStateUpdateStream<void> {
if (blockHeight >= 0) {
yield* stm.processInput(input);
Expand Down
3 changes: 2 additions & 1 deletion e2e/shared/contracts/avail/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
avail_path
avail_path
avail_app.json
2 changes: 1 addition & 1 deletion e2e/shared/contracts/avail/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ http_server_port=7007
port=37000

# WebSocket endpoint of a full node.
full_node_ws = ["ws://127.0.0.1:9944"]
full_node_ws = ["ws://127.0.0.1:9955"]

# Application ID. If not set or set to 0, application client is not started.
app_id=0
Expand Down
17 changes: 12 additions & 5 deletions e2e/shared/contracts/avail/deno.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
{
"name": "@e2e/avail-contracts",
"version": "0.3.0",
"exports": {},
"exports": {
".": "./read-app.ts"
},
"tasks": {
"avail-node:start": "deno run -A --unstable-detect-cjs @paima/npm-avail-node --dev",
"avail-node:wait": "wait-on tcp:9944",
"avail-light-client:start": "deno run -A --unstable-detect-cjs @paima/npm-avail-light-client --network local --config ./config.yml",
"avail-node:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry",
"avail-node:wait": "wait-on tcp:9955",
"avail-light-client:deploy": "deno run -A --unstable-detect-cjs ./deploy.ts",
"avail-light-client:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-light-client --config ./config.yml --app-id $AVAIL_APP_ID",
"avail-light-client:wait": "wait-on tcp:7007"
},
"imports": {}
"imports": {
"avail-js-sdk": "npm:avail-js-sdk@^0.4.2",
"@paimaexample/npm-avail-node": "npm:@paimaexample/npm-avail-node@0.3.30",
"@paimaexample/npm-avail-light-client": "npm:@paimaexample/npm-avail-light-client@0.3.30"
}
}
66 changes: 66 additions & 0 deletions e2e/shared/contracts/avail/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Account, Pallets, SDK } from "avail-js-sdk";

const sdk = await SDK.New("ws://localhost:9955/ws");
const seed: string = Deno.env.get("SEED") ?? "//Alice";
if (!seed) {
throw new Error("SEED environment variable is not set");
}
const account = Account.new(seed);
const genesisHash = await sdk.client.api.rpc.chain.getBlockHash(0);
console.log("Account Address: ", account.address);
// Use a fixed key string
const ApplicationKey = "app_key_" + Date.now();

export async function createApplicationKey() {
// Create application key transaction
const tx = sdk.tx.dataAvailability.createApplicationKey(ApplicationKey);
console.log("Submitting transaction to create application key...");

// Execute and wait for inclusion
const res = await tx.executeWaitForInclusion(account, {});

// Check if transaction was successful
const isOk = res.isSuccessful();
if (isOk === undefined) {
throw new Error("Cannot check if transaction was successful");
} else if (!isOk) {
console.log("Transaction failed", res);
throw new Error("Transaction failed");
}

// Extract event data
if (res.events === undefined) throw new Error("No events found");

const event = res.events.findFirst(
Pallets.DataAvailabilityEvents.ApplicationKeyCreated,
);
if (event === undefined) {
throw new Error("ApplicationKeyCreated event not found");
}

const appId = event.id;
console.log(`Application created successfully:`);
console.log(`Owner: ${event.owner}`);
console.log(`Key: ${event.keyToString()}`);
console.log(`App Id: ${appId}`);
console.log(`Transaction Hash: ${res.txHash}`);
return { appId, txHash: res.txHash };
}

const { appId, txHash } = await createApplicationKey();
console.log("Transaction Hash: ", txHash.toString());
const data = JSON.stringify({ appId, txHash, ApplicationKey, genesisHash });
const fileName = Deno.cwd() + "/avail_app.json";
console.log("Writing to file: ", fileName);
await Deno.writeTextFile(fileName, data);

const child = new Deno.Command("deno", {
args: ["task", "-f", "@e2e/avail-contracts", "avail-light-client:start"],
env: {
AVAIL_APP_ID: appId.toString(),
},
}).spawn();

console.log("Light Client Started");

await child.status;
28 changes: 28 additions & 0 deletions e2e/shared/contracts/avail/read-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export type AvailApplicationInfo = {
appId: number;
txHash: { // The txHash of the apps creation transaction
value: string;
};
ApplicationKey: string;
genesisHash: string;
};

let cachedAppInfo: AvailApplicationInfo | undefined;
export function readAvailApplication(): AvailApplicationInfo {
if (cachedAppInfo) return cachedAppInfo;
try {
// Get the directory of the current module file using Deno's URL API
const dir = new URL(".", import.meta.url);
// Construct the full path to avail_app.json
const appInfoPath = new URL("avail_app.json", dir);
const appInfoJson = Deno.readTextFileSync(appInfoPath);
const appInfo = JSON.parse(appInfoJson) as AvailApplicationInfo;
cachedAppInfo = appInfo;
return appInfo;
} catch (err) {
if (err instanceof Deno.errors.NotFound) {
throw new Error("avail_app.json not found in the current directory");
}
throw new Error(`Failed to read avail_app.json: ${String(err)}`);
}
}
48 changes: 47 additions & 1 deletion e2e/shared/data-types/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { readMidnightContract } from "@e2e/midnight-contracts";
import { contractAddressesEvmMain } from "@e2e/evm-contracts";

import { readAvailApplication } from "@e2e/avail-contracts";
import { getConnection } from "@paima/db";
import {
ConfigBuilder,
ConfigNetworkType,
Expand Down Expand Up @@ -31,6 +32,11 @@ const yaci_enabled = Deno
const midnight_enabled = Deno
? (Deno.env.get("DISABLE_MIDNIGHT") === "true" ? false : true)
: true;

// NOTE: This disable avail sync, allowing for faster testing.
const avail_enabled = Deno
? (Deno.env.get("DISABLE_AVAIL") === "true" ? false : true)
: true;
/**
* Let check if the db.
* If empty then the db is not initialized, and use the current time for the NTP sync.
Expand Down Expand Up @@ -92,6 +98,16 @@ export const localhostConfig = new ConfigBuilder()
},
id: 31338, // taken from hardhat.config.ts
});
if (avail_enabled) {
b = b.addNetwork({
name: "avail",
type: ConfigNetworkType.AVAIL,
genesisSeed: "//Alice",
nodeUrl: "ws://127.0.0.1:9955/ws",
genesisHash: readAvailApplication().genesisHash,
caip2: `avail:local`,
});
}
if (midnight_enabled) {
b = b
.addNetwork({
Expand Down Expand Up @@ -177,6 +193,22 @@ export const localhostConfig = new ConfigBuilder()
confirmationDepth: 2, // TODO: test this
}),
);

if (avail_enabled) {
result = result.addParallel(
(networks) => (networks as any).avail,
(network, deployments) => ({
name: "parallelAvail",
type: ConfigSyncProtocolType.AVAIL_PARALLEL,
rpc: network.nodeUrl,
lightClient: "http://127.0.0.1:7007",
startBlockHeight: 1,
pollingInterval: 20_000,
delayMs: 0,
}),
);
}

if (midnight_enabled) {
result = result
.addParallel(
Expand Down Expand Up @@ -286,6 +318,20 @@ export const localhostConfig = new ConfigBuilder()
}),
);

if (avail_enabled) {
builder = builder.addPrimitive(
(syncProtocols) => (syncProtocols as any).parallelAvail,
(network, deployments, syncProtocol) => ({
name: "AvailContractState",
type: ConfigPrimitiveType.AvailPaimaL2,
startBlockHeight: 1,
appId: readAvailApplication().appId,
contractAddress: readAvailApplication().ApplicationKey,
genesisHash: readAvailApplication().genesisHash,
scheduledPrefix: "avail-app-state",
}),
);
}
if (midnight_enabled) {
builder = builder
.addPrimitive(
Expand Down
12 changes: 11 additions & 1 deletion e2e/shared/data-types/src/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,20 @@ export const grammar = {
),
],
],
"avail-app-state": [
[
"payload",
Type.Object({
suppliedValue: Type.String(),
}),
],
],
// Auto-generate other primitives, but exclude midnight (we define it explicitly above)
...Object.fromEntries(
Object.entries(mapPrimitivesToGrammar(localhostConfig.primitives))
.filter(([key]) => key !== "midnightContractState"),
.filter(([key]) =>
key !== "midnightContractState" && key !== "avail-app-state"
),
),
} as const satisfies GrammarDefinition;

Expand Down
48 changes: 22 additions & 26 deletions packages/binaries/avail-light-client/config.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
# Default configuration for avail-light-client
# For a full list of options, see the official Avail documentation.
# Avail Light Client config (no --network needed)

log_level="info"
http_server_host="127.0.0.1"
http_server_port=7007
# Logging
log_level = "info"

# Secret key for libp2p keypair. Can be either set to 'seed' or to 'key'.
# If set to seed, keypair will be generated from that seed.
# If 'secret_key' is not set, a random seed will be used.
# secret_key={ seed: "avail" }
# API server
http_server_host = "127.0.0.1"
http_server_port = 7007

# P2P TCP listener port (default: 37000).
port=37000

# WebSocket endpoint of a full node.
# RPC to full node (custom 9955)
full_node_ws = ["ws://127.0.0.1:9944"]

# Application ID. If not set or set to 0, application client is not started.
app_id=0

# Confidence threshold (default: 92.0).
confidence=92.0

# File system path where RocksDB used by the light client stores its data.
# This path is relative to the location of this config file.
avail_path="avail_path"

# Vector of Light Client bootstrap nodes.
# This is for a local setup. Replace with public bootstraps for testnet/mainnet.
bootstraps=["/ip4/127.0.0.1/tcp/39000/p2p/12D3KooWMm1c4pzeLPGkkCJMAgFbsfQ8xmVDusg272icWsaNHWzN"]
# App / LC behavior
app_id = 0
confidence = 92.0
avail_path = "avail_path"
network_mode = "both" # both | p2p-only | rpc-only

# LibP2P
port = 37000
webrtc_port = 37001
# secret_key = { seed = "avail" } # optional deterministic key
bootstraps = ["/ip4/127.0.0.1/tcp/39000/p2p/12D3KooWMm1c4pzeLPGkkCJMAgFbsfQ8xmVDusg272icWsaNHWzN"]

# Telemetry / network identity (equivalent to local --network defaults)
ot_collector_endpoint = "http://127.0.0.1:4317"
genesis_hash = "DEV"
Loading