Skip to main content

Documentation Index

Fetch the complete documentation index at: https://daehan-base.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

개요

스펜드 퍼미션을 통해 신뢰할 수 있는 spender를 지정하여 사용자를 대신해 Base Account에서 자산을 이동할 수 있습니다. 사용자가 퍼미션에 서명하면, spender는 정의한 한도 내에서 추가 프롬프트, 팝업, 사용자 서명 없이 전송을 시작할 수 있습니다. 이를 통해 구독 갱신, 알고리즘 거래, 자동화된 지불과 같은 원활한 경험이 가능합니다. Spend Permission Manager 컨트랙트와 지원 체인에 대해 자세히 알아보려면 GitHub을 참조하세요.
Base App 앱을 위한 스펜드 퍼미션은 곧 출시될 예정이며 향후 업데이트에서 지원될 것입니다.
서브 어카운트를 사용하고 있다면, Base Account가 서브 어카운트에 자동으로 자금을 지원하고 선택적으로 승인 프롬프트를 건너뛸 수 있는 자동 스펜드 퍼미션을 확인해 보세요.

사용법

스펜드 퍼미션 요청

퍼미션을 설명하는 EIP-712 페이로드를 생성하고 사용자에게 서명을 요청합니다. 나중에 온체인에서 퍼미션을 등록할 수 있도록 퍼미션 데이터와 함께 서명 결과를 저장합니다. 아래 SDK 헬퍼가 구성과 서명을 처리해 줍니다.
필드명타입설명
accountaddress이 스펜드 퍼미션이 유효한 스마트 계정
spenderaddressaccount의 토큰을 지출할 수 있는 주체
tokenaddress토큰 주소 (ERC-7528 네이티브 토큰 또는 ERC-20 컨트랙트)
allowanceuint160period 내에서 지출할 수 있는 최대 허용 값
perioduint48사용된 allowance를 반복적으로 초기화하는 시간 기간 (초)
startuint48이 스펜드 퍼미션이 유효하기 시작하는 타임스탬프 (포함, Unix 초)
enduint48이 스펜드 퍼미션이 유효한 마지막 타임스탬프 (미포함, Unix 초)
saltuint256동일한 필드를 가진 고유한 스펜드 퍼미션을 구별하기 위한 임의 데이터
extraDatabytesspender가 소비할 수 있는 스펜드 퍼미션에 첨부되는 임의 데이터
import { requestSpendPermission } from "@base-org/account/spend-permission";
import { createBaseAccountSDK } from "@base-org/account";
import { base } from "viem/chains";

const sdk = createBaseAccountSDK({
  appName: 'Base Account SDK 데모',
  appLogoUrl: 'https://base.org/logo.png',
  appChainIds: [base.id],
});

const permission = await requestSpendPermission({
  account: "0x...",
  spender: "0x...",
  token: "0x...",
  chainId: 8453, // 또는 지원되는 다른 체인
  allowance: 1_000_000n,
  periodInDays: 30,
  provider: sdk.getProvider(),
});

console.log("Spend Permission:", permission);

스펜드 퍼미션 사용

퍼미션을 사용하는 것은 2단계입니다:
  1. 콜 준비 — 퍼미션과 요청된 amountprepareSpendCallData를 호출합니다.
  2. 콜 제출 — 앱의 spender 계정을 사용하여 콜을 제출합니다.
prepareSpendCallData는 토큰을 지출하는 데 필요한 콜 배열을 반환합니다:
  • approveWithSignature — 퍼미션이 아직 온체인에 등록되지 않은 경우, 이 콜이 spend 콜 앞에 추가됩니다.
  • spend — 사용자의 Base Account에서 토큰을 지출하는 콜.
import { prepareSpendCallData } from "@base-org/account/spend-permission";

// [approveWithSignatureCall, spendCall] 반환
const spendCalls = await prepareSpendCallData({
  permission,
  amount, // 선택사항; 생략하면 남은 한도를 지출
});

// 앱 spender 계정이 wallet_sendCalls를 지원하는 경우, wallet_sendCalls를 사용하여 배치로 제출
// 이것은 provider 인터페이스에서 wallet_sendCalls를 사용하는 예입니다
await provider.request({
  method: "wallet_sendCalls",
  params: [
    {
      version: "2.0",
      atomicRequired: true,
      from: spender,
      calls: spendCalls,
    },
  ],
});

// 앱 spender 계정이 wallet_sendCalls를 지원하지 않는 경우, eth_sendTransaction을 사용하여 순서대로 제출
// 이것은 provider 인터페이스에서 eth_sendTransaction을 사용하는 예입니다
await Promise.all(
  spendCalls.map((call) =>
    provider.request({
      method: "eth_sendTransaction",
      params: [
        {
          ...call,
          from: spender,
        },
      ],
    })
  )
);
spendCalls 배열에 대하여이 배열은 처음으로 온체인에 퍼미션을 제출할 때 2개의 콜을 가집니다. 퍼미션이 이미 온체인에 등록된 경우, 이 배열에는 1개의 콜(spend 콜)만 있습니다.대부분의 사용 사례에서는 이에 대해 걱정할 필요가 없습니다.

스펜드 퍼미션 취소

두 가지 방법으로 퍼미션을 취소할 수 있습니다:
  • requestRevoke를 사용하여 사용자의 Base Account에 요청을 통해 사용자 승인을 요청합니다.
  • prepareRevokeCallData에서 반환된 콜을 제출하여 앱의 spender에서 자동으로 취소합니다.
import {
  requestRevoke,
  prepareRevokeCallData,
} from "@base-org/account/spend-permission";

// 옵션 A: 사용자 시작 취소 (지갑 팝업)
try {
  const hash = await requestRevoke(permission);
  console.log("취소 성공", hash);
} catch {
  console.warn("취소가 거부되었거나 실패했습니다");
}

// 옵션 B: 앱의 spender 계정에 의한 자동 취소
const revokeCall = await prepareRevokeCallData(permission);

// 앱의 spender 계정을 사용하여 취소 콜 제출
// 이것은 provider 인터페이스에서 wallet_sendCalls를 사용하는 예입니다
await provider.request({
  method: "wallet_sendCalls",
  params: [
    {
      version: "2.0",
      atomicRequired: true,
      from: spender,
      calls: [revokeCall],
    },
  ],
});

// 앱 spender 계정이 wallet_sendCalls를 지원하지 않는 경우, eth_sendTransaction을 사용하여 취소 콜 제출
// 이것은 provider 인터페이스에서 eth_sendTransaction을 사용하는 예입니다
await provider.request({
  method: "eth_sendTransaction",
  params: [
    {
      ...revokeCall,
      from: spender,
    },
  ],
});

API 참조

  • requestSpendPermission
  • prepareSpendCallData
  • requestRevoke
  • prepareRevokeCallData
  • fetchPermissions
  • fetchPermission
  • getPermissionStatus

완전한 통합 예제

import {
  fetchPermissions,
  fetchPermission,
  getPermissionStatus,
  prepareSpendCallData,
  requestSpendPermission,
  requestRevoke,
  prepareRevokeCallData,
} from "@base-org/account/spend-permission";

import { createBaseAccountSDK } from "@base-org/account";
import { base } from "viem/chains";

const sdk = createBaseAccountSDK({
  appName: 'Base Account SDK 데모',
  appLogoUrl: 'https://base.org/logo.png',
  appChainIds: [base.id],
});

const spender = "0xAppSpenderAddress";

// 1) 해시로 특정 퍼미션 가져오기
// 이미 퍼미션 해시를 알고 있을 때 fetchPermission을 사용합니다
// (예: 이전 세션에서 저장했거나 파라미터로 전달됨)
const permission = await fetchPermission({
  permissionHash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  provider: sdk.getProvider(),
});

// 대안: spender의 모든 퍼미션 가져오기
// 모든 사용 가능한 퍼미션을 확인하고 사용할 것을 선택할 때 fetchPermissions를 사용합니다
// const permissions = await fetchPermissions({
//   account: "0xUserBaseAccountAddress",
//   chainId: 84532,
//   spender,
//   provider: sdk.getProvider(),
// });
// const permission = permissions.at(0);

// ========================================
// 기존 퍼미션이 있는 경우
// ========================================

// 2. 퍼미션 상태 확인
try {
  const { isActive, remainingSpend } = await getPermissionStatus(permission);
  const amount = 1000n;

  if (!isActive || remainingSpend < amount) {
    throw new Error("사용 가능한 스펜드 퍼미션이 없습니다");
  }
} catch {
  throw new Error("사용 가능한 스펜드 퍼미션이 없습니다");
}

// 3. 콜 준비
const [approveCall, spendCall] = await prepareSpendCallData({
  permission,
  amount,
});

// 4. 앱의 spender 계정을 사용하여 콜 실행
// 이것은 wallet_sendCalls를 사용한 예입니다. 프로덕션에서는 eth_sendTransaction을 사용할 수 있습니다.
await provider.request({
  method: "wallet_sendCalls",
  params: [
    {
      version: "2.0",
      atomicRequired: true,
      from: spender,
      calls: [approveCall, spendCall],
    },
  ],
});

// ========================================
// 기존 퍼미션이 없는 경우
// ========================================

// 2. 사용할 스펜드 퍼미션 요청
const newPermission = await requestSpendPermission({
  account: "0xUserBaseAccountAddress",
  spender,
  token: "0xTokenContractAddress",
  chainId: 84532,
  allowance: 1_000_000n,
  periodInDays: 30,
  provider: sdk.getProvider(),
});

// 3. 콜 준비
const spendCalls = await prepareSpendCallData({
  permission: newPermission,
  amount: 1_000n,
});

// 4. 앱의 spender 계정을 사용하여 콜 실행
// 이것은 eth_sendTransaction을 사용한 예입니다. 앱 계정이 wallet_sendCalls를 지원하면, wallet_sendCalls를 사용하여 콜을 배치로 처리하세요.
await Promise.all(
  spendCalls.map((call) =>
    provider.request({
      method: "eth_sendTransaction",
      params: [
        {
          ...call,
          from: spender,
        },
      ],
    })
  )
);

// ========================================
// 사용자에게 스펜드 퍼미션 취소 요청
// ========================================

try {
  const hash = await requestRevoke(permission);
  console.log("취소 성공", hash);
} catch {
  throw new Error("취소 실패");
}

// ========================================
// 백그라운드에서 스펜드 퍼미션 취소
// ========================================

const revokeCall = await prepareRevokeCallData(permission);

await provider.request({
  method: "wallet_sendCalls",
  params: [
    {
      version: "2.0",
      atomicRequired: true,
      from: spender,
      calls: [revokeCall],
    },
  ],
});

활용 사례 예제

Base에서 보안 스펜드 퍼미션을 사용하여 자율적으로 Zora Creator Coins를 구매할 수 있는 AI 에이전트를 구축한다고 가정해 보겠습니다. 이 예제는 Base Account의 스펜드 퍼미션을 Coinbase Developer Platform(CDP) 서버 지갑Trade API와 결합하여 원활하고 가스 없는 AI 에이전트 트랜잭션을 구현하는 방법을 보여줍니다.
스펜드 퍼미션 에이전트 인터페이스

라이브 데모

라이브 애플리케이션을 사용해 보고 스펜드 퍼미션이 작동하는 것을 확인하세요

소스 코드

GitHub에서 완전한 구현을 탐색하세요