> For the complete documentation index, see [llms.txt](https://docs.astralbeam.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.astralbeam.io/for-developers/developer-guide.md).

# Developer Guide

This guide covers integrating with AstralBeam programmatically, whether you're building applications that interact with the bridge contracts directly, integrating the bridge into your dApp, or contributing to the bridge codebase.

## Integration Options

### 1. Smart Contract Integration

Interact directly with bridge contracts on-chain:

```mermaid
flowchart LR
    subgraph "Your dApp"
        A["Smart Contract"]
        B[Frontend]
    end
    subgraph "AstralBeam"
        C[MultiSigLocker]
        D[TokenFactory]
    end

    A --> C
    B --> A
```

**Use Cases:**

* Automated bridging from your contracts
* Composable DeFi integrations
* Custom bridge workflows

### 2. API Integration

Use the REST API for off-chain applications:

```mermaid
flowchart LR
    A[Your Backend] --> B[Bridge API]
    B --> C[Transaction Status]
    B --> D[Token Info]
    B --> E[Statistics]
```

**Use Cases:**

* Transaction tracking dashboards
* Portfolio management
* Analytics applications

### 3. Direct SDK/Library Usage

Use ethers.js and casper-js-sdk to interact with contracts:

**Use Cases:**

* Custom bridging interfaces
* Wallet integrations
* Automated trading bots

***

## Quick Start Examples

### Lock Tokens (EVM to Casper)

```typescript
import { ethers } from 'ethers';

const LOCKER_ABI = [
  'function lock(address token, uint256 amount, bytes32 casperRecipient) payable',
  'function bridgeFee() view returns (uint256)'
];

async function lockTokens(
  provider: ethers.Provider,
  signer: ethers.Signer,
  lockerAddress: string,
  tokenAddress: string,
  amount: bigint,
  casperRecipient: string
) {
  const locker = new ethers.Contract(lockerAddress, LOCKER_ABI, signer);
  const token = new ethers.Contract(tokenAddress, [
    'function approve(address spender, uint256 amount) returns (bool)'
  ], signer);

  // Get bridge fee
  const bridgeFee = await locker.bridgeFee();

  // Approve tokens
  const approveTx = await token.approve(lockerAddress, amount);
  await approveTx.wait();

  // Convert Casper public key to bytes32
  const recipientBytes = ethers.zeroPadValue(
    ethers.getBytes('0x' + casperRecipient),
    32
  );

  // Lock tokens
  const lockTx = await locker.lock(
    tokenAddress,
    amount,
    recipientBytes,
    { value: bridgeFee }
  );

  const receipt = await lockTx.wait();
  console.log('Lock transaction:', receipt.hash);

  return receipt;
}
```

### Track Bridge Transaction

```typescript
async function trackBridgeTransaction(txHash: string): Promise<void> {
  const API_BASE = 'https://api.csprbridge.com/api/v1';

  // Poll for transaction status
  while (true) {
    const response = await fetch(`${API_BASE}/transactions/${txHash}`);
    const tx = await response.json();

    console.log(`Status: ${tx.status}`);
    console.log(`Source: ${tx.sourceChain} -> ${tx.destinationChain}`);

    if (tx.status === 'completed') {
      console.log(`Destination TX: ${tx.destinationTxHash}`);
      break;
    }

    if (tx.status === 'failed') {
      throw new Error(`Bridge failed: ${tx.error}`);
    }

    // Wait before next poll
    await new Promise(r => setTimeout(r, 30000));
  }
}
```

### Query Token Balances

```typescript
import { CasperClient, CLPublicKey } from 'casper-js-sdk';

async function getCasperTokenBalance(
  nodeUrl: string,
  tokenContractHash: string,
  accountPublicKey: string
): Promise<bigint> {
  const client = new CasperClient(nodeUrl);

  const accountHash = CLPublicKey.fromHex(accountPublicKey)
    .toAccountHashStr()
    .slice(13); // Remove 'account-hash-' prefix

  const result = await client.nodeClient.queryContractDictionary(
    tokenContractHash,
    'balances',
    accountHash
  );

  return BigInt(result.CLValue.data.toString());
}
```

***

## Development Workflow

### Setting Up Local Environment

1. **Clone the repository:**

   ```bash
   git clone https://github.com/make-software/cspr-bridge.git
   cd bridge
   ```
2. **Install dependencies:**

   ```bash
   # CLI and workers
   cd cli
   npm install

   # EVM contracts
   cd ../contracts/eth
   forge install

   # Casper contracts
   cd ../casper
   cargo odra build
   ```
3. **Configure environment:**

   ```bash
   cp .env.example .env
   # Edit .env with your RPC endpoints and keys
   ```

### Running Tests

```bash
# TypeScript tests
cd cli
npm test

# EVM contract tests
cd contracts/eth
forge test

# Casper contract tests
cd contracts/casper
cargo odra test
```

### Local Development Network

For local testing, you can use:

* **EVM**: Anvil (from Foundry) or Hardhat
* **Casper**: NCTL (Casper's local network tool)

```bash
# Start local Anvil
anvil --chain-id 31337

# Start NCTL (requires Casper node installation)
nctl-start
```

***

## Architecture Overview for Developers

### Contract Interaction Flow

```mermaid
sequenceDiagram
    participant User
    participant YourContract
    participant MultiSigLocker
    participant Relayers
    participant TokenFactory

    User->>YourContract: initiateBridge()
    YourContract->>MultiSigLocker: lock(token, amount, recipient)
    MultiSigLocker-->>YourContract: LockEvent

    Note over Relayers: Monitor & Attest

    Relayers->>TokenFactory: mint(attestation, signatures)
    TokenFactory-->>User: Tokens on Casper
```

### Key Contract Addresses

| Network        | Contract       | Address                                                                 |
| -------------- | -------------- | ----------------------------------------------------------------------- |
| Sepolia        | MultiSigLocker | `0x6aaea12cF566C9fddbC7082c15d38F1447a57D10`                            |
| Base Sepolia   | MultiSigLocker | `0xB4Fcc5E0b3590272820b89aBfc55E8ceb7cFDabc`                            |
| Casper Testnet | TokenFactory   | `hash-bf16ba78a7ecfb0e64756aa8468251110f29639f38ccaf9bdb01b6f38a15c2f2` |
| Casper Testnet | EthClient      | `hash-fa183fe46e92b65da88265deb0d48c7ae44bf44d7917f19875f4457321497aa2` |

***

## Event Signatures

### EVM MultiSigERC20Locker Events

#### Ethereum-Native Token Events (EVM → Casper)

**Locked** - Emitted when ERC-20 tokens are locked for bridging to Casper:

```solidity
event Locked(
    address indexed token,
    address indexed sender,
    uint256 amount,
    bytes32 indexed casperRecipient,
    uint256 nonce
);
```

**Unlocked** - Emitted when tokens are unlocked from Casper burn:

```solidity
event Unlocked(
    address indexed token,
    address indexed recipient,
    uint256 amount,
    bytes32 indexed casperStateRoot,
    bytes32 eventKey
);
```

#### Casper-Native Token Events (Casper → EVM)

**WrappedMinted** - Emitted when wrapped tokens are minted (Casper-native locked on Casper):

```solidity
event WrappedMinted(
    address indexed wrappedToken,
    bytes32 indexed casperTokenHash,
    address indexed recipient,
    uint256 amount,
    bytes32 casperEventKey
);
```

**WrappedBurned** - Emitted when user burns wrapped tokens to unlock on Casper:

```solidity
event WrappedBurned(
    address indexed wrappedToken,
    bytes32 indexed casperTokenHash,
    address indexed sender,
    uint256 amount,
    bytes32 casperRecipient,
    uint256 nonce
);
```

**WrappedTokenDeployed** - Emitted when a new wrapped ERC-20 is deployed:

```solidity
event WrappedTokenDeployed(
    address indexed wrappedToken,
    bytes32 indexed casperTokenHash,
    string name,
    string symbol,
    uint8 decimals
);
```

#### Administrative Events

**TokenRegistered** - Emitted when a token mapping is registered:

```solidity
event TokenRegistered(
    address indexed token,
    bytes32 indexed casperContractHash,
    string name,
    string symbol,
    uint8 decimals
);
```

**RelayerSetUpdated** - Emitted when relayer set or threshold changes:

```solidity
event RelayerSetUpdated(
    address[] relayers,
    uint256 threshold
);
```

**FeeCollected** - Emitted when bridge fee is collected:

```solidity
event FeeCollected(
    address indexed token,
    address indexed user,
    uint256 fee
);
```

**FeeParametersUpdated** - Emitted when fee parameters change:

```solidity
event FeeParametersUpdated(
    uint256 bridgeFee,
    address feeRecipient
);
```

**ContractUpgraded** - Emitted on UUPS upgrade:

```solidity
event ContractUpgraded(
    address indexed newImplementation,
    uint256 version
);
```

**TokenMinLockAmountUpdated** - Emitted when minimum lock amount changes:

```solidity
event TokenMinLockAmountUpdated(
    address indexed token,
    uint256 minAmount
);
```

**LockedBalanceSynced** - Emitted when locked balance is synced:

```solidity
event LockedBalanceSynced(
    address indexed token,
    uint256 balance
);
```

***

### Casper TokenFactory Events

#### Ethereum-Native Token Events (EVM → Casper)

**TokenDeployed** - Emitted when a new CEP-18 wrapper is deployed:

```rust
pub struct TokenDeployed {
    pub erc20_address: H160,      // Original ERC-20 address
    pub cep18_address: Address,   // Deployed CEP-18 contract
    pub name: String,
    pub symbol: String,
    pub decimals: u8,
}
```

**TokensMinted** - Emitted when wrapped CEP-18 tokens are minted:

```rust
pub struct TokensMinted {
    pub token: Address,           // CEP-18 token address
    pub recipient: Address,       // Casper recipient
    pub amount: U256,
    pub source_chain_id: u64,     // Source EVM chain ID
    pub eth_block_number: u64,
    pub eth_tx_index: u64,
}
```

**TokensBurned** - Emitted when user burns CEP-18 to unlock on EVM:

```rust
pub struct TokensBurned {
    pub token: Address,           // CEP-18 token address
    pub sender: Address,          // Casper sender
    pub amount: U256,
    pub eth_recipient: H160,      // EVM recipient address
    pub target_chain_id: u64,     // Target EVM chain ID
    pub nonce: u64,
}
```

#### Casper-Native Token Events (Casper → EVM)

**NativeTokenRegistered** - Emitted when a Casper-native token is registered:

```rust
pub struct NativeTokenRegistered {
    pub cep18_address: Address,   // Native CEP-18 address
    pub wrapped_token: H160,      // Wrapped ERC-20 on EVM
    pub name: String,
    pub symbol: String,
    pub decimals: u8,
}
```

**NativeTokenLocked** - Emitted when Casper-native tokens are locked for bridging:

```rust
pub struct NativeTokenLocked {
    pub cep18_address: Address,   // Native CEP-18 address
    pub sender: Address,          // Casper sender
    pub amount: U256,
    pub eth_recipient: H160,      // EVM recipient
    pub target_chain_id: u64,     // Target EVM chain ID
    pub nonce: u64,
}
```

**NativeTokenUnlocked** - Emitted when Casper-native tokens are unlocked:

```rust
pub struct NativeTokenUnlocked {
    pub cep18_address: Address,   // Native CEP-18 address
    pub recipient: Address,       // Casper recipient
    pub amount: U256,
    pub eth_burn_nonce: u64,      // EVM burn nonce
}
```

**NativeTokenWrappedUpdated** - Emitted when wrapped address is updated:

```rust
pub struct NativeTokenWrappedUpdated {
    pub cep18_address: Address,
    pub old_wrapped_token: H160,
    pub new_wrapped_token: H160,
}
```

#### Administrative Events

**FeeCollected** - Emitted when bridge fee is collected:

```rust
pub struct FeeCollected {
    pub user: Address,
    pub amount: U512,
    pub token: Address,
}
```

**TokenMappingRegistered** - Emitted when token mapping is registered:

```rust
pub struct TokenMappingRegistered {
    pub erc20_address: H160,
    pub cep18_address: Address,
}
```

**TokenMappingUnregistered** - Emitted when token mapping is removed:

```rust
pub struct TokenMappingUnregistered {
    pub erc20_address: H160,
}
```

**FeeParametersUpdated** - Emitted when fee parameters change:

```rust
pub struct FeeParametersUpdated {
    pub new_fee: U512,
    pub new_recipient: Address,
}
```

***

### Casper EthClient Events

**BlockHeaderSubmitted** - Emitted when a block header is submitted:

```rust
pub struct BlockHeaderSubmitted {
    pub block_number: u64,
    pub block_hash: H256,
    pub submitter: Address,
}
```

**RelayerAdded** - Emitted when a relayer is added:

```rust
pub struct RelayerAdded {
    pub eth_address: H160,
    pub relayer_index: u32,
}
```

**RelayerRemoved** - Emitted when a relayer is removed:

```rust
pub struct RelayerRemoved {
    pub eth_address: H160,
}
```

**ThresholdUpdated** - Emitted when signature threshold changes:

```rust
pub struct ThresholdUpdated {
    pub old_threshold: u32,
    pub new_threshold: u32,
}
```

***

## Best Practices

### Security Considerations

1. **Validate addresses**: Always validate token addresses and recipient formats
2. **Check allowances**: Ensure sufficient token approval before locking
3. **Handle failures**: Implement proper error handling for failed transactions
4. **Monitor events**: Use event listeners rather than polling when possible

### Gas Optimization

```typescript
// Batch approve for multiple bridges
const MAX_UINT256 = ethers.MaxUint256;
await token.approve(lockerAddress, MAX_UINT256);

// Or use permit if supported (EIP-2612)
await token.permit(owner, spender, value, deadline, v, r, s);
```

### Error Handling

```typescript
try {
  const tx = await locker.lock(token, amount, recipient, { value: fee });
  await tx.wait();
} catch (error) {
  console.error('Bridge error:', error.message);
}
```

***

## Next Steps

* [Local Development Setup](/for-developers/local-development.md) - Detailed local environment setup
* [Testing Guide](/for-developers/testing.md) - Running and writing tests
* [Contributing](/for-developers/contributing.md) - How to contribute to the project


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.astralbeam.io/for-developers/developer-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
