> ## Documentation Index
> Fetch the complete documentation index at: https://daehan-base.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Base에서의 트레이드 실행

> 트레이딩 에이전트를 위한 Base 특화 패턴, 수수료 조정, 온체인 신호

export const TradeExecutionDemo = () => {
  const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace";
  const col = {
    dim: "#3f3f46",
    muted: "#52525b",
    active: "#60a5fa",
    success: "#34d399",
    code: "#d4d4d8"
  };
  const steps = [{
    delay: 350,
    left: [{
      t: "> Connect to mainnet-preconf.base.org...",
      c: "active"
    }],
    right: [{
      t: "── Flashblocks State ───────────────────",
      c: "dim"
    }, {
      t: "eth_getBlockByNumber(\"pending\")",
      c: "code"
    }, {
      t: "Host: mainnet-preconf.base.org",
      c: "muted"
    }]
  }, {
    delay: 650,
    left: [{
      t: "  ✓ preconf endpoint connected (200ms)",
      c: "success"
    }],
    right: [{
      t: "",
      c: "dim"
    }, {
      t: '{"pending": {',
      c: "code"
    }, {
      t: '  "number": "0x1B2A4F2",',
      c: "code"
    }, {
      t: '  "baseFeePerGas": "0x2386F26FC10"',
      c: "code"
    }, {
      t: "} }",
      c: "code"
    }]
  }, {
    delay: 500,
    left: [{
      t: "> Simulate buying $50 ETH (preconf state)...",
      c: "active"
    }],
    right: [{
      t: "",
      c: "dim"
    }, {
      t: "── eth_simulateV1 ──────────────────────",
      c: "dim"
    }, {
      t: "blockStateCalls: [pending]",
      c: "muted"
    }]
  }, {
    delay: 700,
    left: [{
      t: "  ✓ simulation passed · no revert",
      c: "success"
    }],
    right: [{
      t: "",
      c: "dim"
    }, {
      t: '{"results":[{"status":"0x1",',
      c: "code"
    }, {
      t: '  "gasUsed":"0x14c08"}]}',
      c: "code"
    }]
  }, {
    delay: 450,
    left: [{
      t: "> Get swap quote · price impact check...",
      c: "active"
    }],
    right: [{
      t: "",
      c: "dim"
    }, {
      t: "── Quote Details ───────────────────────",
      c: "dim"
    }, {
      t: '{"fromAmount":"50.00 USDC",',
      c: "code"
    }, {
      t: '  "toAmount":"0.01756 ETH",',
      c: "code"
    }, {
      t: '  "priceImpact":"0.12%"}',
      c: "code"
    }]
  }, {
    delay: 500,
    left: [{
      t: "  impact 0.12% < 1% — executing...",
      c: "muted"
    }],
    right: []
  }, {
    delay: 750,
    left: [{
      t: "  ✓ tx 0xb4f2...91ca confirmed (1 Flashblock)",
      c: "success"
    }],
    right: [{
      t: "",
      c: "dim"
    }, {
      t: "── base_transactionStatus ──────────────",
      c: "dim"
    }, {
      t: "  status:    preconfirmed",
      c: "success"
    }, {
      t: "  hash:      0xb4f2...91ca",
      c: "success"
    }, {
      t: "  block:     28,419,042",
      c: "muted"
    }, {
      t: "  latency:   ~200ms",
      c: "muted"
    }]
  }, {
    delay: 350,
    left: [{
      t: "  ✓ received 0.01756 ETH",
      c: "success",
      bold: true
    }],
    right: []
  }];
  const [leftLines, setLeftLines] = useState([]);
  const [rightLines, setRightLines] = useState([]);
  const [running, setRunning] = useState(false);
  const [done, setDone] = useState(false);
  const [blink, setBlink] = useState(true);
  const leftRef = useRef(null);
  const rightRef = useRef(null);
  useEffect(() => {
    const t = setInterval(() => setBlink(b => !b), 530);
    return () => clearInterval(t);
  }, []);
  useEffect(() => {
    if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight;
  }, [leftLines]);
  const play = () => {
    setLeftLines([]);
    setRightLines([]);
    setRunning(true);
    setDone(false);
    let i = 0;
    const next = () => {
      if (i >= steps.length) {
        setRunning(false);
        setDone(true);
        return;
      }
      const s = steps[i];
      setTimeout(() => {
        if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]);
        if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]);
        i++;
        next();
      }, s.delay);
    };
    next();
  };
  useEffect(() => {
    setTimeout(play, 350);
  }, []);
  const renderLine = (item, i) => {
    if (!item.t) return <div key={i} style={{
      height: 6
    }} />;
    return <div key={i} style={{
      fontFamily: mono,
      fontSize: 12,
      lineHeight: "20px",
      color: col[item.c] || col.code,
      fontWeight: item.bold ? 600 : 400,
      whiteSpace: "pre"
    }}>{item.t}</div>;
  };
  return <div style={{
    margin: "28px 0",
    borderRadius: 12,
    overflow: "hidden",
    border: "1px solid #27272a",
    background: "#09090b"
  }}>
      <div style={{
    display: "flex",
    alignItems: "center",
    padding: "8px 12px",
    background: "#111113",
    borderBottom: "1px solid #27272a"
  }}>
        <div style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    width: 28,
    height: 24,
    borderRadius: 6,
    background: "#1e1e20",
    border: "1px solid #27272a",
    marginRight: 10,
    flexShrink: 0
  }}>
          <span style={{
    fontFamily: mono,
    fontSize: 11,
    color: "#71717a",
    userSelect: "none"
  }}>{">"}_</span>
        </div>
        <span style={{
    fontFamily: mono,
    fontSize: 12,
    color: "#52525b"
  }}>Trade Execution</span>
        <div style={{
    flex: 1
  }} />
        <button onClick={play} title="Reset" style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    width: 28,
    height: 24,
    borderRadius: 6,
    background: "transparent",
    border: "1px solid transparent",
    cursor: "pointer",
    color: "#3f3f46",
    fontSize: 15,
    lineHeight: 1
  }} onMouseEnter={e => {
    e.currentTarget.style.color = "#a1a1aa";
    e.currentTarget.style.background = "#1e1e20";
    e.currentTarget.style.borderColor = "#27272a";
  }} onMouseLeave={e => {
    e.currentTarget.style.color = "#3f3f46";
    e.currentTarget.style.background = "transparent";
    e.currentTarget.style.borderColor = "transparent";
  }}>
          {"\u21ba"}
        </button>
      </div>

      <div style={{
    height: 250,
    borderBottom: "1px solid #27272a",
    overflow: "hidden",
    display: "flex",
    flexDirection: "column"
  }}>
        <div style={{
    padding: "7px 16px 5px",
    borderBottom: "1px solid #1c1c1e"
  }}>
          <span style={{
    fontFamily: mono,
    fontSize: 10,
    fontWeight: 600,
    letterSpacing: "0.1em",
    textTransform: "uppercase",
    color: "#3f3f46"
  }}>Agent</span>
        </div>
        <div ref={leftRef} style={{
    flex: 1,
    overflowY: "hidden",
    padding: "12px 16px"
  }}>
          {leftLines.map(renderLine)}
          {running && <div style={{
    fontFamily: mono,
    fontSize: 12,
    lineHeight: "20px",
    color: "#60a5fa",
    opacity: blink ? 1 : 0
  }}>{"▋"}</div>}
        </div>
      </div>

      <div style={{
    padding: "8px 16px",
    display: "flex",
    justifyContent: "center",
    minHeight: 37,
    alignItems: "center"
  }}>
        {done && <button onClick={play} style={{
    fontFamily: mono,
    fontSize: 11,
    color: "#52525b",
    background: "none",
    border: "none",
    cursor: "pointer",
    padding: "4px 10px",
    borderRadius: 4
  }} onMouseEnter={e => {
    e.currentTarget.style.color = "#a1a1aa";
    e.currentTarget.style.background = "#18181b";
  }} onMouseLeave={e => {
    e.currentTarget.style.color = "#52525b";
    e.currentTarget.style.background = "none";
  }}>
            {"\u21ba"} Play again
          </button>}
      </div>
    </div>;
};

Base는 트레이딩 에이전트에게 두 가지 구조적 이점을 제공합니다: **Flashblocks** (200ms 사전 확인된 블록 상태, 2초 블록보다 10배 빠름)와 명시적인 비용-속도 트레이드오프를 가능하게 하는 노출된 L1/L2 수수료 구조. 이 페이지는 Base에 고유한 내용만 다룹니다 — 일반 EVM 실행 패턴은 [Ethereum 문서](https://ethereum.org/developers/docs)에, Base의 RPC 메서드는 [API 레퍼런스](/base-chain/api-reference/rpc-overview)에 있습니다.

## 모의 데모

<TradeExecutionDemo />

## 지갑 기본 도구로 스왑 실행

[Bankr](https://bankr.bot), [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/), [Sponge Wallet](https://www.paysponge.com) 모두 내장된 스왑 기능을 포함합니다 — 외부 DEX 통합이 필요하지 않습니다.

[Bankr](https://bankr.bot) 사용:

```text theme={null}
Buy $50 of ETH on Base
Swap 100 USDC for ETH at market price
```

[CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) 스킬 사용:

```text theme={null}
Buy $50 of ETH
Trade 0.01 ETH for USDC
```

[Sponge Wallet](https://www.paysponge.com) 사용:

```bash Terminal theme={null}
curl -X POST "https://api.wallet.paysponge.com/api/swap" \
  -H "Authorization: Bearer $SPONGE_API_KEY" \
  -H "Sponge-Version: 0.2.1" \
  -H "Content-Type: application/json" \
  -d '{
    "fromToken": "USDC",
    "toToken": "ETH",
    "amount": "100",
    "chain": "base"
  }'
```

## 실행 패턴

### 모든 읽기와 제출에 preconf 엔드포인트 사용

항상 표준 엔드포인트 대신 `mainnet-preconf.base.org` (또는 테스트넷의 경우 `sepolia-preconf.base.org`)에 연결하세요. 이것이 Flashblocks `pending` 상태, 사전 확인된 트랜잭션 스트림, `base_transactionStatus`에 접근하는 유일한 방법입니다. 전체 목록은 [Flashblocks 엔드포인트](/base-chain/flashblocks/app-integration#rpc-endpoints)를 참조하세요.

### 서명 전 사전 확인된 상태에 대해 시뮬레이션

트랜잭션에 서명하기 전에 `"blockStateCalls"`가 `pending` 블록을 대상으로 하는 preconf 엔드포인트에 대해 [`eth_simulateV1`](/base-chain/api-reference/flashblocks-api/eth_simulateV1)을 호출합니다. 이렇게 하면 트랜잭션이 착지할 때까지 최대 2초 오래된 마지막 봉인된 블록이 아닌 현재 Flashblocks 상태에 대한 리버트를 포착합니다.

### 영수증을 기다리는 대신 `base_transactionStatus` 폴링

제출 후 [`base_transactionStatus`](/base-chain/api-reference/flashblocks-api/base_transactionStatus)는 단일 Flashblock 간격(\~200ms) 내에 사전 확인된 포함 상태를 반환합니다. `eth_getTransactionReceipt`를 기다리면 전체 봉인된 블록(최대 2초)을 기다립니다. 지연에 민감한 전략의 경우 먼저 `base_transactionStatus`를 폴링하고 최종성 확인을 위해서만 영수증으로 폴백합니다.

## 수수료 조정

### L2 우선순위 수수료 휴리스틱

보상 백분위수 `[50, 90]`으로 최근 5-10 블록에 대해 `eth_feeHistory`를 사용합니다:

* **50번째 백분위수 보상** — 1-3 Flashblocks 내 표준 포함
* **90번째 백분위수 보상** — 다음 Flashblock 내 빠른 포함
* **`maxFeePerGas`** — 과다 지불 없이 여러 블록에 걸친 기본 수수료 증가를 견디려면 `nextBaseFee * 2 + maxPriorityFeePerGas`로 설정

### L1 수수료 결정 규칙

서명 전에 [GasPriceOracle](/base-chain/network-information/network-fees#querying-the-l1-fee)을 통해 L1 비용을 추정합니다. 아래 비율이 `0.8`을 초과하고 거래 규모가 작으면 L1 수수료가 총 비용을 지배합니다 — Ethereum 혼잡이 완화될 때까지 연기하는 것을 고려하세요:

```
l1FeeUpperBound / (gasLimit × maxFeePerGas + l1FeeUpperBound) > 0.8
```

## Base 특화 장애 모드

대부분의 트랜잭션 오류는 표준 EVM입니다. 다음은 다른 처리가 필요한 Base 특화 사례입니다:

| 장애                                    | 의미                                                                     | 처리 방법                              |
| ------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------- |
| `replacement transaction underpriced` | 대기 중인 트랜잭션 교체 시 `maxFeePerGas`와 `maxPriorityFeePerGas` 모두 ≥10% 높아야 합니다 | 둘 다 ≥10% 증가, 동일한 nonce로 재제출        |
| DA 쓰로틀링 (오류 코드 없음)                    | 시퀀서가 L1 데이터 가용성 비용을 관리하기 위해 L2 처리량을 속도 제한 중                            | 수수료 인상으로 해결되지 않음 — 쓰로틀이 해제될 때까지 대기 |

전체 오류 분류법은 [트랜잭션 문제 해결](/base-chain/network-information/troubleshooting-transactions)을 참조하세요.

**동시 제출을 위한 nonce:** 항상 `eth_getTransactionCount(address, "pending")`로 조회합니다. 병렬 제출의 경우 한 번만 조회하고 로컬에서 증가시킵니다 — 호출마다 새로 조회하면 모든 동시 요청에 대해 동일한 값이 반환됩니다.

## 전략 신호

Base는 대부분의 체인이 이 해상도로 제공하지 않는 데이터를 노출합니다:

| 신호                              | 접근 방법                                               | 기회 카테고리                   |
| ------------------------------- | --------------------------------------------------- | ------------------------- |
| 사전 확인된 pending 블록 상태 (200ms 선행) | preconf 엔드포인트에서 `eth_getBlockByNumber("pending")`   | 블록 봉인 전 가격 영향 감지          |
| 사전 확인된 트랜잭션 스트림                 | `eth_subscribe("newFlashblockTransactions")`        | 블록에 진입하는 대규모 거래에서 선점      |
| 사전 확인된 로그                       | `eth_subscribe("pendingLogs", { address, topics })` | 최종성 전 청산 임계값, 오라클 업데이트 감지 |
| 수수료 급등 감지                       | 최근 5 블록에 대한 `eth_feeHistory` 추세                     | 혼잡 시작 식별; 라우팅 조정 또는 일시 중지 |
| L1 기본 수수료 추세                    | 시간 경과에 따른 `GasPriceOracle.l1BaseFee()` 폴링           | L1 데이터 비용 최소화를 위한 제출 타이밍  |
| 블록 가스 사용률                       | `eth_feeHistory`의 `gasUsedRatio`                    | 예정된 기본 수수료 증가 예측          |

**Flashblocks의 이점:** 대부분의 체인은 순서가 불확실한 대기 중인 트랜잭션 풀을 노출합니다. Base에서 Flashblocks 엔드포인트는 에이전트에게 최종화되기 전 다음 200ms의 체인 상태에 대한 결정론적이고 순서 있는 뷰를 제공합니다. 이는 멤풀 전용 가시성을 가진 체인에는 존재하지 않는 정보 이점입니다.

## 관련 항목

* [Flashblocks API 레퍼런스](/base-chain/api-reference/rpc-overview#flashblocks-api) — `eth_simulateV1`, `base_transactionStatus`, 구독 타입
* [Flashblocks 통합 가이드](/base-chain/flashblocks/app-integration) — 엔드포인트, 라이브러리 설정 (Wagmi, Viem, Ethers)
* [블록 빌딩](/base-chain/network-information/block-building) — Flashblocks 타이밍, 트랜잭션별 가스 최대값
* [네트워크 수수료](/base-chain/network-information/network-fees) — EIP-1559 파라미터, GasPriceOracle 메서드
* [JSON-RPC API 레퍼런스](/base-chain/api-reference/rpc-overview) — 전체 RPC 메서드 레퍼런스
* [트랜잭션 문제 해결](/base-chain/network-information/troubleshooting-transactions) — 전체 오류 분류법과 재시도 정책
