🧪 Skills

Alkahest Developer

Help developers write code that interacts with Alkahest escrow contracts using the TypeScript, Rust, or Python SDK

v1.0.0
❤️ 0
⬇️ 13
👁 4
Share

Description


name: alkahest-developer description: Help developers write code that interacts with Alkahest escrow contracts using the TypeScript, Rust, or Python SDK

Alkahest Developer Skill

When to Use

Use this skill when a developer wants to write code that interacts with Alkahest escrow contracts. This covers:

  • Integrating Alkahest into an application
  • Writing bots/agents that create escrows, fulfill obligations, or arbitrate
  • Building custom arbiters or obligation contracts
  • Understanding SDK patterns and APIs

SDK Overview

SDK Language Package Foundation
TypeScript TypeScript/JavaScript @alkahest/ts-sdk viem
Rust Rust alkahest-rs alloy
Python Python alkahest-py PyO3 wrapper around Rust SDK

Client Setup

TypeScript

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";
import { makeClient } from "@alkahest/ts-sdk";

const walletClient = createWalletClient({
  account: privateKeyToAccount("0xPRIVATE_KEY"),
  chain: baseSepolia,
  transport: http("https://rpc-url"),
});

// Full client with all extensions
const client = makeClient(walletClient);

// Custom addresses (optional)
const client = makeClient(walletClient, customAddresses);

// Minimal client for custom extension patterns
const minimal = makeMinimalClient(walletClient);
const extended = minimal.extend((base) => ({
  custom: makeErc20Client(base.viemClient, pickErc20Addresses(base.contractAddresses)),
}));

Rust

use alkahest_rs::AlkahestClient;

// Full client with all extensions (Base Sepolia default)
let client = AlkahestClient::with_base_extensions(
    "0xPRIVATE_KEY",
    "https://rpc-url",
    None, // uses Base Sepolia addresses
).await?;

// Custom addresses
use alkahest_rs::{DefaultExtensionConfig, ETHEREUM_SEPOLIA_ADDRESSES};
let client = AlkahestClient::with_base_extensions(
    "0xPRIVATE_KEY",
    "https://rpc-url",
    Some(ETHEREUM_SEPOLIA_ADDRESSES),
).await?;

// Bare client + custom extensions
let bare = AlkahestClient::new("0xPRIVATE_KEY", "https://rpc-url").await?;
let extended = bare.extend::<Erc20Module>(Some(erc20_config)).await?;

Python

from alkahest_py import PyAlkahestClient

# Full client with all extensions (Base Sepolia default)
client = PyAlkahestClient("0xPRIVATE_KEY", "https://rpc-url")

# Custom addresses
from alkahest_py import DefaultExtensionConfig, PyErc20Addresses, ...
config = DefaultExtensionConfig(erc20_addresses=..., ...)
client = PyAlkahestClient("0xPRIVATE_KEY", "https://rpc-url", config)

Core Patterns

Creating an Escrow

TypeScript:

// 1. Approve token
await client.erc20.util.approve({ address: TOKEN, value: amount }, "escrow");

// 2. Create escrow
const { hash, attested } = await client.erc20.escrow.nonTierable.doObligation(
  client.erc20.escrow.nonTierable.encodeObligationRaw({
    token: TOKEN, amount, arbiter: ARBITER, demand: DEMAND_BYTES,
  }),
);
const escrowUid = attested.uid;

Rust:

// 1. Approve
client.erc20().approve(&Erc20Data { address: token, value: amount }, ApprovalPurpose::Escrow).await?;

// 2. Create escrow
let receipt = client.erc20().escrow().non_tierable().make_statement(
    token, amount, arbiter, demand_bytes, expiration,
).await?;
let attested = client.get_attested_event(receipt)?;

Python:

# 1. Approve
await client.erc20.util.approve(token_address, amount, "escrow")

# 2. Create escrow
uid = await client.erc20.escrow.non_tierable.create(
    token=token_address, amount=amount,
    arbiter=arbiter_address, demand=demand_bytes,
    expiration=expiration,
)

Fulfilling with StringObligation

TypeScript:

const { attested } = await client.stringObligation.doObligation(
  "fulfillment content",
  undefined,  // schema
  escrowUid,  // refUID
);

Rust:

let receipt = client.string_obligation().do_obligation(
    "fulfillment content", None, Some(escrow_uid),
).await?;

Python:

uid = await client.string_obligation.do_obligation(
    "fulfillment content",
    ref_uid=escrow_uid,
)

Collecting Escrow

TypeScript:

const { hash } = await client.erc20.escrow.nonTierable.collectObligation(
  escrowUid,
  fulfillmentUid,
);

Rust:

let receipt = client.erc20().escrow().non_tierable().collect_payment(
    escrow_uid, fulfillment_uid,
).await?;

Python:

tx_hash = await client.erc20.escrow.non_tierable.collect(escrow_uid, fulfillment_uid)

Waiting for Fulfillment

TypeScript:

const result = await client.waitForFulfillment(
  client.contractAddresses.erc20EscrowObligation,
  escrowUid,
);

Rust:

let log = client.wait_for_fulfillment(
    client.erc20_address(Erc20Contract::EscrowObligation),
    escrow_uid,
    None, // from_block
).await?;

Python:

result = await client.wait_for_fulfillment(
    escrow_contract_address,
    escrow_uid,
)

Encoding Demands

TypeScript:

// Trusted oracle
const demand = client.arbiters.general.trustedOracle.encodeDemand({
  oracle: ORACLE, data: "0x",
});

// Logical composition
const demand = client.arbiters.logical.all.encodeDemand({
  arbiters: [ARBITER_A, ARBITER_B],
  demands: [DEMAND_A, DEMAND_B],
});

// Attestation properties
const demand = client.arbiters.attestationProperties.attester.encodeDemand({
  attester: REQUIRED_ATTESTER,
});

Rust:

// Trusted oracle (ABI encoding)
use alloy::sol_types::SolValue;
let demand = TrustedOracleArbiter::DemandData { oracle, data: Bytes::new() }.abi_encode();

// Decode arbiter demand (auto-detects)
let decoded = client.arbiters().decode_arbiter_demand(arbiter_addr, &demand_bytes)?;

Python:

# Trusted oracle
demand = client.arbiters.trusted_oracle.encode_demand(oracle=ORACLE, data=b"")

# Logical composition
demand = client.arbiters.logical.all.encode(
    arbiters=[ARBITER_A, ARBITER_B],
    demands=[DEMAND_A, DEMAND_B],
)

Commit-Reveal Pattern

TypeScript:

// 1. Compute commitment
const commitment = await client.commitReveal.computeCommitment(
  escrowUid, claimerAddress, { payload, salt, schema },
);
// 2. Commit (sends bond as ETH)
await client.commitReveal.commit(commitment);
// 3. Wait 1+ blocks, then reveal
const { attested } = await client.commitReveal.doObligation(
  { payload, salt, schema }, escrowUid,
);
// 4. Reclaim bond
await client.commitReveal.reclaimBond(attested.uid);

Rust:

let commitment = client.commit_reveal().compute_commitment(
    escrow_uid, claimer, &obligation_data,
).await?;
client.commit_reveal().commit(commitment).await?;
// wait 1+ blocks
let receipt = client.commit_reveal().do_obligation(&obligation_data, Some(escrow_uid)).await?;
client.commit_reveal().reclaim_bond(obligation_uid).await?;

Python:

commitment = await client.commit_reveal.compute_commitment(
    escrow_uid, claimer, payload, salt, schema,
)
await client.commit_reveal.commit(commitment)
# wait 1+ blocks
uid = await client.commit_reveal.do_obligation(payload, salt, schema, ref_uid=escrow_uid)
await client.commit_reveal.reclaim_bond(uid)

Barter Utilities

Barter utils provide atomic single-transaction token swaps:

TypeScript:

await client.erc20.barter.buyErc20ForErc20(
  { address: BID_TOKEN, value: bidAmount },
  { address: ASK_TOKEN, value: askAmount },
  BigInt(Math.floor(Date.now() / 1000) + 3600),
);

Rust:

client.erc20().barter().buy_erc20_for_erc20(
    &bid_token, &ask_token, expiration,
).await?;

Key Type Differences

Concept TypeScript Rust Python
Addresses `0x${string}` Address str (hex)
Big integers bigint U256 str (decimal)
Bytes `0x${string}` Bytes / FixedBytes<32> bytes / str (hex)
Receipts { hash, attested } TransactionReceipt str (tx hash or uid)
Attestations Attestation object IEAS::Attestation PyAttestation

Reference Documentation

  • references/typescript-api.md — full TS SDK API tree
  • references/rust-api.md — full Rust SDK API tree
  • references/python-api.md — full Python SDK API tree
  • references/contracts.md — contract addresses and data schemas
  • docs/Escrow Flow (pt 1).md — token trading walkthrough
  • docs/Escrow Flow (pt 2).md — oracle arbitration walkthrough
  • docs/Escrow Flow (pt 2b).md — commit-reveal frontrunning protection
  • docs/Escrow Flow (pt 3).md — composing demands with logical arbiters
  • docs/Writing Arbiters/ — custom arbiter development
  • docs/Writing Contracts/ — custom escrow/obligation development
  • docs/mcp-server/ — MCP server for looking up contract details

Reviews (0)

Sign in to write a review.

No reviews yet. Be the first to review!

Comments (0)

Sign in to join the discussion.

No comments yet. Be the first to share your thoughts!

Compatible Platforms

Pricing

Free

Related Configs