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.

Base Account가 제공하는 가장 큰 UX 향상 중 하나는 앱 개발자가 사용자의 트랜잭션을 스폰서할 수 있는 기능입니다. 앱이 Base Account를 지원한다면 표준화된 페이마스터 서비스 통신새로운 지갑 RPC 메서드를 사용하여 사용자의 트랜잭션을 스폰서할 수 있습니다. 이 가이드는 Base Account 사용에 특화되어 있습니다. Base에서 페이마스터를 사용하는 방법에 대해 자세히 알아보려면 Coinbase Developer Platform 문서를 참조하세요.

구현 가이드

1

페이마스터 서비스 설정

먼저 페이마스터 서비스 제공업체에서 페이마스터 서비스 URL을 획득해야 합니다.Coinbase Developer Platform을 페이마스터 서비스 제공업체로 사용하겠습니다. 현재 Base 가스리스 캠페인의 일환으로 최대 $15,000의 가스 크레딧을 제공합니다.
ERC-7677 호환 페이마스터 제공업체다른 페이마스터 서비스 제공업체를 사용하는 경우 ERC-7677 호환 여부를 확인하세요.
Coinbase Developer Platform에 가입한 후 아래와 같이 온체인 도구 > 페이마스터로 이동하여 페이마스터 서비스 URL을 얻을 수 있습니다:
페이마스터 CDP
페이마스터 서비스를 위한 프록시를 생성해야 할까요?프런트엔드 클라이언트에서 노출/유출되는 것을 방지하기 위해 페이마스터 서비스 URL을 보호하는 프록시를 사용하는 것을 권장합니다.로컬 개발의 경우 페이마스터 서비스와 프록시에 동일한 URL을 사용할 수 있습니다.
페이마스터 서비스 URL을 얻은 후 컨트랙트 허용 목록을 설정할 수 있습니다. 이것은 페이마스터가 스폰서할 컨트랙트와 함수 호출의 목록입니다.
페이마스터 CDP 허용 목록
페이마스터 서비스와 컨트랙트 허용 목록 설정이 완료되었습니다. 이제 Base Account SDK를 설정할 차례입니다.
커스텀 고급 정책을 생성할 수도 있습니다!정책 시행에 더 많은 제어가 필요한 경우 추가 검증을 위한 willSponsor 함수를 생성할 수 있습니다.willSponsorCoinbase Developer Platform에 내장 정책 시행 기능이 있으므로 사용하지 않아도 될 가능성이 높지만, 필요한 경우 여전히 가능합니다.
2

Base Account SDK 설정

Base Account와 상호작용하기 위해 Base Account SDK를 설치하고 초기화합니다:

설치

npm install @base-org/account

SDK 초기화

import { createBaseAccountSDK, base } from '@base-org/account';

const sdk = createBaseAccountSDK({
  appName: '페이마스터 데모',
  appLogoUrl: 'https://base.org/logo.png',
  appChainIds: [base.constants.CHAIN_IDS.baseSepolia], // 메인넷은 base.constants.CHAIN_IDS.base 사용
});

const provider = sdk.getProvider();
3

페이마스터 서비스 기능으로 트랜잭션 전송

페이마스터 서비스를 설정했다면 이제 트랜잭션을 스폰서하기 위해 페이마스터 기능과 함께 wallet_sendCalls를 사용할 수 있습니다.
프록시 URL 전달위의 (1)단계에서 권장한 대로 앱의 백엔드에 프록시를 설정한 경우 생성한 프록시 URL을 전달합니다.

기본 스폰서 트랜잭션

wallet_sendCalls RPC 메서드를 사용하여 스폰서 트랜잭션을 전송하는 방법:
import { createBaseAccountSDK, getCryptoKeyAccount, base } from '@base-org/account';
import { numberToHex, encodeFunctionData, parseEther } from 'viem';

// 예제 NFT 컨트랙트 ABI
const nftABI = [
  {
    name: 'safeMint',
    type: 'function',
    stateMutability: 'nonpayable',
    inputs: [{ name: 'to', type: 'address' }],
    outputs: []
  }
] as const;

async function sendSponsoredTransaction() {
  const sdk = createBaseAccountSDK({
    appName: '페이마스터 데모',
    appLogoUrl: 'https://base.org/logo.png',
    appChainIds: [base.constants.CHAIN_IDS.baseSepolia],
  });

  const provider = sdk.getProvider();
  
  try {
    // 사용자 계정 가져오기
    const cryptoAccount = await getCryptoKeyAccount();
    const fromAddress = cryptoAccount?.account?.address;
    
    if (!fromAddress) {
      throw new Error('계정을 찾을 수 없습니다');
    }

    // 페이마스터 서비스 URL (프록시 URL 사용)
    const paymasterServiceUrl = process.env.NEXT_PUBLIC_PAYMASTER_PROXY_SERVER_URL;
    
    // 트랜잭션 콜 준비
    const nftAddress = '0x119Ea671030FBf79AB93b436D2E20af6ea469a19';
    const calls = [
      {
        to: nftAddress,
        value: '0x0',
        data: encodeFunctionData({
          abi: nftABI,
          functionName: 'safeMint',
          args: [fromAddress]
        })
      }
    ];

    // 페이마스터 기능과 함께 트랜잭션 전송
    const result = await provider.request({
      method: 'wallet_sendCalls',
      params: [{
        version: '1.0',
        chainId: numberToHex(base.constants.CHAIN_IDS.baseSepolia),
        from: fromAddress,
        calls: calls,
        capabilities: {
          paymasterService: {
            url: paymasterServiceUrl
          }
        }
      }]
    });

    console.log('Sponsored transaction sent:', result);
    return result;
  } catch (error) {
    console.error('Sponsored transaction failed:', error);
    throw error;
  }
}

다중 스폰서 트랜잭션

여러 트랜잭션을 배치로 묶어 모두 스폰서할 수도 있습니다:
async function sendMultipleSponsoredTransactions() {
  const sdk = createBaseAccountSDK({
    appName: '페이마스터 데모',
    appLogoUrl: 'https://base.org/logo.png',
    appChainIds: [base.constants.CHAIN_IDS.baseSepolia],
  });

  const provider = sdk.getProvider();
  const cryptoAccount = await getCryptoKeyAccount();
  const fromAddress = cryptoAccount?.account?.address;

  const paymasterServiceUrl = process.env.NEXT_PUBLIC_PAYMASTER_PROXY_SERVER_URL;

  // 단일 스폰서 트랜잭션에서 여러 콜
  const calls = [
    {
      to: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
      value: numberToHex(parseEther('0.001')),
      data: '0x' // 간단한 ETH 전송
    },
    {
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f6E456',
      value: numberToHex(parseEther('0.001')),
      data: '0x' // 다른 ETH 전송
    }
  ];

  const result = await provider.request({
    method: 'wallet_sendCalls',
    params: [{
      version: '1.0',
      chainId: numberToHex(base.constants.CHAIN_IDS.baseSepolia),
      from: fromAddress,
      calls: calls,
      capabilities: {
        paymasterService: {
          url: paymasterServiceUrl
        }
      }
    }]
  });

  return result;
}

페이마스터 기능 확인

스폰서 트랜잭션을 전송하기 전에 지갑이 페이마스터 서비스를 지원하는지 확인할 수 있습니다:
async function checkPaymasterSupport() {
  const sdk = createBaseAccountSDK({
    appName: '페이마스터 데모',
    appLogoUrl: 'https://base.org/logo.png',
    appChainIds: [base.constants.CHAIN_IDS.baseSepolia],
  });

  const provider = sdk.getProvider();
  const cryptoAccount = await getCryptoKeyAccount();
  const address = cryptoAccount?.account?.address;

  try {
    const capabilities = await provider.request({
      method: 'wallet_getCapabilities',
      params: [address]
    });

    const baseCapabilities = capabilities[base.constants.CHAIN_IDS.baseSepolia];
    
    if (baseCapabilities?.paymasterService?.supported) {
      console.log('페이마스터 서비스가 지원됩니다');
      return true;
    } else {
      console.log('페이마스터 서비스가 지원되지 않습니다');
      return false;
    }
  } catch (error) {
    console.error('Failed to check paymaster capabilities:', error);
    return false;
  }
}
이것으로 완료됩니다! Base Account가 나머지를 처리합니다. 페이마스터 서비스가 트랜잭션을 스폰서할 수 있다면 Base Account UI에서 사용자에게 트랜잭션이 스폰서됨을 표시합니다.